# -- Matt McCutchen
# If I had to update the version in the --version message separately, I would forget.
-PATCHSYNC_VERSION=2.3
+PATCHSYNC_VERSION=2.4
# usage: patchsync [--dry-run] <staging> [branch | patch]
#
# - do_patch <patch> <convert-trunk-to-branch>: apply the patch to the
# specified trunk; define it to understand your favorite diff format
# - example: patch --no-backup-if-mismatch -d $2/ -p1 <$1
-# - Note: patchsync runs these functions under "pipefail", but the
-# "set -e" it uses does not propagate into the functions. Patchsync
-# provides an "exitoneok" function you can use to treat an exit code of
-# 1 as 0. You might want to && successive commands together.
+# - Note: Patchsync runs these functions under "pipefail" and "set -e".
+# Caution: "set -e" is idiosyncratic; you may wish to && together
+# successive commands anyway. Patchsync provides an "exitoneok"
+# function you can use to treat an exit code of 1 as 0.
# - There are several possible ways to handle failed hunks. The simplest
# and safest is to make do_patch fail, but that's inconvenient for the
# user, who must investigate the *.rej files in the staging directory
# Disable branch/.patchsync support because it's a bad idea in general, and the
# cyclic symlink confuses Eclipse in particular. -- Matt 2006.11.30
-set -e
-trap "echo 'Patchsync encountered an unexpected error! ABORTING!' 1>&2; exit 2;" ERR
+# Error handling
+function handle_error {
+ exec >&2
+ echo "Patchsync encountered an unexpected error! Aborting!"
+ echo "The failed command was: $1"
+ exit 2
+}
+trap 'handle_error "$BASH_COMMAND"' ERR
set -o errtrace
set -o pipefail
# NOT bash builtin pwd; it tells us how we got here, not where we are
pA="$(/bin/pwd)/"
pA="${pA#/}"
- pB="$( (cd "$AtoB" && /bin/pwd) )/"
+ pB="$(cd "$AtoB" && /bin/pwd)/"
pB="${pB#/}"
# Lop off the longest common prefix of components that we can.
# While first components are equal...
ans="$pA"
# Translate remaining components of $pB to ../s
while [ -n "$pB" ]; do
- ans="$ans../"
+ ans="../$ans"
pB="${pB#*/}"
done
# Double check; add dot to the end to enforce ending in a slash and handle empty ans
(cd "$AtoB" && [ "$ans." -ef /proc/self/fd/3 ]) 3<.
+ [ $? == 0 ]
# Yay
echo "$ans"
}
type do_patch >/dev/null 2>&1 || { echo "do_patch is not defined!" 1>&2; exit 1; }
whichtoupdate="$1"
-# patchsync --new doesn't need this any more except for identical-branch
-#if [ -z "$whichtoupdate" ] && [ -s whichtoupdate ]; then
-# # Hook for patchsync --new
-# whichtoupdate="$(< whichtoupdate)"
-# echo "Updating $whichtoupdate according to staging dir."
-#el
if [ -n "$whichtoupdate" ]; then
echo "Updating $whichtoupdate according to command line argument."
else
echo "Preparing updated branch..."
# No link-dest because we will modify and then link-dest when copying out
"${COPYIN[@]}" trunk/ branch-new/
- do_patch patch branch-new || \
- { error=1; echo "Failed to prepare updated branch!" 1>&2; rm -rf branch-new; }
+ (do_patch patch branch-new)
+ [ $? == 0 ] || { error=1; echo "Failed to prepare updated branch!" 1>&2; rm -rf branch-new; }
}
function prepare_patch {
# Link-dest is fine because these are temporary read-only copies
"${COPYIN[@]}" --link-dest=../trunk/ trunk/ trunk-tmp/
"${COPYIN[@]}" --link-dest=../branch/ branch/ branch-tmp/
- do_diff trunk-tmp branch-tmp patch-new || \
- { error=1; echo "Failed to prepare updated patch!" 1>&2; rm -rf patch-new; }
+ (do_diff trunk-tmp branch-tmp patch-new)
+ [ $? == 0 ] || { error=1; echo "Failed to prepare updated patch!" 1>&2; rm -rf patch-new; }
rm -rf trunk-tmp branch-tmp
}
# No link-dest because we will link-dest when copying out
"${COPYIN[@]}" trunk/ branch-new/
echo "Creating empty patch..."
- do_diff branch-new branch-new patch-new || \
- { error=1; echo "Failed to create empty patch!" 1>&2; rm -rf patch-new; }
+ (do_diff branch-new branch-new patch-new)
+ [ $? == 0 ] || { error=1; echo "Failed to create empty patch!" 1>&2; rm -rf patch-new; }
;;
(branch)
prepare_branch
esac
if ! [ $error ] && ! [ $dryrun ]; then
- # Disable locking for now...
- # ! [ -e lock ] || { echo "Staging dir is locked! Delete the file \`lock' if the other instance of patchsync is gone." 1>&2; exit 1; }
- # echo "patchsync lock file pid $$ date $(date)" >lock
-
echo "Copying out..."
! [ -e branch-new ] || {
hash_dir branch-new/ >branch-new-hash
- "${COPYOUT[@]}" -i --link-dest="$(wdpp_from branch/)branch-new/" branch-new/ branch/
+ linkdest="$(wdpp_from branch/)branch-new/" # Do separately so a failure in wdpp_from is noticed.
+ "${COPYOUT[@]}" -i --link-dest="$linkdest" branch-new/ branch/
rm -rf branch-new
}
! [ -e patch-new ] || cmp -s patch patch-new || {
for i in trunk patch branch; do
mv $i-new-hash $i-save-hash
done
-
- # rm lock
else
echo "Would copy out as follows:"
! [ -e branch-new ] || {
hash_dir branch-new/ >branch-new-hash
- "${COPYOUT[@]}" -n -i --link-dest="$(wdpp_from branch/)branch-new/" branch-new/ branch/
+ linkdest="$(wdpp_from branch/)branch-new/" # Do separately so a failure in wdpp_from is noticed.
+ "${COPYOUT[@]}" -n -i --link-dest="$linkdest" branch-new/ branch/
#rm -rf branch-new
}
! [ -e patch-new ] || cmp -s patch patch-new || {
echo "Created staging dir at $staging."
# Adjust paths appropriately.
- trunk="$wdpp$trunk"
- patch="$wdpp$patch"
- branch="$wdpp$branch"
+ [[ "$trunk" == /* ]] || trunk="$wdpp$trunk"
+ [[ "$patch" == /* ]] || patch="$wdpp$patch"
+ [[ "$branch" == /* ]] || branch="$wdpp$branch"
# Create links to areas
ln -s "$trunk" trunk