@matheusbsbs / matheus-bagliano / commits / ad5aeeded3
Fork 0

revision.c: introduce --min-parents and --max-parents options

Introduce --min-parents and --max-parents options which limit the revisions to those commits which have at least (or at most) that many commits, where negative arguments for --max-parents= denote infinity (i.e. no upper limit). In particular: --max-parents=1 is the same as --no-merges; --min-parents=2 is the same as --merges; --max-parents=0 shows only roots; and --min-parents=3 shows only octopus merges Using --min-parents=n and --max-parents=m with n>m gives you what you ask for (i.e. nothing) for obvious reasons, just like when you give --merges (show only merge commits) and --no-merges (show only non-merge commits) at the same time. Also, introduce --no-min-parents and --no-max-parents to do the obvious thing for convenience. We compute the number of parents only when we limit by that, so there is no performance impact when there are no limiters. Signed-off-by: Michael J Gruber <git@drmicha.warpmail.net> Signed-off-by: Junio C Hamano <gitster@pobox.com>

Michael J Gruber committed Mar 21, 2011 at 11:14 UTC ad5aeeded3295589b2573b143f754762a56f8f82
5 files changed +32 -10
builtin/log.c
+1 -1
@@ -1055,7 +1055,7 @@ int cmd_format_patch(int argc, const char **argv, const char *prefix)
1055 rev.commit_format = CMIT_FMT_EMAIL;
1056 rev.verbose_header = 1;
1057 rev.diff = 1;
1058 - rev.no_merges = 1;
1058 + rev.max_parents = 1;
1059 DIFF_OPT_SET(&rev.diffopt, RECURSIVE);
1060 rev.subject_prefix = fmt_patch_subject_prefix;
1061 memset(&s_r_opt, 0, sizeof(s_r_opt));
builtin/rev-list.c
+4
@@ -16,6 +16,10 @@ static const char rev_list_usage[] =
16 " --min-age=<epoch>\n"
17 " --sparse\n"
18 " --no-merges\n"
19 +" --min-parents=<n>\n"
20 +" --no-min-parents\n"
21 +" --max-parents=<n>\n"
22 +" --no-max-parents\n"
23 " --remove-empty\n"
24 " --all\n"
25 " --branches\n"
builtin/rev-parse.c
+4
@@ -48,6 +48,10 @@ static int is_rev_argument(const char *arg)
48 "--max-count=",
49 "--min-age=",
50 "--no-merges",
51 + "--min-parents=",
52 + "--no-min-parents",
53 + "--max-parents=",
54 + "--no-max-parents",
55 "--objects",
56 "--objects-edge",
57 "--parents",
revision.c
+21 -7
@@ -945,6 +945,7 @@ void init_revisions(struct rev_info *revs, const char *prefix)
945 revs->min_age = -1;
946 revs->skip_count = -1;
947 revs->max_count = -1;
948 + revs->max_parents = -1;
949
950 revs->commit_format = CMIT_FMT_DEFAULT;
951
@@ -1280,9 +1281,17 @@ static int handle_revision_opt(struct rev_info *revs, int argc, const char **arg
1281 } else if (!strcmp(arg, "--remove-empty")) {
1282 revs->remove_empty_trees = 1;
1283 } else if (!strcmp(arg, "--merges")) {
1283 - revs->merges_only = 1;
1284 + revs->min_parents = 2;
1285 } else if (!strcmp(arg, "--no-merges")) {
1285 - revs->no_merges = 1;
1286 + revs->max_parents = 1;
1287 + } else if (!prefixcmp(arg, "--min-parents=")) {
1288 + revs->min_parents = atoi(arg+14);
1289 + } else if (!prefixcmp(arg, "--no-min-parents")) {
1290 + revs->min_parents = 0;
1291 + } else if (!prefixcmp(arg, "--max-parents=")) {
1292 + revs->max_parents = atoi(arg+14);
1293 + } else if (!prefixcmp(arg, "--no-max-parents")) {
1294 + revs->max_parents = -1;
1295 } else if (!strcmp(arg, "--boundary")) {
1296 revs->boundary = 1;
1297 } else if (!strcmp(arg, "--left-right")) {
@@ -1301,7 +1310,7 @@ static int handle_revision_opt(struct rev_info *revs, int argc, const char **arg
1310 die("--cherry is incompatible with --left-only");
1311 revs->cherry_mark = 1;
1312 revs->right_only = 1;
1304 - revs->no_merges = 1;
1313 + revs->max_parents = 1;
1314 revs->limited = 1;
1315 } else if (!strcmp(arg, "--count")) {
1316 revs->count = 1;
@@ -2032,10 +2041,15 @@ enum commit_action get_commit_action(struct rev_info *revs, struct commit *commi
2041 return commit_ignore;
2042 if (revs->min_age != -1 && (commit->date > revs->min_age))
2043 return commit_ignore;
2035 - if (revs->no_merges && commit->parents && commit->parents->next)
2036 - return commit_ignore;
2037 - if (revs->merges_only && !(commit->parents && commit->parents->next))
2038 - return commit_ignore;
2044 + if (revs->min_parents || (revs->max_parents >= 0)) {
2045 + int n = 0;
2046 + struct commit_list *p;
2047 + for (p = commit->parents; p; p = p->next)
2048 + n++;
2049 + if ((n < revs->min_parents) ||
2050 + ((revs->max_parents >= 0) && (n > revs->max_parents)))
2051 + return commit_ignore;
2052 + }
2053 if (!commit_match(commit, revs))
2054 return commit_ignore;
2055 if (revs->prune && revs->dense) {
revision.h
+2 -2
@@ -41,8 +41,6 @@ struct rev_info {
41 /* Traversal flags */
42 unsigned int dense:1,
43 prune:1,
44 - no_merges:1,
45 - merges_only:1,
44 no_walk:1,
45 show_all:1,
46 remove_empty_trees:1,
@@ -126,6 +124,8 @@ struct rev_info {
124 int max_count;
125 unsigned long max_age;
126 unsigned long min_age;
127 + int min_parents;
128 + int max_parents;
129
130 /* diff info for patches and for paths limiting */
131 struct diff_options diffopt;