@@ -15,6 +15,7 @@ g_cached_opt=
1515gf_debug=0
1616gf_no_term=
1717gf_use_color=
18+ gf_warn_risky_stderr=
1819
1920g_rm_list=" $( mktemp) "
2021
@@ -80,6 +81,14 @@ sed_esc () (
8081 fi
8182)
8283
84+ sgr () {
85+ if [ " $gf_use_color " -eq 1 ]; then
86+ printf " \033[%sm%s\033[0m" " $1 " " $2 "
87+ else
88+ printf ' %s' " $2 "
89+ fi
90+ }
91+
8392warn () (
8493 >&2 printf " %s: " " $( basename " $0 " ) "
8594 # printf "\033[30m\033[103m"
@@ -275,10 +284,12 @@ detect_filetype () (
275284
276285git_changes_formatted () (
277286 tempdir=" $1 "
278- b_raw=" $2 "
279- a_raw=" $3 "
280- b_fmt=" $4 "
281- a_fmt=" $5 "
287+ formatter=" $2 "
288+
289+ b_raw=" $3 "
290+ a_raw=" $4 "
291+ b_fmt=" $5 "
292+ a_fmt=" $6 "
282293
283294 merge () { git merge-file -p " $@ " ; }
284295 chng_fmt=" $tempdir " /chng_fmt
@@ -306,20 +317,30 @@ git_changes_formatted () (
306317 if ! git diff -s " $chng_fmt " " $temp " ; then
307318 echo " $chng_fmt "
308319 fi
320+
321+ sh -c " $formatter " < " $chng_fmt " > " $temp " 2> /dev/null
322+ if ! git diff -s " $b_fmt " " $temp " ; then
323+ return 1
324+ fi
309325)
310326
311327git_diff () (
312328 b_raw=" $1 "
313329 chng_fmt=" $2 "
314330 filename=" $3 "
315331
316- [ " $gf_use_color " = 1 ] && color=" --color" || color=
332+ case " $filename " in
333+ /* ) ;;
334+ * ) a_filename=" a/$a_filename " ;;
335+ esac
336+
337+ [ " $gf_use_color " -eq 1 ] && color=" --color" || color=
317338
318339 # shellcheck disable=SC2086
319340 git diff $color " $b_raw " " $chng_fmt " | \
320341 sed \
321- -e " s/$( sed_esc -p " a$b_raw " ) /$( sed_esc -s " a/ $filename " ) /g" \
322- -e " s/$( sed_esc -p " b$chng_fmt " ) /$( sed_esc -s " b/ $filename " ) /g"
342+ -e " s/$( sed_esc -p " a$b_raw " ) /$( sed_esc -s " $filename " ) /g" \
343+ -e " s/$( sed_esc -p " b$chng_fmt " ) /$( sed_esc -s " $filename " ) /g"
323344)
324345
325346git_retrieve_file_from_sha () (
@@ -357,10 +378,12 @@ list_files () (
357378)
358379
359380process_file () (
360- a_hash=" $1 "
361- b_hash=" $2 "
362- a_name=" $3 "
363- b_name=" ${4:- $a_name } "
381+ risky=" $1 "
382+
383+ a_hash=" $2 "
384+ b_hash=" $3 "
385+ a_name=" $4 "
386+ b_name=" ${5:- $a_name } "
364387
365388 debug " --- PROCESSING: $b_name ---"
366389 debug " args = " " $@ "
@@ -396,26 +419,29 @@ process_file () (
396419 rm_list__push " $a_raw " " $b_raw "
397420
398421 if [ ! -s " $b_raw " ]; then
399- warn " couldn't retrieve $b_name "
422+ warn " couldn't retrieve '$b_name '"
423+ return
400424 fi
401425
402426 sh -c " $formatter " < " $b_raw " > " $b_fmt " 2> /dev/null
403427 rm_list__push " $b_fmt "
404428
405- if ! git diff -s " $b_raw " " $b_fmt " ; then
406- sh -c " $formatter " < " $a_raw " > " $a_fmt " 2> /dev/null
407- rm_list__push " $a_fmt "
429+ git diff -s " $b_raw " " $b_fmt " && return
408430
409- chng_fmt=" $( git_changes_formatted \
410- " $tempdir " \
411- " $b_raw " " $a_raw " \
412- " $b_fmt " " $a_fmt " \
413- ) "
431+ sh -c " $formatter " < " $a_raw " > " $a_fmt " 2> /dev/null
432+ rm_list__push " $a_fmt "
414433
415- if [ -n " $chng_fmt " ]; then
416- git_diff " $b_raw " " $chng_fmt " " $b_name "
417- fi
418- fi
434+ chng_fmt=" $( git_changes_formatted \
435+ " $tempdir " " $formatter " \
436+ " $b_raw " " $a_raw " \
437+ " $b_fmt " " $a_fmt " \
438+ ) "
439+ ret=" $? "
440+
441+ [ -z " $chng_fmt " ] && return
442+
443+ [ " $ret " -ne 0 ] && echo " $b_name " >> " $risky "
444+ git_diff " $b_raw " " $chng_fmt " " $b_name "
419445)
420446
421447processing () (
@@ -428,7 +454,11 @@ processing () (
428454 repo_root=" $( git rev-parse --show-toplevel 2> /dev/null) "
429455 [ -n " $repo_root " ] && { cd " $repo_root " || exit 1; }
430456
431- i=0
457+ risky=" $outdir " /0
458+ touch " $risky "
459+ rm_list__push " $risky "
460+
461+ i=1
432462 i_len=" $( echo " $files " | wc -l | tr -d ' \n' | wc -m) "
433463 while read -r line; do
434464 [ -z " $line " ] && continue
@@ -437,7 +467,7 @@ processing () (
437467 rm_list__push " $outfile "
438468
439469 # shellcheck disable=SC2086
440- process_file $line > " $outfile " &
470+ process_file " $risky " $line > " $outfile " &
441471
442472 i=$(( i+ 1 ))
443473 done << EOL
@@ -446,12 +476,29 @@ EOL
446476
447477 wait
448478
479+ if [ -s " $risky " ]; then
480+ cat > " $risky " .temp << EOW
481+ $( sgr 33 ' @ WARNING!' )
482+ $( sgr 33 ' @ Suggestions for the following files might smuggle unsolicited changes:' )
483+ $( sort " $risky " | sed ' s/^/- /' )
484+ $( sgr 33 " @ Review them thoroughly before applying." )
485+
486+
487+ EOW
488+ mv " $risky " .temp " $risky "
489+
490+ if [ " $gf_warn_risky_stderr " -eq 1 ]; then
491+ cat " $risky " 1>&2
492+ true > " $risky "
493+ fi
494+ fi
495+
449496 if [ -n " $( ls -A " $outdir " ) " ]; then
450497 cat " $outdir " /* | sh -c " $( git_conf_get pager) "
451498 fi
452499)
453500
454- # start {{{ 1
501+ # }}} 1
455502
456503usage () (
457504 cat << EOU
@@ -461,97 +508,95 @@ usage: git fmt-diff [<options>] [<commit>] [--] [<path>...]
461508 or: git fmt-diff [<options>] <blob> <blob>
462509
463510options:
464- -h display this help and exit
465- --cached view the changes you staged for the next commit relative
466- to the named <commit> (which defaults to HEAD)
467- --staged a synonym of --cached
468- --color always show colors
469- --no-color turn off colored diff
470- --config <file> read config from specified file rather than \$ GIT_DIR/.git-$gc_prog_name
511+ -h display this help and exit
512+ --cached view the changes you staged for the next commit relative
513+ to the named <commit> (which defaults to HEAD)
514+ --staged a synonym of --cached
515+ --color always show colors
516+ --no-color turn off colored diff
517+ --config <file> read config from specified file rather than \$ GIT_DIR/.git-$gc_prog_name
518+ --warn-risky-stderr redirects warning about potential unsolicited changes in suggestions to stderr;
519+ option not recommended as the warning blocks dangerous 'git apply'
471520EOU
472521)
473522
474- main () (
475- # parse options {{{2
476- while : ; do
477- case " $1 " in
478- -h)
479- usage
480- exit
481- ;;
482- --cached|--staged)
483- g_cached_opt=" --cached"
484- ;;
485- --debug)
486- gf_debug=1
487- ;;
488- --debug=* )
489- gf_debug=" ${1# --debug=} "
490- ;;
491- --config)
492- g_config=" $2 "
493- if [ -z " $g_config " ]; then
494- warn " option 'config' requires a path to config file as argument"
495- exit 1
496- fi
497- shift
498- ;;
499- --color)
500- gf_use_color=1
501- ;;
502- --no-color)
503- gf_use_color=0
504- ;;
505- --)
506- shift
507- break
508- ;;
509- -?* )
510- warn " unknown option: $1 "
511- usage
523+ # parse options {{{2
524+ while : ; do
525+ case " $1 " in
526+ -h)
527+ usage
528+ exit
529+ ;;
530+ --cached|--staged)
531+ g_cached_opt=" --cached"
532+ ;;
533+ --debug)
534+ gf_debug=1
535+ ;;
536+ --debug=* )
537+ gf_debug=" ${1# --debug=} "
538+ ;;
539+ --config)
540+ g_config=" $2 "
541+ if [ -z " $g_config " ]; then
542+ warn " option 'config' requires a path to config file as argument"
512543 exit 1
513- ;;
514- * )
515- break
516- ;;
517- esac
518-
519- shift
520- done
521-
522- for o in " $@ " ; do
523- case " $o " in
524- -?* )
525- warn " option '$o ' must come before non-option arguments"
526- return 1
527- ;;
528- esac
529- done
544+ fi
545+ shift
546+ ;;
547+ --color)
548+ gf_use_color=1
549+ ;;
550+ --no-color)
551+ gf_use_color=0
552+ ;;
553+ --warn-risky-stderr)
554+ gf_warn_risky_stderr=1
555+ ;;
556+ --)
557+ shift
558+ break
559+ ;;
560+ -?* )
561+ warn " unknown option: $1 "
562+ usage
563+ exit 1
564+ ;;
565+ * )
566+ break
567+ ;;
568+ esac
530569
531- [ -t 1 ] && gf_no_term=0 || gf_no_term=1
570+ shift
571+ done
572+
573+ for o in " $@ " ; do
574+ case " $o " in
575+ -?* )
576+ warn " option '$o ' must come before non-option arguments"
577+ return 1
578+ ;;
579+ esac
580+ done
532581
533- repo_root=" $( git rev-parse --show-toplevel 2> /dev/null) "
534- if [ -z " $g_config " ] && [ -n " $repo_root " ]; then
535- if [ -e " $repo_root /.git-$gc_prog_name " ]; then
536- g_local_rc=" $repo_root /.git-$gc_prog_name "
537- fi
538- fi
582+ [ -t 1 ] && gf_no_term=0 || gf_no_term=1
583+ [ -z " $gf_warn_risky_stderr " ] && gf_warn_risky_stderr=0
584+ [ -z " $gf_use_color " ] && [ " $gf_no_term " = 0 ] && gf_use_color=1
585+ [ -z " $gf_use_color " ] && gf_use_color=0
539586
540- if [ -z " $gf_use_color " ] && [ " $gf_no_term " = 0 ]; then
541- gf_use_color=1
587+ repo_root=" $( git rev-parse --show-toplevel 2> /dev/null) "
588+ if [ -z " $g_config " ] && [ -n " $repo_root " ]; then
589+ if [ -e " $repo_root /.git-$gc_prog_name " ]; then
590+ g_local_rc=" $repo_root /.git-$gc_prog_name "
542591 fi
592+ fi
543593
544- # setup env {{{2
545- TMPDIR=" ${TMPDIR:-/ tmp} " /git-" $gc_prog_name "
546- mkdir -p " $TMPDIR "
547- rm_list__push " $TMPDIR "
548-
549- trap ' cleanup' EXIT
550- # }}}2
594+ # setup env {{{2
595+ TMPDIR=" ${TMPDIR:-/ tmp} " /git-" $gc_prog_name "
596+ mkdir -p " $TMPDIR "
597+ rm_list__push " $TMPDIR "
551598
552- processing " $@ "
553- )
554-
555- # }}}1
599+ trap ' cleanup' EXIT
600+ # }}}2
556601
557- main " $@ "
602+ processing " $@ "
0 commit comments