Import patchsync version 1
[utils/utils.git] / patchsync
... / ...
CommitLineData
1#!/bin/bash
2# patchsync: Synchronize a branch with a patch (e.g., acls.diff and rsync-acl).
3# usage: patchsync <staging> {'' | --dry-run} [branch | patch]
4# <staging>: the staging directory, containing a shell script "settings" and an optional rsync filter file "filter"
5# "settings" must contain:
6# - $trunk, $patch, $branch paths interpreted relative to the staging dir
7# - shell function do_diff: trunk, branch => patch
8# e.g., for rsync: diff -uprN trunk branch | sed -re 's/^(\+\+\+|---) ([^\t]+).*$/\1 \2/' | grep -v '^diff' >patch
9# - shell function do_patch: branch copied from trunk, patch => branch
10# e.g., for rsync: patch --no-backup-if-mismatch -d branch/ -p1 <patch
11# --dry-run: don't note anything
12# branch | patch: overwrite the specified thing in case of a conflict (e.g., on the first run)
13
14set -e
15
16staging="$1"
17if ! [ -r "$staging/settings" ]; then
18 echo "Specify a staging directory containing a settings file!" 1>&2
19 exit 1
20fi
21cd "$staging"
22
23dryrun="$2"
24whichtochange="$3"
25CP2t=(cp2 --del)
26CP2in=("${CP2t[@]}" --filter='. filter' --delete-excluded)
27CP2out=("${CP2t[@]}" --filter='. filter' --no-t --checksum) # be nice to mtimes
28export LC_COLLATE="C"
29
30. settings
31
32echo "Copying in, checking for changes..."
33"${CP2in[@]}" --link-dest=../trunk-save -i "$trunk/" trunk/
34diff -r trunk{-save,} >/dev/null || trunkch=ch
35"${CP2in[@]}" --link-dest=../branch-save -i "$branch/" branch/
36diff -r branch{-save,} >/dev/null || branchch=ch
37cp2 --link-dest=../patch-save -i "$patch" patch
38diff -r patch{-save,} >/dev/null || patchch=ch
39echo "Done."
40
41if [ $trunkch ] || [ $branchch ] || [ $patchch ]; then
42 # Something changed.
43 # Update either branch or patch, whichever didn't change.
44 # If trunk changes, update branch, not patch.
45 if [ "$whichtochange" == 'branch' ] || ! [ $branchch ]; then
46 echo "Updating branch..."
47 "${CP2t[@]}" trunk/ branch/
48 do_patch
49 echo "Done."
50 copyout=1
51 elif [ "$whichtochange" == 'patch' ] || ! [ $patchch ]; then
52 echo "Updating patch..."
53 do_diff
54 echo "Done."
55 copyout=1
56 else
57 echo "Conflict: both branch and patch changed!"
58 echo "Run patchsync <staging> <dry-run> [branch | patch] to"
59 echo "update the specified area from the others."
60 exit 1
61 fi
62else
63 # Easy case
64 echo "Nothing changed."
65fi
66
67if [ $copyout ]; then
68if ! [ $dryrun ]; then
69 ! [ -e lock ] || { echo "Locked! Please fix!"; exit 1; }
70 echo "patchsync lock file pid $$ date $(date)" >lock
71
72 echo "Copying out..."
73 "${CP2out[@]}" -i branch/ "$branch/"
74 cp2 -i --checksum patch "$patch"
75 echo "Done."
76 echo "Noting..."
77 for i in trunk branch patch; do
78 rm -rf $i-save
79 mv $i{,-save}
80 done
81 echo "Done."
82
83 rm lock
84else
85 echo "Dry run; no action. You can inspect the results if you want."
86 echo "Fake copying out..."
87 "${CP2out[@]}" -in branch/ "$branch/"
88 cp2 -in --checksum patch "$patch"
89 echo "Done."
90fi
91fi
92
93exit 0