From patchwork Thu Jul 30 00:27:33 2020 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Aaron Lipman X-Patchwork-Id: 11691975 Return-Path: Received: from mail.kernel.org (pdx-korg-mail-1.web.codeaurora.org [172.30.200.123]) by pdx-korg-patchwork-2.web.codeaurora.org (Postfix) with ESMTP id 16EEC722 for ; Thu, 30 Jul 2020 00:27:47 +0000 (UTC) Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by mail.kernel.org (Postfix) with ESMTP id E97252075D for ; Thu, 30 Jul 2020 00:27:46 +0000 (UTC) Authentication-Results: mail.kernel.org; dkim=pass (2048-bit key) header.d=gmail.com header.i=@gmail.com header.b="VfC5vtM6" Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1728184AbgG3A1q (ORCPT ); Wed, 29 Jul 2020 20:27:46 -0400 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:39060 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1726709AbgG3A1p (ORCPT ); Wed, 29 Jul 2020 20:27:45 -0400 Received: from mail-qt1-x843.google.com (mail-qt1-x843.google.com [IPv6:2607:f8b0:4864:20::843]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id 2837AC061794 for ; Wed, 29 Jul 2020 17:27:45 -0700 (PDT) Received: by mail-qt1-x843.google.com with SMTP id t23so15993839qto.3 for ; Wed, 29 Jul 2020 17:27:45 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20161025; h=from:to:cc:subject:date:message-id:in-reply-to:references :mime-version:content-transfer-encoding; bh=r/h64BdyCd+J/Ro7H5J45qdi3RzYwz6wZEv+LQaygsA=; b=VfC5vtM65euv/LMVAifMYRcHsYqrg/y49I7DLo3/H2AmdQOpBnge5AJLReua1QYsXS Ra6EL/gAJywB61iHs6lEYaU7JPsvH4SNDhcKrg9KaJwl29eHgSDjL3YNF5b3a8tjO3CR zciSOW+Cs41vesCZ1ylHhmhpjz3sAm85mL3xM+PObCnv6Y5ra2YlfCWbjU1/FCC4rN1x IM/rDrxXEUwb/RG+FiGiYkvYkyodlJUQK5TJerEgzwGsi0qukchRo5qoOYs0Ayb73Mi2 9vYlq0Sx+xGKo7UAqekk2T6bEMjL5egcP9ZeD0gMF4DmRabQvDMJWeYh67F4zql3U3lp 84vQ== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-gm-message-state:from:to:cc:subject:date:message-id:in-reply-to :references:mime-version:content-transfer-encoding; bh=r/h64BdyCd+J/Ro7H5J45qdi3RzYwz6wZEv+LQaygsA=; b=rPkI8Y7KfPM5wkAhftmLveHsqnOTLBbH2OCFODZDtsspjgezeVb8mlwnF8csXclROA uv3dadnxIJbbBZtqftAGSjbc+TAL5+k821DfrKkxrMD4K1R8YKsvGy2rINkv56SaKy+Z 8qSMUVuVQVn2+Xgz1LvgIXlJjiEZmby6tbY/9adCeyIzV/I02MPJy+Uv0Z3jq+zLIQLI e7CSbjr05z591yiRCsnh8usQLO8dskMO40+hmy0SAddfXq67Oi0GmhADZOynEBhyYXP9 xFPdRhWhp4hL7gzLXpj4EDupgYQuK/rl/XKsVM9H4rpT+9Nv6jNCTttB+JectMqCfk5l 6T5A== X-Gm-Message-State: AOAM530ZJ5oKtqwmS9cJuzjvDwNHTZNR/jAqvjAPsBe2HeBUdHWtZAuC fIjqOpSnpu8xulO945Ev4JZoP27Jcxo= X-Google-Smtp-Source: ABdhPJzMZWNHbwo6H0+5SzMdyS16vEYXHla4qx0Bc6HUE+tg0T8UdMPqlE3dde2+9NED2ob+EQmdqA== X-Received: by 2002:ac8:564d:: with SMTP id 13mr482561qtt.101.1596068863913; Wed, 29 Jul 2020 17:27:43 -0700 (PDT) Received: from localhost.localdomain (c-98-229-3-81.hsd1.vt.comcast.net. [98.229.3.81]) by smtp.gmail.com with ESMTPSA id m32sm3239391qtd.94.2020.07.29.17.27.43 (version=TLS1_2 cipher=ECDHE-ECDSA-AES128-GCM-SHA256 bits=128/128); Wed, 29 Jul 2020 17:27:43 -0700 (PDT) From: Aaron Lipman To: git@vger.kernel.org Cc: Aaron Lipman Subject: [PATCH v2 1/3] rev-list: allow bisect and first-parent flags Date: Wed, 29 Jul 2020 20:27:33 -0400 Message-Id: <20200730002735.87655-2-alipman88@gmail.com> X-Mailer: git-send-email 2.24.3 (Apple Git-128) In-Reply-To: <20200730002735.87655-1-alipman88@gmail.com> References: <20200730002735.87655-1-alipman88@gmail.com> MIME-Version: 1.0 Sender: git-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: git@vger.kernel.org Add first_parent_only parameter to find_bisection(), removing the barrier that prevented combining the --bisect and --first-parent flags when using git rev-list Signed-off-by: Aaron Lipman Based-on-patch-by: Tiago Botelho --- Documentation/rev-list-options.txt | 7 ++--- bisect.c | 28 ++++++++++++------- bisect.h | 2 +- builtin/rev-list.c | 2 +- revision.c | 3 -- t/t6000-rev-list-misc.sh | 4 +-- t/t6002-rev-list-bisect.sh | 45 ++++++++++++++++++++++++++++++ 7 files changed, 70 insertions(+), 21 deletions(-) diff --git a/Documentation/rev-list-options.txt b/Documentation/rev-list-options.txt index b01b2b6773..d3117ce51b 100644 --- a/Documentation/rev-list-options.txt +++ b/Documentation/rev-list-options.txt @@ -128,8 +128,7 @@ parents) and `--max-parents=-1` (negative numbers denote no upper limit). because merges into a topic branch tend to be only about adjusting to updated upstream from time to time, and this option allows you to ignore the individual commits - brought in to your history by such a merge. Cannot be - combined with --bisect. + brought in to your history by such a merge. --not:: Reverses the meaning of the '{caret}' prefix (or lack thereof) @@ -207,7 +206,7 @@ ifndef::git-rev-list[] Pretend as if the bad bisection ref `refs/bisect/bad` was listed and as if it was followed by `--not` and the good bisection refs `refs/bisect/good-*` on the command - line. Cannot be combined with --first-parent. + line. endif::git-rev-list[] --stdin:: @@ -743,7 +742,7 @@ outputs 'midpoint', the output of the two commands would be of roughly the same length. Finding the change which introduces a regression is thus reduced to a binary search: repeatedly generate and test new 'midpoint's until the commit chain is of length -one. Cannot be combined with --first-parent. +one. --bisect-vars:: This calculates the same as `--bisect`, except that refs in diff --git a/bisect.c b/bisect.c index d5e830410f..a11fdb1473 100644 --- a/bisect.c +++ b/bisect.c @@ -88,15 +88,16 @@ static inline void weight_set(struct commit_list *elem, int weight) **commit_weight_at(&commit_weight, elem->item) = weight; } -static int count_interesting_parents(struct commit *commit) +static int count_interesting_parents(struct commit *commit, int first_parent_only) { struct commit_list *p; int count; for (count = 0, p = commit->parents; p; p = p->next) { - if (p->item->object.flags & UNINTERESTING) - continue; - count++; + if (!(p->item->object.flags & UNINTERESTING)) + count++; + if (first_parent_only) + break; } return count; } @@ -259,7 +260,7 @@ static struct commit_list *best_bisection_sorted(struct commit_list *list, int n */ static struct commit_list *do_find_bisection(struct commit_list *list, int nr, int *weights, - int find_all) + int find_all, int first_parent_only) { int n, counted; struct commit_list *p; @@ -271,7 +272,7 @@ static struct commit_list *do_find_bisection(struct commit_list *list, unsigned flags = commit->object.flags; *commit_weight_at(&commit_weight, p->item) = &weights[n++]; - switch (count_interesting_parents(commit)) { + switch (count_interesting_parents(commit, first_parent_only)) { case 0: if (!(flags & TREESAME)) { weight_set(p, 1); @@ -314,6 +315,8 @@ static struct commit_list *do_find_bisection(struct commit_list *list, continue; if (weight(p) != -2) continue; + if (first_parent_only) + BUG("shouldn't be calling count-distance in fp mode"); weight_set(p, count_distance(p)); clear_distance(list); @@ -332,7 +335,10 @@ static struct commit_list *do_find_bisection(struct commit_list *list, if (0 <= weight(p)) continue; - for (q = p->item->parents; q; q = q->next) { + + for (q = p->item->parents; + q; + q = first_parent_only ? NULL : q->next) { if (q->item->object.flags & UNINTERESTING) continue; if (0 <= weight(q)) @@ -370,7 +376,7 @@ static struct commit_list *do_find_bisection(struct commit_list *list, } void find_bisection(struct commit_list **commit_list, int *reaches, - int *all, int find_all) + int *all, int find_all, int first_parent_only) { int nr, on_list; struct commit_list *list, *p, *best, *next, *last; @@ -406,7 +412,7 @@ void find_bisection(struct commit_list **commit_list, int *reaches, weights = xcalloc(on_list, sizeof(*weights)); /* Do the real work of finding bisection commit. */ - best = do_find_bisection(list, nr, weights, find_all); + best = do_find_bisection(list, nr, weights, find_all, first_parent_only); if (best) { if (!find_all) { list->item = best->item; @@ -991,6 +997,7 @@ enum bisect_error bisect_next_all(struct repository *r, const char *prefix, int enum bisect_error res = BISECT_OK; struct object_id *bisect_rev; char *steps_msg; + int first_parent_only = 0; /* TODO: pass --first-parent flag from git bisect start */ read_bisect_terms(&term_bad, &term_good); if (read_bisect_refs()) @@ -1001,11 +1008,12 @@ enum bisect_error bisect_next_all(struct repository *r, const char *prefix, int return res; bisect_rev_setup(r, &revs, prefix, "%s", "^%s", 1); + revs.first_parent_only = first_parent_only; revs.limited = 1; bisect_common(&revs); - find_bisection(&revs.commits, &reaches, &all, !!skipped_revs.nr); + find_bisection(&revs.commits, &reaches, &all, !!skipped_revs.nr, first_parent_only); revs.commits = managed_skipped(revs.commits, &tried); if (!revs.commits) { diff --git a/bisect.h b/bisect.h index 8bad8d8391..a63af0505f 100644 --- a/bisect.h +++ b/bisect.h @@ -12,7 +12,7 @@ struct repository; * best commit, as chosen by `find_all`. */ void find_bisection(struct commit_list **list, int *reaches, int *all, - int find_all); + int find_all, int first_parent_only); struct commit_list *filter_skipped(struct commit_list *list, struct commit_list **tried, diff --git a/builtin/rev-list.c b/builtin/rev-list.c index f520111eda..d1a14596b2 100644 --- a/builtin/rev-list.c +++ b/builtin/rev-list.c @@ -638,7 +638,7 @@ int cmd_rev_list(int argc, const char **argv, const char *prefix) if (bisect_list) { int reaches, all; - find_bisection(&revs.commits, &reaches, &all, bisect_find_all); + find_bisection(&revs.commits, &reaches, &all, bisect_find_all, revs.first_parent_only); if (bisect_show_vars) return show_bisect_vars(&info, reaches, all); diff --git a/revision.c b/revision.c index 6aa7f4f567..f0ad2603c1 100644 --- a/revision.c +++ b/revision.c @@ -2869,9 +2869,6 @@ int setup_revisions(int argc, const char **argv, struct rev_info *revs, struct s if (!revs->reflog_info && revs->grep_filter.use_reflog_filter) die("cannot use --grep-reflog without --walk-reflogs"); - if (revs->first_parent_only && revs->bisect) - die(_("--first-parent is incompatible with --bisect")); - if (revs->line_level_traverse && (revs->diffopt.output_format & ~(DIFF_FORMAT_PATCH | DIFF_FORMAT_NO_OUTPUT))) die(_("-L does not yet support diff formats besides -p and -s")); diff --git a/t/t6000-rev-list-misc.sh b/t/t6000-rev-list-misc.sh index 3dc1ad8f71..26e3533562 100755 --- a/t/t6000-rev-list-misc.sh +++ b/t/t6000-rev-list-misc.sh @@ -125,8 +125,8 @@ test_expect_success 'rev-list can negate index objects' ' test_cmp expect actual ' -test_expect_success '--bisect and --first-parent can not be combined' ' - test_must_fail git rev-list --bisect --first-parent HEAD +test_expect_success '--bisect and --first-parent can be combined' ' + git rev-list --bisect --first-parent HEAD ' test_expect_success '--header shows a NUL after each commit' ' diff --git a/t/t6002-rev-list-bisect.sh b/t/t6002-rev-list-bisect.sh index a661408038..7fc0f75ca5 100755 --- a/t/t6002-rev-list-bisect.sh +++ b/t/t6002-rev-list-bisect.sh @@ -263,4 +263,49 @@ test_expect_success 'rev-parse --bisect can default to good/bad refs' ' test_cmp expect.sorted actual.sorted ' +test_output_expect_success "--bisect --first-parent" 'git rev-list --bisect --first-parent E ^F' < expect.unsorted < expect && +git rev-list --bisect-all --first-parent E ^F > actual && +test_cmp actual expect +' + test_done