]> oss.titaniummirror.com Git - git-utils.git/commitdiff
git-diffall is now in git contribs
authorR. Steve McKown <rsmckown@gmail.com>
Thu, 27 Feb 2014 23:07:05 +0000 (16:07 -0700)
committerR. Steve McKown <rsmckown@gmail.com>
Thu, 27 Feb 2014 23:07:05 +0000 (16:07 -0700)
Update to latest git-diffall in contribs, and update man page with
information from the script.

git-diffall
git-diffall.1

index 990d28537b858ba773f068242c747c67a53c2c09..84f2b654d755cf4b55beb959491b46728f3c59b6 100755 (executable)
 #!/bin/sh
-# Thanks to Thomas Rast
-# http://thread.gmane.org/gmane.comp.version-control.git/124807
+# Copyright 2010 - 2012, Tim Henigan <tim.henigan@gmail.com>
+#
+# Perform a directory diff between commits in the repository using
+# the external diff or merge tool specified in the user's config.
+
+USAGE='[--cached] [--copy-back] [-x|--extcmd=<command>] <commit>{0,2} [-- <path>*]
+
+    --cached     Compare to the index rather than the working tree.
+
+    --copy-back  Copy files back to the working tree when the diff
+                 tool exits (in case they were modified by the
+                 user).  This option is only valid if the diff
+                 compared with the working tree.
+
+    -x=<command>
+    --extcmd=<command>  Specify a custom command for viewing diffs.
+                 git-diffall ignores the configured defaults and
+                 runs $command $LOCAL $REMOTE when this option is
+                 specified. Additionally, $BASE is set in the
+                 environment.
+'
 
 SUBDIRECTORY_OK=1
 . "$(git --exec-path)/git-sh-setup"
-cd_to_toplevel # for the tar below
 
-pre="${1-HEAD}"
-post="$2"
+TOOL_MODE=diff
+. "$(git --exec-path)/git-mergetool--lib"
+
+merge_tool="$(get_merge_tool)"
+if test -z "$merge_tool"
+then
+       echo "Error: Either the 'diff.tool' or 'merge.tool' option must be set."
+       usage
+fi
 
-tmp="$(mktemp -d)"
+start_dir=$(pwd)
 
-cleanup () {
-       rm -rf $tmp
+# All the file paths returned by the diff command are relative to the root
+# of the working copy. So if the script is called from a subdirectory, it
+# must switch to the root of working copy before trying to use those paths.
+cdup=$(git rev-parse --show-cdup) &&
+cd "$cdup" || {
+       echo >&2 "Cannot chdir to $cdup, the toplevel of the working tree"
+       exit 1
 }
 
-trap cleanup EXIT
+# set up temp dir
+tmp=$(perl -e 'use File::Temp qw(tempdir);
+       $t=tempdir("/tmp/git-diffall.XXXXX") or exit(1);
+       print $t') || exit 1
+trap 'rm -rf "$tmp"' EXIT
+
+left=
+right=
+paths=
+dashdash_seen=
+compare_staged=
+merge_base=
+left_dir=
+right_dir=
+diff_tool=
+copy_back=
+
+while test $# != 0
+do
+       case "$1" in
+       -h|--h|--he|--hel|--help)
+               usage
+               ;;
+       --cached)
+               compare_staged=1
+               ;;
+       --copy-back)
+               copy_back=1
+               ;;
+       -x|--e|--ex|--ext|--extc|--extcm|--extcmd)
+               if test $# = 1
+               then
+                       echo You must specify the tool for use with --extcmd
+                       usage
+               else
+                       diff_tool=$2
+                       shift
+               fi
+               ;;
+       --)
+               dashdash_seen=1
+               ;;
+       -*)
+               echo Invalid option: "$1"
+               usage
+               ;;
+       *)
+               # could be commit, commit range or path limiter
+               case "$1" in
+               *...*)
+                       left=${1%...*}
+                       right=${1#*...}
+                       merge_base=1
+                       ;;
+               *..*)
+                       left=${1%..*}
+                       right=${1#*..}
+                       ;;
+               *)
+                       if test -n "$dashdash_seen"
+                       then
+                               paths="$paths$1 "
+                       elif test -z "$left"
+                       then
+                               left=$1
+                       elif test -z "$right"
+                       then
+                               right=$1
+                       else
+                               paths="$paths$1 "
+                       fi
+                       ;;
+               esac
+               ;;
+       esac
+       shift
+done
 
-mkdir "$tmp"/a "$tmp"/b
+# Determine the set of files which changed
+if test -n "$left" && test -n "$right"
+then
+       left_dir="cmt-$(git rev-parse --short $left)"
+       right_dir="cmt-$(git rev-parse --short $right)"
 
-if [ -n "$post" ]; then
-       git diff --name-only "$pre" "$post" > "$tmp"/filelist
-       while read name; do
-               mkdir -p "$tmp"/b/"$(dirname "$name")"
-               git show "$post":"$name" > "$tmp"/b/"$name"
-       done < "$tmp"/filelist
+       if test -n "$compare_staged"
+       then
+               usage
+       elif test -n "$merge_base"
+       then
+               git diff --name-only "$left"..."$right" -- $paths >"$tmp/filelist"
+       else
+               git diff --name-only "$left" "$right" -- $paths >"$tmp/filelist"
+       fi
+elif test -n "$left"
+then
+       left_dir="cmt-$(git rev-parse --short $left)"
+
+       if test -n "$compare_staged"
+       then
+               right_dir="staged"
+               git diff --name-only --cached "$left" -- $paths >"$tmp/filelist"
+       else
+               right_dir="working_tree"
+               git diff --name-only "$left" -- $paths >"$tmp/filelist"
+       fi
 else
-       git diff --name-only "$pre" > "$tmp"/filelist
-       tar -c -T "$tmp"/filelist | (cd "$tmp"/b && tar -x)
+       left_dir="HEAD"
+
+       if test -n "$compare_staged"
+       then
+               right_dir="staged"
+               git diff --name-only --cached -- $paths >"$tmp/filelist"
+       else
+               right_dir="working_tree"
+               git diff --name-only -- $paths >"$tmp/filelist"
+       fi
 fi
 
-while read name; do
-       mkdir -p "$tmp"/a/"$(dirname "$name")"
-       git show "$pre":"$name" > "$tmp"/a/"$name"
-done < "$tmp"/filelist
-
-cd "$tmp"
-#meld a b
-#diff -ur a b
-tool="$(git-config diff.tool)"
-if [ -n "$tool" ]; then
-  "$tool" a b
+# Exit immediately if there are no diffs
+if test ! -s "$tmp/filelist"
+then
+       exit 0
+fi
+
+if test -n "$copy_back" && test "$right_dir" != "working_tree"
+then
+       echo "--copy-back is only valid when diff includes the working tree."
+       exit 1
+fi
+
+# Create the named tmp directories that will hold the files to be compared
+mkdir -p "$tmp/$left_dir" "$tmp/$right_dir"
+
+# Populate the tmp/right_dir directory with the files to be compared
+while read name
+do
+       if test -n "$right"
+       then
+               ls_list=$(git ls-tree $right "$name")
+               if test -n "$ls_list"
+               then
+                       mkdir -p "$tmp/$right_dir/$(dirname "$name")"
+                       git show "$right":"$name" >"$tmp/$right_dir/$name" || true
+               fi
+       elif test -n "$compare_staged"
+       then
+               ls_list=$(git ls-files -- "$name")
+               if test -n "$ls_list"
+               then
+                       mkdir -p "$tmp/$right_dir/$(dirname "$name")"
+                       git show :"$name" >"$tmp/$right_dir/$name"
+               fi
+       else
+               if test -e "$name"
+               then
+                       mkdir -p "$tmp/$right_dir/$(dirname "$name")"
+                       cp "$name" "$tmp/$right_dir/$name"
+               fi
+       fi
+done < "$tmp/filelist"
+
+# Populate the tmp/left_dir directory with the files to be compared
+while read name
+do
+       if test -n "$left"
+       then
+               ls_list=$(git ls-tree $left "$name")
+               if test -n "$ls_list"
+               then
+                       mkdir -p "$tmp/$left_dir/$(dirname "$name")"
+                       git show "$left":"$name" >"$tmp/$left_dir/$name" || true
+               fi
+       else
+               if test -n "$compare_staged"
+               then
+                       ls_list=$(git ls-tree HEAD "$name")
+                       if test -n "$ls_list"
+                       then
+                               mkdir -p "$tmp/$left_dir/$(dirname "$name")"
+                               git show HEAD:"$name" >"$tmp/$left_dir/$name"
+                       fi
+               else
+                       mkdir -p "$tmp/$left_dir/$(dirname "$name")"
+                       git show :"$name" >"$tmp/$left_dir/$name"
+               fi
+       fi
+done < "$tmp/filelist"
+
+LOCAL="$tmp/$left_dir"
+REMOTE="$tmp/$right_dir"
+
+if test -n "$diff_tool"
+then
+       export BASE
+       eval $diff_tool '"$LOCAL"' '"$REMOTE"'
 else
-  diff -urN a b
+       run_merge_tool "$merge_tool" false
+fi
+
+# Copy files back to the working dir, if requested
+if test -n "$copy_back" && test "$right_dir" = "working_tree"
+then
+       cd "$start_dir"
+       git_top_dir=$(git rev-parse --show-toplevel)
+       find "$tmp/$right_dir" -type f |
+       while read file
+       do
+               cp "$file" "$git_top_dir/${file#$tmp/$right_dir/}"
+       done
 fi
index fa1d55c5e4c8b5f0d67e31079f7e5415f6d62f49..6c8302c69a214315ed7156a41cd4d19e3ef506b8 100644 (file)
@@ -4,17 +4,31 @@
 git-diffall \- Use a visual diff tool to show all differences
 
 .SH SYNOPSIS
-\fBgit-diffall\fR [\fIPRE\fR] [\fIPOST\fR]
+\fBgit-diffall\fR [\fI--cached\fR] [\fI--copy-back\fR]
+        [\fI-x|--extcmd=<command>\fR] <commit>{0,2} [\fI-- <path>*\fR]
 
 .SH "DESCRIPTION"
 
 .PP
-\fBgit-diffall\fR performs a visual diff using kdiff3 between PRE and POST
-of the current project.  No arguments will show the differences between the
-working directory and HEAD.  If in the git config diff.tool is set, this
-program is passed the name of the two temporary directories containing the
-changed files of each revision.  If diff.tool is not defined, the fall-back
-is to diff.
+\fBgit-diffall\fR performs a diff using the configured diff.tool or merge.tool.
+
+    --cached     Compare to the index rather than the working tree.
+
+    --copy-back  Copy files back to the working tree when the diff
+                 tool exits (in case they were modified by the
+                 user).  This option is only valid if the diff
+                 compared with the working tree.
+
+    -x=<command>
+    --extcmd=<command>
+                 Specify a custom command for viewing diffs.
+                 git-diffall ignores the configured defaults and
+                 runs $command $LOCAL $REMOTE when this option is
+                 specified. Additionally, $BASE is set in the
+                 environment.
+
+Thanks to Tim Henigan <tim.henigan@gmail.com> who created a newer version now
+released with git contribs.
 
 Thanks to Thomas Rast for publishing this script online:
 http://thread.gmane.org/gmane.comp.version-control.git/124807