* [PATCH] contrib/diffall: Add script to perform directory diff using external diff tool
@ 2010-04-14 1:15 Tim Henigan
0 siblings, 0 replies; only message in thread
From: Tim Henigan @ 2010-04-14 1:15 UTC (permalink / raw)
To: git; +Cc: Thomas Rast, Seba Illingworth
The existing 'git difftool' command allows the user to view git diffs
using an external diff tool. However, if multiple files contain
differences, a separate instance of the diff tool is launched for
each one.
This script launches a single instance of the external diff tool
and performs a directory diff between the specified revisions.
The before/after files are copied to a tmp directory to do this.
The 'diff.tool' configuration option must be set for this script
to work.
The user interface matches the standard 'git diff' command.
Signed-off-by: Tim Henigan <tim.henigan@gmail.com>
---
This script is based on an example provided by Thomas Rast on the Git list [1].
I tested with:
- msysgit and kdiff3 (the platform where I first needed this script)
- cygwin git and kdiff3
- git and meld
[1] http://thread.gmane.org/gmane.comp.version-control.git/124807
contrib/diffall/git-diffall | 159 +++++++++++++++++++++++++++++++++++++++++++
1 files changed, 159 insertions(+), 0 deletions(-)
create mode 100755 contrib/diffall/git-diffall
diff --git a/contrib/diffall/git-diffall b/contrib/diffall/git-diffall
new file mode 100755
index 0000000..c24fba9
--- /dev/null
+++ b/contrib/diffall/git-diffall
@@ -0,0 +1,159 @@
+#!/bin/sh -e
+# Copyright 2010, Tim Henigan <tim.henigan@gmail.com>
+#
+# Perform a directory diff between commits in the repository using
+# the external diff tool specified in the 'diff.tool' configuration
+# option.
+
+USAGE='<options> <commit>{0,2} -- <path>*
+
+--cached Compare to the index rather than the working tree
+commit SHA1 of a commit
+path Limit the diff to the specified paths
+'
+
+. git-sh-setup
+
+if [ -z $(git config --get diff.tool) ]; then
+ echo "Error: The 'diff.tool' configuration option must be set."
+ usage
+fi
+
+start_dir=$(pwd)
+cd_to_toplevel # needed to access tar utility
+
+# mktemp is not available on all platforms (missing from msysgit)
+# Use a hard-coded tmp dir if it is not available
+if [ -z $(which mktemp) ]; then
+ tmp=/tmp/git-diffall-tmp
+else
+ tmp="$(mktemp -d)"
+fi
+mkdir -p "$tmp" "$tmp"/a "$tmp"/b
+
+left=
+right=
+paths=
+path_sep=
+compare_staged=
+common_anscestor=
+
+while test $# != 0; do
+ case "$1" in
+ -h|--h|--he|--hel|--help)
+ usage
+ ;;
+ --cached)
+ compare_staged=1
+ ;;
+ --)
+ path_sep=1
+ ;;
+ -*)
+ echo Invalid option: "$1"
+ usage
+ ;;
+ *)
+ # could be commit, commit range or path limiter
+ case "$1" in
+ *...*)
+ left=${1%...*}
+ right=${1#*...}
+ common_anscestor=1
+ ;;
+ *..*)
+ left=${1%..*}
+ right=${1#*..}
+ ;;
+ *)
+ if [ -n "$path_sep" ]; then
+ if [ -z "$paths" ]; then
+ paths=$1
+ else
+ paths="$paths $1"
+ fi
+ elif [ -z "$left" ]; then
+ left=$1
+ elif [ -z "$right" ]; then
+ right=$1
+ else
+ if [ -z "$paths" ]; then
+ paths=$1
+ else
+ paths="$paths $1"
+ fi
+ fi
+ ;;
+ esac
+ ;;
+ esac
+ shift
+done
+
+# Determine the set of files which changed
+if [ -n "$left" ] && [ -n "$right" ]; then
+ if [ -n "$compare_staged" ]; then
+ usage
+ elif [ -n "$common_anscestor" ]; then
+ git diff --name-only "$left"..."$right" -- "$paths" > "$tmp"/filelist
+ else
+ git diff --name-only "$left" "$right" -- "$paths" > "$tmp"/filelist
+ fi
+elif [ -n "$left" ]; then
+ if [ -n "$compare_staged" ]; then
+ git diff --name-only --cached "$left" -- "$paths" > "$tmp"/filelist
+ else
+ git diff --name-only "$left" -- "$paths" > "$tmp"/filelist
+ fi
+else
+ if [ -n "$compare_staged" ]; then
+ git diff --name-only --cached -- "$paths" > "$tmp"/filelist
+ else
+ git diff --name-only -- "$paths" > "$tmp"/filelist
+ fi
+fi
+
+# Exit immediately if there are no diffs
+if [ ! -s "$tmp"/filelist ]; then
+ exit 0
+fi
+
+# Populate the tmp/b directory with the files to be compared
+if [ -n "$right" ]; then
+ while read name; do
+ mkdir -p "$tmp"/b/"$(dirname "$name")"
+ git show "$right":"$name" > "$tmp"/b/"$name"
+ done < "$tmp"/filelist
+elif [ -n "$compare_staged" ]; then
+ while read name; do
+ mkdir -p "$tmp"/b/"$(dirname "$name")"
+ git show :"$name" > "$tmp"/b/"$name"
+ done < "$tmp"/filelist
+else
+ tar -c -T "$tmp"/filelist | (cd "$tmp"/b && tar -x)
+fi
+
+# Populate the tmp/a directory with the files to be compared
+while read name; do
+ mkdir -p "$tmp"/a/"$(dirname "$name")"
+ if [ -n "$left" ]; then
+ git show "$left":"$name" > "$tmp"/a/"$name"
+ else
+ if [ -n "$compare_staged" ]; then
+ git show HEAD:"$name" > "$tmp"/a/"$name"
+ else
+ git show :"$name" > "$tmp"/a/"$name"
+ fi
+ fi
+done < "$tmp"/filelist
+
+cd "$tmp"
+$(git config --get diff.tool) a b
+
+# On exit, remove the tmp directory
+cleanup () {
+ cd "$start_dir"
+ rm -rf "$tmp"
+}
+
+trap cleanup EXIT
--
1.7.0.3.291.g5e4f6.dirty
^ permalink raw reply related [flat|nested] only message in thread
only message in thread, other threads:[~2010-04-14 1:15 UTC | newest]
Thread overview: (only message) (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2010-04-14 1:15 [PATCH] contrib/diffall: Add script to perform directory diff using external diff tool Tim Henigan
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.