test: compare raw output, not mangle tabs and spaces
[git] / t / t6020-bundle-misc.sh
1 #!/bin/sh
2 #
3 # Copyright (c) 2021 Jiang Xin
4 #
5
6 test_description='Test git-bundle'
7
8 GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME=main
9 export GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME
10
11 . ./test-lib.sh
12 . "$TEST_DIRECTORY"/lib-bundle.sh
13
14 # Create a commit or tag and set the variable with the object ID.
15 test_commit_setvar () {
16         notick=
17         signoff=
18         indir=
19         merge=
20         tag=
21         var=
22
23         while test $# != 0
24         do
25                 case "$1" in
26                 --merge)
27                         merge=t
28                         ;;
29                 --tag)
30                         tag=t
31                         ;;
32                 --notick)
33                         notick=t
34                         ;;
35                 --signoff)
36                         signoff="$1"
37                         ;;
38                 -C)
39                         shift
40                         indir="$1"
41                         ;;
42                 -*)
43                         echo >&2 "error: unknown option $1"
44                         return 1
45                         ;;
46                 *)
47                         break
48                         ;;
49                 esac
50                 shift
51         done
52         if test $# -lt 2
53         then
54                 echo >&2 "error: test_commit_setvar must have at least 2 arguments"
55                 return 1
56         fi
57         var=$1
58         shift
59         indir=${indir:+"$indir"/}
60         if test -z "$notick"
61         then
62                 test_tick
63         fi &&
64         if test -n "$merge"
65         then
66                 git ${indir:+ -C "$indir"} merge --no-edit --no-ff \
67                         ${2:+-m "$2"} "$1" &&
68                 oid=$(git ${indir:+ -C "$indir"} rev-parse HEAD)
69         elif test -n "$tag"
70         then
71                 git ${indir:+ -C "$indir"} tag -m "$1" "$1" "${2:-HEAD}" &&
72                 oid=$(git ${indir:+ -C "$indir"} rev-parse "$1")
73         else
74                 file=${2:-"$1.t"} &&
75                 echo "${3-$1}" >"$indir$file" &&
76                 git ${indir:+ -C "$indir"} add "$file" &&
77                 git ${indir:+ -C "$indir"} commit $signoff -m "$1" &&
78                 oid=$(git ${indir:+ -C "$indir"} rev-parse HEAD)
79         fi &&
80         eval $var=$oid
81 }
82
83 # Format the output of git commands to make a user-friendly and stable
84 # text.  We can easily prepare the expect text without having to worry
85 # about future changes of the commit ID.
86 make_user_friendly_and_stable_output () {
87         sed \
88                 -e "s/${A%${A#???????}}[0-9a-f]*/<COMMIT-A>/g" \
89                 -e "s/${B%${B#???????}}[0-9a-f]*/<COMMIT-B>/g" \
90                 -e "s/${C%${C#???????}}[0-9a-f]*/<COMMIT-C>/g" \
91                 -e "s/${D%${D#???????}}[0-9a-f]*/<COMMIT-D>/g" \
92                 -e "s/${E%${E#???????}}[0-9a-f]*/<COMMIT-E>/g" \
93                 -e "s/${F%${F#???????}}[0-9a-f]*/<COMMIT-F>/g" \
94                 -e "s/${G%${G#???????}}[0-9a-f]*/<COMMIT-G>/g" \
95                 -e "s/${H%${H#???????}}[0-9a-f]*/<COMMIT-H>/g" \
96                 -e "s/${I%${I#???????}}[0-9a-f]*/<COMMIT-I>/g" \
97                 -e "s/${J%${J#???????}}[0-9a-f]*/<COMMIT-J>/g" \
98                 -e "s/${K%${K#???????}}[0-9a-f]*/<COMMIT-K>/g" \
99                 -e "s/${L%${L#???????}}[0-9a-f]*/<COMMIT-L>/g" \
100                 -e "s/${M%${M#???????}}[0-9a-f]*/<COMMIT-M>/g" \
101                 -e "s/${N%${N#???????}}[0-9a-f]*/<COMMIT-N>/g" \
102                 -e "s/${O%${O#???????}}[0-9a-f]*/<COMMIT-O>/g" \
103                 -e "s/${P%${P#???????}}[0-9a-f]*/<COMMIT-P>/g" \
104                 -e "s/${TAG1%${TAG1#???????}}[0-9a-f]*/<TAG-1>/g" \
105                 -e "s/${TAG2%${TAG2#???????}}[0-9a-f]*/<TAG-2>/g" \
106                 -e "s/${TAG3%${TAG3#???????}}[0-9a-f]*/<TAG-3>/g"
107 }
108
109 format_and_save_expect () {
110         sed -e 's/Z$//' >expect
111 }
112
113 #            (C)   (D, pull/1/head, topic/1)
114 #             o --- o
115 #            /       \                              (L)
116 #           /         \        o (H, topic/2)             (M, tag:v2)
117 #          /    (F)    \      /                                 (N, tag:v3)
118 #         /      o --------- o (G, pull/2/head)      o --- o --- o (release)
119 #        /      /        \    \                      /       \
120 #  o --- o --- o -------- o -- o ------------------ o ------- o --- o (main)
121 # (A)   (B)  (E, tag:v1) (I)  (J)                  (K)       (O)   (P)
122 #
123 test_expect_success 'setup' '
124         # Try to make a stable fixed width for abbreviated commit ID,
125         # this fixed-width oid will be replaced with "<OID>".
126         git config core.abbrev 7 &&
127
128         # branch main: commit A & B
129         test_commit_setvar A "Commit A" main.txt &&
130         test_commit_setvar B "Commit B" main.txt &&
131
132         # branch topic/1: commit C & D, refs/pull/1/head
133         git checkout -b topic/1 &&
134         test_commit_setvar C "Commit C" topic-1.txt &&
135         test_commit_setvar D "Commit D" topic-1.txt &&
136         git update-ref refs/pull/1/head HEAD &&
137
138         # branch topic/1: commit E, tag v1
139         git checkout main &&
140         test_commit_setvar E "Commit E" main.txt &&
141         test_commit_setvar --tag TAG1 v1 &&
142
143         # branch topic/2: commit F & G, refs/pull/2/head
144         git checkout -b topic/2 &&
145         test_commit_setvar F "Commit F" topic-2.txt &&
146         test_commit_setvar G "Commit G" topic-2.txt &&
147         git update-ref refs/pull/2/head HEAD &&
148         test_commit_setvar H "Commit H" topic-2.txt &&
149
150         # branch main: merge commit I & J
151         git checkout main &&
152         test_commit_setvar --merge I topic/1 "Merge commit I" &&
153         test_commit_setvar --merge J refs/pull/2/head "Merge commit J" &&
154
155         # branch main: commit K
156         git checkout main &&
157         test_commit_setvar K "Commit K" main.txt &&
158
159         # branch release:
160         git checkout -b release &&
161         test_commit_setvar L "Commit L" release.txt &&
162         test_commit_setvar M "Commit M" release.txt &&
163         test_commit_setvar --tag TAG2 v2 &&
164         test_commit_setvar N "Commit N" release.txt &&
165         test_commit_setvar --tag TAG3 v3 &&
166
167         # branch main: merge commit O, commit P
168         git checkout main &&
169         test_commit_setvar --merge O tags/v2 "Merge commit O" &&
170         test_commit_setvar P "Commit P" main.txt
171 '
172
173 test_expect_success 'create bundle from special rev: main^!' '
174         git bundle create special-rev.bdl "main^!" &&
175
176         git bundle list-heads special-rev.bdl |
177                 make_user_friendly_and_stable_output >actual &&
178         cat >expect <<-\EOF &&
179         <COMMIT-P> refs/heads/main
180         EOF
181         test_cmp expect actual &&
182
183         git bundle verify special-rev.bdl |
184                 make_user_friendly_and_stable_output >actual &&
185         format_and_save_expect <<-\EOF &&
186         The bundle contains this ref:
187         <COMMIT-P> refs/heads/main
188         The bundle requires this ref:
189         <COMMIT-O> Z
190         EOF
191         test_cmp expect actual &&
192
193         test_bundle_object_count special-rev.bdl 3
194 '
195
196 test_expect_success 'create bundle with --max-count option' '
197         git bundle create max-count.bdl --max-count 1 \
198                 main \
199                 "^release" \
200                 refs/tags/v1 \
201                 refs/pull/1/head \
202                 refs/pull/2/head &&
203
204         git bundle verify max-count.bdl |
205                 make_user_friendly_and_stable_output >actual &&
206         format_and_save_expect <<-\EOF &&
207         The bundle contains these 2 refs:
208         <COMMIT-P> refs/heads/main
209         <TAG-1> refs/tags/v1
210         The bundle requires this ref:
211         <COMMIT-O> Z
212         EOF
213         test_cmp expect actual &&
214
215         test_bundle_object_count max-count.bdl 4
216 '
217
218 test_expect_success 'create bundle with --since option' '
219         git log -1 --pretty="%ad" $M >actual &&
220         cat >expect <<-\EOF &&
221         Thu Apr 7 15:26:13 2005 -0700
222         EOF
223         test_cmp expect actual &&
224
225         git bundle create since.bdl \
226                 --since "Thu Apr 7 15:27:00 2005 -0700" \
227                 --all &&
228
229         git bundle verify since.bdl |
230                 make_user_friendly_and_stable_output >actual &&
231         format_and_save_expect <<-\EOF &&
232         The bundle contains these 5 refs:
233         <COMMIT-P> refs/heads/main
234         <COMMIT-N> refs/heads/release
235         <TAG-2> refs/tags/v2
236         <TAG-3> refs/tags/v3
237         <COMMIT-P> HEAD
238         The bundle requires these 2 refs:
239         <COMMIT-M> Z
240         <COMMIT-K> Z
241         EOF
242         test_cmp expect actual &&
243
244         test_bundle_object_count --thin since.bdl 13
245 '
246
247 test_expect_success 'create bundle 1 - no prerequisites' '
248         # create bundle from args
249         git bundle create 1.bdl topic/1 topic/2 &&
250
251         # create bundle from stdin
252         cat >input <<-\EOF &&
253         topic/1
254         topic/2
255         EOF
256         git bundle create stdin-1.bdl --stdin <input &&
257
258         cat >expect <<-\EOF &&
259         The bundle contains these 2 refs:
260         <COMMIT-D> refs/heads/topic/1
261         <COMMIT-H> refs/heads/topic/2
262         The bundle records a complete history.
263         EOF
264
265         # verify bundle, which has no prerequisites
266         git bundle verify 1.bdl |
267                 make_user_friendly_and_stable_output >actual &&
268         test_cmp expect actual &&
269
270         git bundle verify stdin-1.bdl |
271                 make_user_friendly_and_stable_output >actual &&
272         test_cmp expect actual &&
273
274         test_bundle_object_count       1.bdl 24 &&
275         test_bundle_object_count stdin-1.bdl 24
276 '
277
278 test_expect_success 'create bundle 2 - has prerequisites' '
279         # create bundle from args
280         git bundle create 2.bdl \
281                 --ignore-missing \
282                 ^topic/deleted \
283                 ^$D \
284                 ^topic/2 \
285                 release &&
286
287         # create bundle from stdin
288         # input has a non-exist reference: "topic/deleted"
289         cat >input <<-EOF &&
290         ^topic/deleted
291         ^$D
292         ^topic/2
293         EOF
294         git bundle create stdin-2.bdl \
295                 --ignore-missing \
296                 --stdin \
297                 release <input &&
298
299         format_and_save_expect <<-\EOF &&
300         The bundle contains this ref:
301         <COMMIT-N> refs/heads/release
302         The bundle requires these 3 refs:
303         <COMMIT-D> Z
304         <COMMIT-E> Z
305         <COMMIT-G> Z
306         EOF
307
308         git bundle verify 2.bdl |
309                 make_user_friendly_and_stable_output >actual &&
310         test_cmp expect actual &&
311
312         git bundle verify stdin-2.bdl |
313                 make_user_friendly_and_stable_output >actual &&
314         test_cmp expect actual &&
315
316         test_bundle_object_count       2.bdl 16 &&
317         test_bundle_object_count stdin-2.bdl 16
318 '
319
320 test_expect_success 'fail to verify bundle without prerequisites' '
321         git init --bare test1.git &&
322
323         format_and_save_expect <<-\EOF &&
324         error: Repository lacks these prerequisite commits:
325         error: <COMMIT-D> Z
326         error: <COMMIT-E> Z
327         error: <COMMIT-G> Z
328         EOF
329
330         test_must_fail git -C test1.git bundle verify ../2.bdl 2>&1 |
331                 make_user_friendly_and_stable_output >actual &&
332         test_cmp expect actual &&
333
334         test_must_fail git -C test1.git bundle verify ../stdin-2.bdl 2>&1 |
335                 make_user_friendly_and_stable_output >actual &&
336         test_cmp expect actual
337 '
338
339 test_expect_success 'create bundle 3 - two refs, same object' '
340         # create bundle from args
341         git bundle create --version=3 3.bdl \
342                 ^release \
343                 ^topic/1 \
344                 ^topic/2 \
345                 main \
346                 HEAD &&
347
348         # create bundle from stdin
349         cat >input <<-\EOF &&
350         ^release
351         ^topic/1
352         ^topic/2
353         EOF
354         git bundle create --version=3 stdin-3.bdl \
355                 --stdin \
356                 main HEAD <input &&
357
358         format_and_save_expect <<-\EOF &&
359         The bundle contains these 2 refs:
360         <COMMIT-P> refs/heads/main
361         <COMMIT-P> HEAD
362         The bundle requires these 2 refs:
363         <COMMIT-M> Z
364         <COMMIT-K> Z
365         EOF
366
367         git bundle verify 3.bdl |
368                 make_user_friendly_and_stable_output >actual &&
369         test_cmp expect actual &&
370
371         git bundle verify stdin-3.bdl |
372                 make_user_friendly_and_stable_output >actual &&
373         test_cmp expect actual &&
374
375         test_bundle_object_count       3.bdl 4 &&
376         test_bundle_object_count stdin-3.bdl 4
377 '
378
379 test_expect_success 'create bundle 4 - with tags' '
380         # create bundle from args
381         git bundle create 4.bdl \
382                 ^main \
383                 ^release \
384                 ^topic/1 \
385                 ^topic/2 \
386                 --all &&
387
388         # create bundle from stdin
389         cat >input <<-\EOF &&
390         ^main
391         ^release
392         ^topic/1
393         ^topic/2
394         EOF
395         git bundle create stdin-4.bdl \
396                 --ignore-missing \
397                 --stdin \
398                 --all <input &&
399
400         cat >expect <<-\EOF &&
401         The bundle contains these 3 refs:
402         <TAG-1> refs/tags/v1
403         <TAG-2> refs/tags/v2
404         <TAG-3> refs/tags/v3
405         The bundle records a complete history.
406         EOF
407
408         git bundle verify 4.bdl |
409                 make_user_friendly_and_stable_output >actual &&
410         test_cmp expect actual &&
411
412         git bundle verify stdin-4.bdl |
413                 make_user_friendly_and_stable_output >actual &&
414         test_cmp expect actual &&
415
416         test_bundle_object_count       4.bdl 3 &&
417         test_bundle_object_count stdin-4.bdl 3
418 '
419
420 test_expect_success 'clone from bundle' '
421         git clone --mirror 1.bdl mirror.git &&
422         git -C mirror.git show-ref |
423                 make_user_friendly_and_stable_output >actual &&
424         cat >expect <<-\EOF &&
425         <COMMIT-D> refs/heads/topic/1
426         <COMMIT-H> refs/heads/topic/2
427         EOF
428         test_cmp expect actual &&
429
430         git -C mirror.git fetch ../2.bdl "+refs/*:refs/*" &&
431         git -C mirror.git show-ref |
432                 make_user_friendly_and_stable_output >actual &&
433         cat >expect <<-\EOF &&
434         <COMMIT-N> refs/heads/release
435         <COMMIT-D> refs/heads/topic/1
436         <COMMIT-H> refs/heads/topic/2
437         EOF
438         test_cmp expect actual &&
439
440         git -C mirror.git fetch ../3.bdl "+refs/*:refs/*" &&
441         git -C mirror.git show-ref |
442                 make_user_friendly_and_stable_output >actual &&
443         cat >expect <<-\EOF &&
444         <COMMIT-P> refs/heads/main
445         <COMMIT-N> refs/heads/release
446         <COMMIT-D> refs/heads/topic/1
447         <COMMIT-H> refs/heads/topic/2
448         EOF
449         test_cmp expect actual &&
450
451         git -C mirror.git fetch ../4.bdl "+refs/*:refs/*" &&
452         git -C mirror.git show-ref |
453                 make_user_friendly_and_stable_output >actual &&
454         cat >expect <<-\EOF &&
455         <COMMIT-P> refs/heads/main
456         <COMMIT-N> refs/heads/release
457         <COMMIT-D> refs/heads/topic/1
458         <COMMIT-H> refs/heads/topic/2
459         <TAG-1> refs/tags/v1
460         <TAG-2> refs/tags/v2
461         <TAG-3> refs/tags/v3
462         EOF
463         test_cmp expect actual
464 '
465
466 test_done