From: Junio C Hamano Date: Wed, 23 Mar 2011 04:38:50 +0000 (-0700) Subject: Merge branch 'mg/rev-list-one-side-only' X-Git-Tag: v1.7.5-rc0~36 X-Git-Url: https://git.lorimer.id.au/gitweb.git/diff_plain/aeb2aaa7712f7af8237d5bceb725a7db8c2d4620?ds=inline;hp=-c Merge branch 'mg/rev-list-one-side-only' * mg/rev-list-one-side-only: git-log: put space after commit mark t6007: test rev-list --cherry log --cherry: a synonym rev-list: documentation and test for --cherry-mark revision.c: introduce --cherry-mark rev-list/log: factor out revision mark generation rev-list: --left/right-only are mutually exclusive rev-list: documentation and test for --left/right-only t6007: Make sure we test --cherry-pick revlist.c: introduce --left/right-only for unsymmetric picking --- aeb2aaa7712f7af8237d5bceb725a7db8c2d4620 diff --combined Documentation/git-rev-list.txt index 5ce4d7fd0b,8a891ca68d..b08dfbc3c4 --- a/Documentation/git-rev-list.txt +++ b/Documentation/git-rev-list.txt @@@ -31,6 -31,9 +31,9 @@@ SYNOPSI [ \--parents ] [ \--timestamp ] [ \--left-right ] + [ \--left-only ] + [ \--right-only ] + [ \--cherry-mark ] [ \--cherry-pick ] [ \--encoding[=] ] [ \--(author|committer|grep)= ] @@@ -105,6 -108,16 +108,6 @@@ include::rev-list-options.txt[ include::pretty-formats.txt[] - -Author ------- -Written by Linus Torvalds - -Documentation --------------- -Documentation by David Greaves, Junio C Hamano, Jonas Fonseca -and the git-list . - GIT --- Part of the linkgit:git[1] suite diff --combined Documentation/rev-list-options.txt index 09860de9c2,95d209c11d..5c6850f048 --- a/Documentation/rev-list-options.txt +++ b/Documentation/rev-list-options.txt @@@ -1,17 -1,171 +1,17 @@@ -Commit Formatting -~~~~~~~~~~~~~~~~~ - -ifdef::git-rev-list[] -Using these options, linkgit:git-rev-list[1] will act similar to the -more specialized family of commit log tools: linkgit:git-log[1], -linkgit:git-show[1], and linkgit:git-whatchanged[1] -endif::git-rev-list[] - -include::pretty-options.txt[] - ---relative-date:: - - Synonym for `--date=relative`. - ---date=(relative|local|default|iso|rfc|short|raw):: - - Only takes effect for dates shown in human-readable format, such - as when using "--pretty". `log.date` config variable sets a default - value for log command's --date option. -+ -`--date=relative` shows dates relative to the current time, -e.g. "2 hours ago". -+ -`--date=local` shows timestamps in user's local timezone. -+ -`--date=iso` (or `--date=iso8601`) shows timestamps in ISO 8601 format. -+ -`--date=rfc` (or `--date=rfc2822`) shows timestamps in RFC 2822 -format, often found in E-mail messages. -+ -`--date=short` shows only date but not time, in `YYYY-MM-DD` format. -+ -`--date=raw` shows the date in the internal raw git format `%s %z` format. -+ -`--date=default` shows timestamps in the original timezone -(either committer's or author's). - -ifdef::git-rev-list[] ---header:: - - Print the contents of the commit in raw-format; each record is - separated with a NUL character. -endif::git-rev-list[] - ---parents:: - - Print also the parents of the commit (in the form "commit parent..."). - Also enables parent rewriting, see 'History Simplification' below. - ---children:: - - Print also the children of the commit (in the form "commit child..."). - Also enables parent rewriting, see 'History Simplification' below. - -ifdef::git-rev-list[] ---timestamp:: - Print the raw commit timestamp. -endif::git-rev-list[] - ---left-right:: - - Mark which side of a symmetric diff a commit is reachable from. - Commits from the left side are prefixed with `<` and those from - the right with `>`. If combined with `--boundary`, those - commits are prefixed with `-`. -+ -For example, if you have this topology: -+ ------------------------------------------------------------------------ - y---b---b branch B - / \ / - / . - / / \ - o---x---a---a branch A ------------------------------------------------------------------------ -+ -you would get an output like this: -+ ------------------------------------------------------------------------ - $ git rev-list --left-right --boundary --pretty=oneline A...B - - >bbbbbbb... 3rd on b - >bbbbbbb... 2nd on b - :: - Limit the number of commits output. + Limit the number of commits to output. --skip=:: @@@ -151,6 -305,11 +151,11 @@@ ifdef::git-rev-list[ to /dev/null as the output does not have to be formatted. endif::git-rev-list[] + --cherry-mark:: + + Like `--cherry-pick` (see below) but mark equivalent commits + with `=` rather than omitting them, and inequivalent ones with `+`. + --cherry-pick:: Omit any commit that introduces the same change as @@@ -165,6 -324,27 +170,27 @@@ from the other branch (for example, "3r from branch A). With this option, such pairs of commits are excluded from the output. + --left-only:: + --right-only:: + + List only commits on the respective side of a symmetric range, + i.e. only those which would be marked `<` resp. `>` by + `--left-right`. + + + For example, `--cherry-pick --right-only A...B` omits those + commits from `B` which are in `A` or are patch-equivalent to a commit in + `A`. In other words, this lists the `{plus}` commits from `git cherry A B`. + More precisely, `--cherry-pick --right-only --no-merges` gives the exact + list. + + --cherry:: + + A synonym for `--right-only --cherry-mark --no-merges`; useful to + limit the output to the commits on our side and mark those that + have been applied to the other side of a forked history with + `git log --cherry upstream...mybranch`, similar to + `git cherry upstream mybranch`. + -g:: --walk-reflogs:: @@@ -581,158 -761,3 +607,158 @@@ These options are mostly targeted for p --do-walk:: Overrides a previous --no-walk. + +Commit Formatting +~~~~~~~~~~~~~~~~~ + +ifdef::git-rev-list[] +Using these options, linkgit:git-rev-list[1] will act similar to the +more specialized family of commit log tools: linkgit:git-log[1], +linkgit:git-show[1], and linkgit:git-whatchanged[1] +endif::git-rev-list[] + +include::pretty-options.txt[] + +--relative-date:: + + Synonym for `--date=relative`. + +--date=(relative|local|default|iso|rfc|short|raw):: + + Only takes effect for dates shown in human-readable format, such + as when using "--pretty". `log.date` config variable sets a default + value for log command's --date option. ++ +`--date=relative` shows dates relative to the current time, +e.g. "2 hours ago". ++ +`--date=local` shows timestamps in user's local timezone. ++ +`--date=iso` (or `--date=iso8601`) shows timestamps in ISO 8601 format. ++ +`--date=rfc` (or `--date=rfc2822`) shows timestamps in RFC 2822 +format, often found in E-mail messages. ++ +`--date=short` shows only date but not time, in `YYYY-MM-DD` format. ++ +`--date=raw` shows the date in the internal raw git format `%s %z` format. ++ +`--date=default` shows timestamps in the original timezone +(either committer's or author's). + +ifdef::git-rev-list[] +--header:: + + Print the contents of the commit in raw-format; each record is + separated with a NUL character. +endif::git-rev-list[] + +--parents:: + + Print also the parents of the commit (in the form "commit parent..."). + Also enables parent rewriting, see 'History Simplification' below. + +--children:: + + Print also the children of the commit (in the form "commit child..."). + Also enables parent rewriting, see 'History Simplification' below. + +ifdef::git-rev-list[] +--timestamp:: + Print the raw commit timestamp. +endif::git-rev-list[] + +--left-right:: + + Mark which side of a symmetric diff a commit is reachable from. + Commits from the left side are prefixed with `<` and those from + the right with `>`. If combined with `--boundary`, those + commits are prefixed with `-`. ++ +For example, if you have this topology: ++ +----------------------------------------------------------------------- + y---b---b branch B + / \ / + / . + / / \ + o---x---a---a branch A +----------------------------------------------------------------------- ++ +you would get an output like this: ++ +----------------------------------------------------------------------- + $ git rev-list --left-right --boundary --pretty=oneline A...B + + >bbbbbbb... 3rd on b + >bbbbbbb... 2nd on b + len - 1; i >= 0; i--) + if (sb->buf[i] == '\n') + break; + line_len = sb->len - (i+1); for (i = 0; i < len; i++) { int ch = line[i]; - if (non_ascii(ch)) + if (non_ascii(ch) || ch == '\n') goto needquote; if ((i + 1 < len) && (ch == '=' && line[i+1] == '?')) goto needquote; } - strbuf_add(sb, line, len); + strbuf_add_wrapped_bytes(sb, line, len, 0, 1, max_length - line_len); return; needquote: strbuf_grow(sb, len * 3 + strlen(encoding) + 100); strbuf_addf(sb, "=?%s?q?", encoding); - for (i = last = 0; i < len; i++) { + line_len += strlen(encoding) + 5; /* 5 for =??q? */ + for (i = 0; i < len; i++) { unsigned ch = line[i] & 0xFF; + + if (line_len >= max_length - 2) { + strbuf_addf(sb, "?=\n =?%s?q?", encoding); + line_len = strlen(encoding) + 5 + 1; /* =??q? plus SP */ + } + /* * We encode ' ' using '=20' even though rfc2047 * allows using '_' for readability. Unfortunately, * many programs do not understand this and just * leave the underscore in place. */ - if (is_rfc2047_special(ch) || ch == ' ') { - strbuf_add(sb, line + last, i - last); + if (is_rfc2047_special(ch) || ch == ' ' || ch == '\n') { strbuf_addf(sb, "=%02X", ch); - last = i + 1; + line_len += 3; + } + else { + strbuf_addch(sb, ch); + line_len++; } } - strbuf_add(sb, line + last, len - last); strbuf_addstr(sb, "?="); } @@@ -876,11 -859,7 +876,7 @@@ static size_t format_commit_one(struct c->abbrev_parent_hashes.off; return 1; case 'm': /* left/right/bottom */ - strbuf_addch(sb, (commit->object.flags & BOUNDARY) - ? '-' - : (commit->object.flags & SYMMETRIC_LEFT) - ? '<' - : '>'); + strbuf_addstr(sb, get_revision_mark(NULL, commit)); return 1; case 'd': format_decoration(sb, commit); @@@ -1123,10 -1102,11 +1119,10 @@@ void pp_title_line(enum cmit_fmt fmt const char *encoding, int need_8bit_cte) { - const char *line_separator = (fmt == CMIT_FMT_EMAIL) ? "\n " : " "; struct strbuf title; strbuf_init(&title, 80); - *msg_p = format_subject(&title, *msg_p, line_separator); + *msg_p = format_subject(&title, *msg_p, " "); strbuf_grow(sb, title.len + 1024); if (subject) { diff --combined revision.c index 86d2470489,626f6a23d1..e96c281d1f --- a/revision.c +++ b/revision.c @@@ -323,7 -323,7 +323,7 @@@ static int rev_compare_tree(struct rev_ * tagged commit by specifying both --simplify-by-decoration * and pathspec. */ - if (!revs->prune_data) + if (!revs->prune_data.nr) return REV_TREE_SAME; } @@@ -535,6 -535,7 +535,7 @@@ static void cherry_pick_list(struct com int left_count = 0, right_count = 0; int left_first; struct patch_ids ids; + unsigned cherry_flag; /* First count the commits on the left and on the right */ for (p = list; p; p = p->next) { @@@ -553,7 -554,11 +554,7 @@@ left_first = left_count < right_count; init_patch_ids(&ids); - if (revs->diffopt.nr_paths) { - ids.diffopts.nr_paths = revs->diffopt.nr_paths; - ids.diffopts.paths = revs->diffopt.paths; - ids.diffopts.pathlens = revs->diffopt.pathlens; - } + ids.diffopts.pathspec = revs->diffopt.pathspec; /* Compute patch-ids for one side */ for (p = list; p; p = p->next) { @@@ -572,6 -577,9 +573,9 @@@ commit->util = add_commit_patch_id(commit, &ids); } + /* either cherry_mark or cherry_pick are true */ + cherry_flag = revs->cherry_mark ? PATCHSAME : SHOWN; + /* Check the other side */ for (p = list; p; p = p->next) { struct commit *commit = p->item; @@@ -594,7 -602,7 +598,7 @@@ if (!id) continue; id->seen = 1; - commit->object.flags |= SHOWN; + commit->object.flags |= cherry_flag; } /* Now check the original side for seen ones */ @@@ -606,7 -614,7 +610,7 @@@ if (!ent) continue; if (ent->seen) - commit->object.flags |= SHOWN; + commit->object.flags |= cherry_flag; commit->util = NULL; } @@@ -729,6 -737,23 +733,23 @@@ static struct commit_list *collect_bott return bottom; } + /* Assumes either left_only or right_only is set */ + static void limit_left_right(struct commit_list *list, struct rev_info *revs) + { + struct commit_list *p; + + for (p = list; p; p = p->next) { + struct commit *commit = p->item; + + if (revs->right_only) { + if (commit->object.flags & SYMMETRIC_LEFT) + commit->object.flags |= SHOWN; + } else /* revs->left_only is set */ + if (!(commit->object.flags & SYMMETRIC_LEFT)) + commit->object.flags |= SHOWN; + } + } + static int limit_list(struct rev_info *revs) { int slop = SLOP; @@@ -781,9 -806,12 +802,12 @@@ show(revs, newlist); show_early_output = NULL; } - if (revs->cherry_pick) + if (revs->cherry_pick || revs->cherry_mark) cherry_pick_list(newlist, revs); + if (revs->left_only || revs->right_only) + limit_left_right(newlist, revs); + if (bottom) { limit_to_ancestry(bottom, newlist); free_commit_list(bottom); @@@ -969,7 -997,7 +993,7 @@@ static void prepare_show_merge(struct r struct cache_entry *ce = active_cache[i]; if (!ce_stage(ce)) continue; - if (ce_path_match(ce, revs->prune_data)) { + if (ce_path_match(ce, &revs->prune_data)) { prune_num++; prune = xrealloc(prune, sizeof(*prune) * prune_num); prune[prune_num-2] = ce->name; @@@ -979,8 -1007,7 +1003,8 @@@ ce_same_name(ce, active_cache[i+1])) i++; } - revs->prune_data = prune; + free_pathspec(&revs->prune_data); + init_pathspec(&revs->prune_data, prune); revs->limited = 1; } @@@ -1260,9 -1287,32 +1284,32 @@@ static int handle_revision_opt(struct r revs->boundary = 1; } else if (!strcmp(arg, "--left-right")) { revs->left_right = 1; + } else if (!strcmp(arg, "--left-only")) { + if (revs->right_only) + die("--left-only is incompatible with --right-only" + " or --cherry"); + revs->left_only = 1; + } else if (!strcmp(arg, "--right-only")) { + if (revs->left_only) + die("--right-only is incompatible with --left-only"); + revs->right_only = 1; + } else if (!strcmp(arg, "--cherry")) { + if (revs->left_only) + die("--cherry is incompatible with --left-only"); + revs->cherry_mark = 1; + revs->right_only = 1; + revs->no_merges = 1; + revs->limited = 1; } else if (!strcmp(arg, "--count")) { revs->count = 1; + } else if (!strcmp(arg, "--cherry-mark")) { + if (revs->cherry_pick) + die("--cherry-mark is incompatible with --cherry-pick"); + revs->cherry_mark = 1; + revs->limited = 1; /* needs limit_list() */ } else if (!strcmp(arg, "--cherry-pick")) { + if (revs->cherry_mark) + die("--cherry-pick is incompatible with --cherry-mark"); revs->cherry_pick = 1; revs->limited = 1; } else if (!strcmp(arg, "--objects")) { @@@ -1617,7 -1667,7 +1664,7 @@@ int setup_revisions(int argc, const cha } if (prune_data) - revs->prune_data = get_pathspec(revs->prefix, prune_data); + init_pathspec(&revs->prune_data, get_pathspec(revs->prefix, prune_data)); if (revs->def == NULL) revs->def = opt ? opt->def : NULL; @@@ -1648,13 -1698,13 +1695,13 @@@ if (revs->topo_order) revs->limited = 1; - if (revs->prune_data) { - diff_tree_setup_paths(revs->prune_data, &revs->pruning); + if (revs->prune_data.nr) { + diff_tree_setup_paths(revs->prune_data.raw, &revs->pruning); /* Can't prune commits with rename following: the paths change.. */ if (!DIFF_OPT_TST(&revs->diffopt, FOLLOW_RENAMES)) revs->prune = 1; if (!revs->full_diff) - diff_tree_setup_paths(revs->prune_data, &revs->diffopt); + diff_tree_setup_paths(revs->prune_data.raw, &revs->diffopt); } if (revs->combine_merges) revs->ignore_merges = 0; @@@ -2232,3 -2282,32 +2279,32 @@@ struct commit *get_revision(struct rev_ graph_update(revs->graph, c); return c; } + + char *get_revision_mark(const struct rev_info *revs, const struct commit *commit) + { + if (commit->object.flags & BOUNDARY) + return "-"; + else if (commit->object.flags & UNINTERESTING) + return "^"; + else if (commit->object.flags & PATCHSAME) + return "="; + else if (!revs || revs->left_right) { + if (commit->object.flags & SYMMETRIC_LEFT) + return "<"; + else + return ">"; + } else if (revs->graph) + return "*"; + else if (revs->cherry_mark) + return "+"; + return ""; + } + + void put_revision_mark(const struct rev_info *revs, const struct commit *commit) + { + char *mark = get_revision_mark(revs, commit); + if (!strlen(mark)) + return; + fputs(mark, stdout); + putchar(' '); + } diff --combined revision.h index 82509dd1d9,1c0abf0f58..ae948601f9 --- a/revision.h +++ b/revision.h @@@ -14,7 -14,8 +14,8 @@@ #define CHILD_SHOWN (1u<<6) #define ADDED (1u<<7) /* Parents already parsed and added? */ #define SYMMETRIC_LEFT (1u<<8) - #define ALL_REV_FLAGS ((1u<<9)-1) + #define PATCHSAME (1u<<9) + #define ALL_REV_FLAGS ((1u<<10)-1) #define DECORATE_SHORT_REFS 1 #define DECORATE_FULL_REFS 2 @@@ -34,7 -35,7 +35,7 @@@ struct rev_info /* Basic information */ const char *prefix; const char *def; - void *prune_data; + struct pathspec prune_data; unsigned int early_output; /* Traversal flags */ @@@ -59,6 -60,8 +60,8 @@@ boundary:2, count:1, left_right:1, + left_only:1, + right_only:1, rewrite_parents:1, print_parents:1, show_source:1, @@@ -66,6 -69,7 +69,7 @@@ reverse:1, reverse_output_stage:1, cherry_pick:1, + cherry_mark:1, bisect:1, ancestry_path:1, first_parent_only:1; @@@ -163,6 -167,8 +167,8 @@@ extern int handle_revision_arg(const ch extern int prepare_revision_walk(struct rev_info *revs); extern struct commit *get_revision(struct rev_info *revs); + extern char *get_revision_mark(const struct rev_info *revs, const struct commit *commit); + extern void put_revision_mark(const struct rev_info *revs, const struct commit *commit); extern void mark_parents_uninteresting(struct commit *commit); extern void mark_tree_uninteresting(struct tree *tree);