diff: --{rotate,skip}-to=<path>

In the implementation of "git difftool", there is a case where the
user wants to start viewing the diffs at a specific path and
continue on to the rest, optionally wrapping around to the
beginning.  Since it is somewhat cumbersome to implement such a
feature as a post-processing step of "git diff" output, let's
support it internally with two new options.

 - "git diff --rotate-to=C", when the resulting patch would show
   paths A B C D E without the option, would "rotate" the paths to
   shows patch to C D E A B instead.  It is an error when there is
   no patch for C is shown.

 - "git diff --skip-to=C" would instead "skip" the paths before C,
   and shows patch to C D E.  Again, it is an error when there is no
   patch for C is shown.

 - "git log [-p]" also accepts these two options, but it is not an
   error if there is no change to the specified path.  Instead, the
   set of output paths are rotated or skipped to the specified path
   or the first path that sorts after the specified path.

Signed-off-by: Junio C Hamano <gitster@pobox.com>
This commit is contained in:
Junio C Hamano
2021-02-11 11:57:50 -08:00
parent c6102b7585
commit 1eb4136ac2
12 changed files with 197 additions and 1 deletions

21
diff.c
View File

@ -5348,6 +5348,19 @@ static int diff_opt_word_diff_regex(const struct option *opt,
return 0;
}
static int diff_opt_rotate_to(const struct option *opt, const char *arg, int unset)
{
struct diff_options *options = opt->value;
BUG_ON_OPT_NEG(unset);
if (!strcmp(opt->long_name, "skip-to"))
options->skip_instead_of_rotate = 1;
else
options->skip_instead_of_rotate = 0;
options->rotate_to = arg;
return 0;
}
static void prep_parse_options(struct diff_options *options)
{
struct option parseopts[] = {
@ -5599,6 +5612,12 @@ static void prep_parse_options(struct diff_options *options)
DIFF_PICKAXE_REGEX, PARSE_OPT_NONEG),
OPT_FILENAME('O', NULL, &options->orderfile,
N_("control the order in which files appear in the output")),
OPT_CALLBACK_F(0, "rotate-to", options, N_("<path>"),
N_("show the change in the specified path first"),
PARSE_OPT_NONEG, diff_opt_rotate_to),
OPT_CALLBACK_F(0, "skip-to", options, N_("<path>"),
N_("skip the output to the specified path"),
PARSE_OPT_NONEG, diff_opt_rotate_to),
OPT_CALLBACK_F(0, "find-object", options, N_("<object-id>"),
N_("look for differences that change the number of occurrences of the specified object"),
PARSE_OPT_NONEG, diff_opt_find_object),
@ -6669,6 +6688,8 @@ void diffcore_std(struct diff_options *options)
diffcore_pickaxe(options);
if (options->orderfile)
diffcore_order(options->orderfile);
if (options->rotate_to)
diffcore_rotate(options);
if (!options->found_follow)
/* See try_to_follow_renames() in tree-diff.c */
diff_resolve_rename_copy();