#!/bin/bash # patchsync: Synchronize a branch with a patch (e.g., acls.diff and rsync-acl). # usage: patchsync {'' | --dry-run} [branch | patch] # : the staging directory, containing a shell script "settings" and an optional rsync filter file "filter" # "settings" must contain: # - $trunk, $patch, $branch paths interpreted relative to the staging dir # - shell function do_diff: trunk, branch => patch # e.g., for rsync: diff -uprN trunk branch | sed -re 's/^(\+\+\+|---) ([^\t]+).*$/\1 \2/' | grep -v '^diff' >patch # - shell function do_patch: branch copied from trunk, patch => branch # e.g., for rsync: patch --no-backup-if-mismatch -d branch/ -p1 &2 exit 1 fi cd "$staging" dryrun="$2" whichtochange="$3" CP2t=(cp2 --del) CP2in=("${CP2t[@]}" --filter='. filter' --delete-excluded) CP2out=("${CP2t[@]}" --filter='. filter' --no-t --checksum) # be nice to mtimes export LC_COLLATE="C" . settings echo "Copying in, checking for changes..." "${CP2in[@]}" --link-dest=../trunk-save -i "$trunk/" trunk/ diff -r trunk{-save,} >/dev/null || trunkch=ch "${CP2in[@]}" --link-dest=../branch-save -i "$branch/" branch/ diff -r branch{-save,} >/dev/null || branchch=ch cp2 --link-dest=../patch-save -i "$patch" patch diff -r patch{-save,} >/dev/null || patchch=ch echo "Done." if [ $trunkch ] || [ $branchch ] || [ $patchch ]; then # Something changed. # Update either branch or patch, whichever didn't change. # If trunk changes, update branch, not patch. if [ "$whichtochange" == 'branch' ] || ! [ $branchch ]; then echo "Updating branch..." "${CP2t[@]}" trunk/ branch/ do_patch echo "Done." copyout=1 elif [ "$whichtochange" == 'patch' ] || ! [ $patchch ]; then echo "Updating patch..." do_diff echo "Done." copyout=1 else echo "Conflict: both branch and patch changed!" echo "Run patchsync [branch | patch] to" echo "update the specified area from the others." exit 1 fi else # Easy case echo "Nothing changed." fi if [ $copyout ]; then if ! [ $dryrun ]; then ! [ -e lock ] || { echo "Locked! Please fix!"; exit 1; } echo "patchsync lock file pid $$ date $(date)" >lock echo "Copying out..." "${CP2out[@]}" -i branch/ "$branch/" cp2 -i --checksum patch "$patch" echo "Done." echo "Noting..." for i in trunk branch patch; do rm -rf $i-save mv $i{,-save} done echo "Done." rm lock else echo "Dry run; no action. You can inspect the results if you want." echo "Fake copying out..." "${CP2out[@]}" -in branch/ "$branch/" cp2 -in --checksum patch "$patch" echo "Done." fi fi exit 0