]> git.ipfire.org Git - thirdparty/git.git/commitdiff
difftool: display the number of files in the diff queue in the prompt
authorZoltan Klinger <zoltan.klinger@gmail.com>
Thu, 5 Dec 2013 23:38:46 +0000 (10:38 +1100)
committerJunio C Hamano <gitster@pobox.com>
Fri, 6 Dec 2013 22:00:27 +0000 (14:00 -0800)
When --prompt option is set, git-difftool displays a prompt for each
modified file to be viewed in an external diff program.  At that
point, it could be useful to display a counter and the total number
of files in the diff queue.

Below is the current difftool prompt for the first of 5 modified files:

    Viewing: 'diff.c'
    Launch 'vimdiff' [Y/n]:

Consider the modified prompt:

    Viewing (1/5): 'diff.c'
    Launch 'vimdiff' [Y/n]:

The current GIT_EXTERNAL_DIFF mechanism does not tell the number of
paths in the diff queue nor the current counter.  To make this
"counter/total" info available for GIT_EXTERNAL_DIFF programs
without breaking existing ones by doing the following:

 - Keep track of the number of paths shown so far in diff_options;

 - Export two new environment variables from run_external_diff() to
   show the total number of paths (from diff_queue_struct) and the
   current value of the counter (from diff_options); and

 - Update git-difftool--helper to use these two environment variables.

Signed-off-by: Zoltan Klinger <zoltan.klinger@gmail.com>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
Documentation/git.txt
diff.c
diff.h
git-difftool--helper.sh
t/t4020-diff-external.sh

index b73a24a3c78c72c8cb6e75b0e14a45cb0e0b42e9..25b9002be32ae02bbe89ac3de924278dd01ae233 100644 (file)
@@ -804,6 +804,15 @@ temporary file --- it is removed when 'GIT_EXTERNAL_DIFF' exits.
 +
 For a path that is unmerged, 'GIT_EXTERNAL_DIFF' is called with 1
 parameter, <path>.
++
+For each path 'GIT_EXTERNAL_DIFF' is called, two environment variables,
+'GIT_DIFF_PATH_COUNTER' and 'GIT_DIFF_PATH_TOTAL' are set.
+
+'GIT_DIFF_PATH_COUNTER'::
+       A 1-based counter incremented by one for every path.
+
+'GIT_DIFF_PATH_TOTAL'::
+       The total number of paths.
 
 other
 ~~~~~
diff --git a/diff.c b/diff.c
index e34bf971207f7737c3b1a10968acd8ffb3ecf93d..a7d5a47edf36a8b6901886615b5f32da01ecb118 100644 (file)
--- a/diff.c
+++ b/diff.c
@@ -2899,11 +2899,16 @@ static void run_external_diff(const char *pgm,
                              struct diff_filespec *one,
                              struct diff_filespec *two,
                              const char *xfrm_msg,
-                             int complete_rewrite)
+                             int complete_rewrite,
+                             struct diff_options *o)
 {
        const char *spawn_arg[10];
        int retval;
        const char **arg = &spawn_arg[0];
+       struct diff_queue_struct *q = &diff_queued_diff;
+       const char *env[3] = { NULL };
+       char env_counter[50];
+       char env_total[50];
 
        if (one && two) {
                struct diff_tempfile *temp_one, *temp_two;
@@ -2928,7 +2933,14 @@ static void run_external_diff(const char *pgm,
        }
        *arg = NULL;
        fflush(NULL);
-       retval = run_command_v_opt(spawn_arg, RUN_USING_SHELL);
+
+       env[0] = env_counter;
+       snprintf(env_counter, sizeof(env_counter), "GIT_DIFF_PATH_COUNTER=%d",
+                       ++o->diff_path_counter);
+       env[1] = env_total;
+       snprintf(env_total, sizeof(env_total), "GIT_DIFF_PATH_TOTAL=%d", q->nr);
+
+       retval = run_command_v_opt_cd_env(spawn_arg, RUN_USING_SHELL, NULL, env);
        remove_tempfile();
        if (retval) {
                fprintf(stderr, "external diff died, stopping at %s.\n", name);
@@ -3042,7 +3054,7 @@ static void run_diff_cmd(const char *pgm,
 
        if (pgm) {
                run_external_diff(pgm, name, other, one, two, xfrm_msg,
-                                 complete_rewrite);
+                                 complete_rewrite, o);
                return;
        }
        if (one && two)
@@ -3317,6 +3329,8 @@ void diff_setup_done(struct diff_options *options)
                options->output_format = DIFF_FORMAT_NO_OUTPUT;
                DIFF_OPT_SET(options, EXIT_WITH_STATUS);
        }
+
+    options->diff_path_counter = 0;
 }
 
 static int opt_arg(const char *arg, int arg_short, const char *arg_long, int *val)
diff --git a/diff.h b/diff.h
index e34232501ee8e56a1d245da1c4f95ed8b928a837..42bd34c0ce75fac6332f584c280542cbde3ee6c4 100644 (file)
--- a/diff.h
+++ b/diff.h
@@ -164,6 +164,8 @@ struct diff_options {
        diff_prefix_fn_t output_prefix;
        int output_prefix_length;
        void *output_prefix_data;
+
+       int diff_path_counter;
 };
 
 enum color_diff {
index b00ed95dba9c035ee812d3a2d6db2d13a1944a33..7ef36b9482ccc4111f2c888bf5ccbaa2421a5875 100755 (executable)
@@ -40,7 +40,8 @@ launch_merge_tool () {
        # the user with the real $MERGED name before launching $merge_tool.
        if should_prompt
        then
-               printf "\nViewing: '%s'\n" "$MERGED"
+               printf "\nViewing (%s/%s): '%s'\n" "$GIT_DIFF_PATH_COUNTER" \
+                       "$GIT_DIFF_PATH_TOTAL" "$MERGED"
                if use_ext_cmd
                then
                        printf "Launch '%s' [Y/n]: " \
index 8a309795c9c9654446d82c2e474e1ca08486e081..bcae35ac1c93aaf79032db5ee09fd2d3400101f5 100755 (executable)
@@ -193,6 +193,19 @@ test_expect_success 'GIT_EXTERNAL_DIFF with more than one changed files' '
        GIT_EXTERNAL_DIFF=echo git diff
 '
 
+test_expect_success 'GIT_EXTERNAL_DIFF path counter/total' '
+       write_script external-diff.sh <<-\EOF &&
+       echo $GIT_DIFF_PATH_COUNTER of $GIT_DIFF_PATH_TOTAL >>counter.txt
+       EOF
+       >counter.txt &&
+       cat >expect <<-\EOF &&
+       1 of 2
+       2 of 2
+       EOF
+       GIT_EXTERNAL_DIFF=./external-diff.sh git diff &&
+       test_cmp expect counter.txt
+'
+
 test_expect_success 'GIT_EXTERNAL_DIFF generates pretty paths' '
        touch file.ext &&
        git add file.ext &&