chiark / gitweb /
76e51b67169d7b84e84eb6edda573860f7f3d9b0
[dgit.git] / tests / tartree-edit
1 #!/bin/sh
2 set -e
3 fail () { echo >&2 "$0: $*"; exit 1; }
4
5 play=.git/tartree-edit-work
6
7 git_manip_play () {
8         local wd=$(pwd)
9         case "$wd" in
10         *.edit) fail "bad idea to run gitfetchinfo into a .edit tree!" ;;
11         esac
12         rm -rf $play
13         mkdir $play
14 }
15
16 gitfetchdiff_list () {
17         git for-each-ref --format '%(refname) %(objectname)' \
18                 refs/remotes/"$1" \
19         | sed 's/^refs\/remotes\/[^\/]*\///' \
20         | sort >"$play/$2"
21 }
22
23 gitfetchdiff () {
24         local how="$1"
25         local a="$2"
26         local b="$3"
27         git_manip_play
28
29         rrab=refs/remotes/"$a+$b"
30
31         ulf=\
32 "delete refs/remotes/$a/%l
33 delete refs/remotes/$b/%l
34 "
35         case "$how" in
36         diff)
37                 git for-each-ref --format 'delete %(refname)' $rrab \
38                         | git update-ref --stdin
39                 ;;
40         merge)
41                 ulf=\
42 "create $rrab/%l
43 $ulf"
44                 ;;
45         *)
46                 fail "internal error bad how ($how)"
47                 ;;
48         esac
49
50         gitfetchdiff_list "$a" a
51         gitfetchdiff_list "$b" b
52
53         diff --old-line-format='' --new-line-format='' \
54                 --unchanged-line-format="$ulf" \
55                 $play/a $play/b >$play/updates \
56         || test $? = 1
57
58         git update-ref --stdin <$play/updates
59         exit 0
60 }
61
62 case "$#.$1" in
63 2.edit|2.done)  mode="$1"; arg="$2" ;;
64 3.gitfetchinfo) mode="$1"; arg="$2"; remote="$3" ;;
65 3.gitfetchinfo-diff)    gitfetchdiff diff "$2" "$3"     ;;
66 3.gitfetchinfo-merge)   gitfetchdiff merge "$2" "$3"    ;;
67 ?.-*)   fail "no options understood"                    ;;
68 *)      fail "usage:
69     tartree-edit edit|done DIRECTORY|TARBALL
70     tartree-edit gitfetchinfo DIRECTORY|TARBALL REMOTE" ;;
71 esac
72
73 case "$arg" in
74 *.tar)          base=${arg%.tar}                        ;;
75 *.edit)         base=${arg%.edit}                       ;;
76 *)              base=${arg}                             ;;
77 esac
78
79 tryat_pre () {
80         local b="$1"
81         rm -rf "$b.tmp"
82         if test -f "$b.tar" && test -f "$b.edit"; then
83                 echo "$b.edit exists, deleting possibly-obsolete $b.tar"
84                 rm "$b.tar"
85         fi
86 }
87
88 tryat_edit () {
89         local b="$1"
90         if test -d "$b.edit"; then
91                 echo "$b.edit already exists"
92                 exit 0
93         fi
94         if test -f "$b.tar"; then
95                 mkdir "$b.tmp"
96                 (set -e; cd "$b.tmp"; tar xf "$b.tar")
97                 mv "$b.tmp" "$b.edit"
98                 rm "$b.tar"
99                 echo "$b.edit ready"
100                 exit 0
101         fi
102 }
103
104 gitfetchinfo_perhaps_commit () {
105         local m="$1"
106         set +e
107         git diff --cached --quiet --exit-code HEAD
108         local rc=$?
109         set -e
110         case "$rc" in
111         0)   return ;;
112         1)   git commit --allow-empty --author='tartree-edit <>' -m "$m" ;;
113         *)   fail "git diff failed ($rc)" ;;
114         esac
115 }
116
117 tryat_gitfetchinfo () {
118         git_manip_play
119         if test -d "$b.edit"; then
120                 cp -a "$b.edit"/. "$play"/.
121         else
122                 exec 3<"$b.tar"
123                 tar -C $play -f - <&3 -x
124                 exec 3<&-
125         fi
126         local innerwd=$play/*
127         git remote remove "$remote" 2>/dev/null ||:
128         git remote add "$remote" $innerwd
129         git fetch --no-tags -p "$remote" \
130                 +"HEAD:refs/remotes/$remote/HEAD"
131         cd $innerwd
132         git checkout -b WORKTREE
133         gitfetchinfo_perhaps_commit INDEX
134         git add -Af .
135         gitfetchinfo_perhaps_commit WORKTREE
136         cd ../../..
137         git fetch --no-tags "$remote" --refmap \
138                 +"refs/*:refs/remotes/$remote/*" \
139                 +"refs/*:refs/remotes/$remote/*"
140         exit 0
141 }
142
143 tryat_done () {
144         local b="$1"
145         if test -d "$b.edit"; then
146                 (set -e; cd "$b.edit"; tar cf "$b.tmp" *)
147                 mv "$b.tmp" "$b.tar"
148                 mv "$b.edit" "$b.tmp"
149                 rm -rf "$b.tmp"
150                 echo "$b.tar regenerated"
151                 exit 0
152         fi
153         if test -f "$b.tar"; then
154                 echo "$b.tar already exists and $b.edit doesn't"
155                 exit 0
156         fi
157 }
158
159 tryat () {
160         local b="$1"
161         if ! test -f "$b.tar" && ! test -d "$b.edit"; then
162                 return
163         fi
164         tryat_pre "$b"
165         tryat_$mode "$b"
166         fail "unexpected situation in $b.*"
167 }
168
169 case "$arg" in
170 /*)             tryat "$base"
171                 ;;
172 *)
173                 pwd=`pwd`
174                 tryat "$pwd/$base"
175                 tryat "$pwd/git-srcs/$base"
176                 tryat "$pwd/tests/git-srcs/$base"
177                 fail "could not find $base..."
178                 ;;
179 esac