Commit | Line | Data |
---|---|---|
67afd050 MM |
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 | ||
14 | set -e | |
15 | ||
16 | staging="$1" | |
17 | if ! [ -r "$staging/settings" ]; then | |
18 | echo "Specify a staging directory containing a settings file!" 1>&2 | |
19 | exit 1 | |
20 | fi | |
21 | cd "$staging" | |
22 | ||
23 | dryrun="$2" | |
24 | whichtochange="$3" | |
25 | CP2t=(cp2 --del) | |
26 | CP2in=("${CP2t[@]}" --filter='. filter' --delete-excluded) | |
27 | CP2out=("${CP2t[@]}" --filter='. filter' --no-t --checksum) # be nice to mtimes | |
28 | export LC_COLLATE="C" | |
29 | ||
30 | . settings | |
31 | ||
32 | echo "Copying in, checking for changes..." | |
33 | "${CP2in[@]}" --link-dest=../trunk-save -i "$trunk/" trunk/ | |
34 | diff -r trunk{-save,} >/dev/null || trunkch=ch | |
35 | "${CP2in[@]}" --link-dest=../branch-save -i "$branch/" branch/ | |
36 | diff -r branch{-save,} >/dev/null || branchch=ch | |
37 | cp2 --link-dest=../patch-save -i "$patch" patch | |
38 | diff -r patch{-save,} >/dev/null || patchch=ch | |
39 | echo "Done." | |
40 | ||
41 | if [ $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 | |
62 | else | |
63 | # Easy case | |
64 | echo "Nothing changed." | |
65 | fi | |
66 | ||
67 | if [ $copyout ]; then | |
68 | if ! [ $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 | |
84 | else | |
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." | |
90 | fi | |
91 | fi | |
92 | ||
93 | exit 0 |