Skip to content

Commit

Permalink
revision.c: introduce --min-parents and --max-parents options
Browse files Browse the repository at this point in the history
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>
  • Loading branch information
Michael J Gruber authored and Junio C Hamano committed Mar 23, 2011
1 parent 8ee5059 commit ad5aeed
Show file tree
Hide file tree
Showing 5 changed files with 32 additions and 10 deletions.
2 changes: 1 addition & 1 deletion builtin/log.c
Original file line number Diff line number Diff line change
Expand Up @@ -1055,7 +1055,7 @@ int cmd_format_patch(int argc, const char **argv, const char *prefix)
rev.commit_format = CMIT_FMT_EMAIL;
rev.verbose_header = 1;
rev.diff = 1;
rev.no_merges = 1;
rev.max_parents = 1;
DIFF_OPT_SET(&rev.diffopt, RECURSIVE);
rev.subject_prefix = fmt_patch_subject_prefix;
memset(&s_r_opt, 0, sizeof(s_r_opt));
Expand Down
4 changes: 4 additions & 0 deletions builtin/rev-list.c
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,10 @@ static const char rev_list_usage[] =
" --min-age=<epoch>\n"
" --sparse\n"
" --no-merges\n"
" --min-parents=<n>\n"
" --no-min-parents\n"
" --max-parents=<n>\n"
" --no-max-parents\n"
" --remove-empty\n"
" --all\n"
" --branches\n"
Expand Down
4 changes: 4 additions & 0 deletions builtin/rev-parse.c
Original file line number Diff line number Diff line change
Expand Up @@ -48,6 +48,10 @@ static int is_rev_argument(const char *arg)
"--max-count=",
"--min-age=",
"--no-merges",
"--min-parents=",
"--no-min-parents",
"--max-parents=",
"--no-max-parents",
"--objects",
"--objects-edge",
"--parents",
Expand Down
28 changes: 21 additions & 7 deletions revision.c
Original file line number Diff line number Diff line change
Expand Up @@ -945,6 +945,7 @@ void init_revisions(struct rev_info *revs, const char *prefix)
revs->min_age = -1;
revs->skip_count = -1;
revs->max_count = -1;
revs->max_parents = -1;

revs->commit_format = CMIT_FMT_DEFAULT;

Expand Down Expand Up @@ -1280,9 +1281,17 @@ static int handle_revision_opt(struct rev_info *revs, int argc, const char **arg
} else if (!strcmp(arg, "--remove-empty")) {
revs->remove_empty_trees = 1;
} else if (!strcmp(arg, "--merges")) {
revs->merges_only = 1;
revs->min_parents = 2;
} else if (!strcmp(arg, "--no-merges")) {
revs->no_merges = 1;
revs->max_parents = 1;
} else if (!prefixcmp(arg, "--min-parents=")) {
revs->min_parents = atoi(arg+14);
} else if (!prefixcmp(arg, "--no-min-parents")) {
revs->min_parents = 0;
} else if (!prefixcmp(arg, "--max-parents=")) {
revs->max_parents = atoi(arg+14);
} else if (!prefixcmp(arg, "--no-max-parents")) {
revs->max_parents = -1;
} else if (!strcmp(arg, "--boundary")) {
revs->boundary = 1;
} else if (!strcmp(arg, "--left-right")) {
Expand All @@ -1301,7 +1310,7 @@ static int handle_revision_opt(struct rev_info *revs, int argc, const char **arg
die("--cherry is incompatible with --left-only");
revs->cherry_mark = 1;
revs->right_only = 1;
revs->no_merges = 1;
revs->max_parents = 1;
revs->limited = 1;
} else if (!strcmp(arg, "--count")) {
revs->count = 1;
Expand Down Expand Up @@ -2032,10 +2041,15 @@ enum commit_action get_commit_action(struct rev_info *revs, struct commit *commi
return commit_ignore;
if (revs->min_age != -1 && (commit->date > revs->min_age))
return commit_ignore;
if (revs->no_merges && commit->parents && commit->parents->next)
return commit_ignore;
if (revs->merges_only && !(commit->parents && commit->parents->next))
return commit_ignore;
if (revs->min_parents || (revs->max_parents >= 0)) {
int n = 0;
struct commit_list *p;
for (p = commit->parents; p; p = p->next)
n++;
if ((n < revs->min_parents) ||
((revs->max_parents >= 0) && (n > revs->max_parents)))
return commit_ignore;
}
if (!commit_match(commit, revs))
return commit_ignore;
if (revs->prune && revs->dense) {
Expand Down
4 changes: 2 additions & 2 deletions revision.h
Original file line number Diff line number Diff line change
Expand Up @@ -41,8 +41,6 @@ struct rev_info {
/* Traversal flags */
unsigned int dense:1,
prune:1,
no_merges:1,
merges_only:1,
no_walk:1,
show_all:1,
remove_empty_trees:1,
Expand Down Expand Up @@ -126,6 +124,8 @@ struct rev_info {
int max_count;
unsigned long max_age;
unsigned long min_age;
int min_parents;
int max_parents;

/* diff info for patches and for paths limiting */
struct diff_options diffopt;
Expand Down

0 comments on commit ad5aeed

Please sign in to comment.