@@ -34,6 +34,9 @@ OPTIONS
This is the default behaviour; the option is provided to
override any configuration settings.
+--start-from=<file>::
+ Start viewing diff from the specified file.
+
-t <tool>::
--tool=<tool>::
Use the diff tool specified by <tool>. Valid values include
@@ -882,6 +882,7 @@ LIB_OBJS += diffcore-delta.o
LIB_OBJS += diffcore-order.o
LIB_OBJS += diffcore-pickaxe.o
LIB_OBJS += diffcore-rename.o
+LIB_OBJS += diffcore-rotate.o
LIB_OBJS += dir-iterator.o
LIB_OBJS += dir.o
LIB_OBJS += editor.o
@@ -5599,6 +5599,10 @@ 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_STRING(0, "rotate-to", &options->rotate_to, N_("<path>"),
+ N_("show the change in the specified path first")),
+ OPT_STRING(0, "start-from", &options->rotate_to, N_("<path>"),
+ N_("pass from difftool to diff, has the same effort as `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 +6673,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->rotate_to);
if (!options->found_follow)
/* See try_to_follow_renames() in tree-diff.c */
diff_resolve_rename_copy();
@@ -226,6 +226,7 @@ enum diff_submodule_format {
*/
struct diff_options {
const char *orderfile;
+ const char *rotate_to;
/**
* A constant string (can and typically does contain newlines to look for
new file mode 100644
@@ -0,0 +1,35 @@
+/*
+ * Copyright (C) 2021, Google LLC.
+ * Based on diffcore-order.c, which is Copyright (C) 2005, Junio C Hamano
+ */
+#include "cache.h"
+#include "diff.h"
+#include "diffcore.h"
+
+void diffcore_rotate(const char *rotate_to_filename)
+{
+ struct diff_queue_struct *q = &diff_queued_diff;
+ struct diff_queue_struct outq;
+ int rotate_to, i;
+
+ if (!q->nr)
+ return;
+
+ for (i = 0; i < q->nr; i++)
+ if (strcmp(rotate_to_filename, q->queue[i]->two->path) <= 0)
+ break;
+ /* we did not find the specified path */
+ if (q->nr <= i)
+ return;
+
+ DIFF_QUEUE_CLEAR(&outq);
+ rotate_to = i;
+
+ for (i = rotate_to; i < q->nr; i++)
+ diff_q(&outq, q->queue[i]);
+ for (i = 0; i < rotate_to; i++)
+ diff_q(&outq, q->queue[i]);
+
+ free(q->queue);
+ *q = outq;
+}
@@ -164,6 +164,7 @@ void diffcore_rename(struct diff_options *);
void diffcore_merge_broken(void);
void diffcore_pickaxe(struct diff_options *);
void diffcore_order(const char *orderfile);
+void diffcore_rotate(const char *rotate_to_filename);
/* low-level interface to diffcore_order */
struct obj_order {
@@ -762,4 +762,27 @@ test_expect_success 'difftool --gui, --tool and --extcmd are mutually exclusive'
test_must_fail git difftool --gui --tool=test-tool --extcmd=cat
'
+test_expect_success 'difftool --start-from' '
+ difftool_test_setup &&
+ test_when_finished git reset --hard &&
+ echo 1 >1 &&
+ echo 2 >2 &&
+ echo 4 >4 &&
+ git add 1 2 4 &&
+ git commit -a -m "124" &&
+ git difftool --no-prompt --extcmd=cat --start-from="2" HEAD^ >output &&
+ cat >expect <<-\EOF &&
+ 2
+ 4
+ 1
+ EOF
+ test_cmp output expect &&
+ git difftool --no-prompt --extcmd=cat --start-from="3" HEAD^ >output &&
+ cat >expect <<-\EOF &&
+ 4
+ 1
+ 2
+ EOF
+ test_cmp output expect
+'
test_done