difftool: display the number of files in the diff queue in the prompt

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>

Zoltan Klinger committed Dec 6, 2013 at 10:38 UTC ee7fb0b1d433cbb433d2ed5cd9d8738023836b27
5 files changed +43 -4
Documentation/git.txt
+9
@@ -804,6 +804,15 @@ temporary file --- it is removed when 'GIT_EXTERNAL_DIFF' exits.
804 +
805 For a path that is unmerged, 'GIT_EXTERNAL_DIFF' is called with 1
806 parameter, <path>.
807 ++
808 +For each path 'GIT_EXTERNAL_DIFF' is called, two environment variables,
809 +'GIT_DIFF_PATH_COUNTER' and 'GIT_DIFF_PATH_TOTAL' are set.
810 +
811 +'GIT_DIFF_PATH_COUNTER'::
812 + A 1-based counter incremented by one for every path.
813 +
814 +'GIT_DIFF_PATH_TOTAL'::
815 + The total number of paths.
816
817 other
818 ~~~~~
diff.c
+17 -3
@@ -2899,11 +2899,16 @@ static void run_external_diff(const char *pgm,
2899 struct diff_filespec *one,
2900 struct diff_filespec *two,
2901 const char *xfrm_msg,
2902 - int complete_rewrite)
2902 + int complete_rewrite,
2903 + struct diff_options *o)
2904 {
2905 const char *spawn_arg[10];
2906 int retval;
2907 const char **arg = &spawn_arg[0];
2908 + struct diff_queue_struct *q = &diff_queued_diff;
2909 + const char *env[3] = { NULL };
2910 + char env_counter[50];
2911 + char env_total[50];
2912
2913 if (one && two) {
2914 struct diff_tempfile *temp_one, *temp_two;
@@ -2928,7 +2933,14 @@ static void run_external_diff(const char *pgm,
2933 }
2934 *arg = NULL;
2935 fflush(NULL);
2931 - retval = run_command_v_opt(spawn_arg, RUN_USING_SHELL);
2936 +
2937 + env[0] = env_counter;
2938 + snprintf(env_counter, sizeof(env_counter), "GIT_DIFF_PATH_COUNTER=%d",
2939 + ++o->diff_path_counter);
2940 + env[1] = env_total;
2941 + snprintf(env_total, sizeof(env_total), "GIT_DIFF_PATH_TOTAL=%d", q->nr);
2942 +
2943 + retval = run_command_v_opt_cd_env(spawn_arg, RUN_USING_SHELL, NULL, env);
2944 remove_tempfile();
2945 if (retval) {
2946 fprintf(stderr, "external diff died, stopping at %s.\n", name);
@@ -3042,7 +3054,7 @@ static void run_diff_cmd(const char *pgm,
3054
3055 if (pgm) {
3056 run_external_diff(pgm, name, other, one, two, xfrm_msg,
3045 - complete_rewrite);
3057 + complete_rewrite, o);
3058 return;
3059 }
3060 if (one && two)
@@ -3317,6 +3329,8 @@ void diff_setup_done(struct diff_options *options)
3329 options->output_format = DIFF_FORMAT_NO_OUTPUT;
3330 DIFF_OPT_SET(options, EXIT_WITH_STATUS);
3331 }
3332 +
3333 + options->diff_path_counter = 0;
3334 }
3335
3336 static int opt_arg(const char *arg, int arg_short, const char *arg_long, int *val)
diff.h
+2
@@ -164,6 +164,8 @@ struct diff_options {
164 diff_prefix_fn_t output_prefix;
165 int output_prefix_length;
166 void *output_prefix_data;
167 +
168 + int diff_path_counter;
169 };
170
171 enum color_diff {
git-difftool--helper.sh
+2 -1
@@ -40,7 +40,8 @@ launch_merge_tool () {
40 # the user with the real $MERGED name before launching $merge_tool.
41 if should_prompt
42 then
43 - printf "\nViewing: '%s'\n" "$MERGED"
43 + printf "\nViewing (%s/%s): '%s'\n" "$GIT_DIFF_PATH_COUNTER" \
44 + "$GIT_DIFF_PATH_TOTAL" "$MERGED"
45 if use_ext_cmd
46 then
47 printf "Launch '%s' [Y/n]: " \
t/t4020-diff-external.sh
+13
@@ -193,6 +193,19 @@ test_expect_success 'GIT_EXTERNAL_DIFF with more than one changed files' '
193 GIT_EXTERNAL_DIFF=echo git diff
194 '
195
196 +test_expect_success 'GIT_EXTERNAL_DIFF path counter/total' '
197 + write_script external-diff.sh <<-\EOF &&
198 + echo $GIT_DIFF_PATH_COUNTER of $GIT_DIFF_PATH_TOTAL >>counter.txt
199 + EOF
200 + >counter.txt &&
201 + cat >expect <<-\EOF &&
202 + 1 of 2
203 + 2 of 2
204 + EOF
205 + GIT_EXTERNAL_DIFF=./external-diff.sh git diff &&
206 + test_cmp expect counter.txt
207 +'
208 +
209 test_expect_success 'GIT_EXTERNAL_DIFF generates pretty paths' '
210 touch file.ext &&
211 git add file.ext &&