Merge branch 'jc/calloc-fix'
[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 and spaces of the output.
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                 -e "s/ *\$//"
108 }
109
110 #            (C)   (D, pull/1/head, topic/1)
111 #             o --- o
112 #            /       \                              (L)
113 #           /         \        o (H, topic/2)             (M, tag:v2)
114 #          /    (F)    \      /                                 (N, tag:v3)
115 #         /      o --------- o (G, pull/2/head)      o --- o --- o (release)
116 #        /      /        \    \                      /       \
117 #  o --- o --- o -------- o -- o ------------------ o ------- o --- o (main)
118 # (A)   (B)  (E, tag:v1) (I)  (J)                  (K)       (O)   (P)
119 #
120 test_expect_success 'setup' '
121         # Try to make a stable fixed width for abbreviated commit ID,
122         # this fixed-width oid will be replaced with "<OID>".
123         git config core.abbrev 7 &&
124
125         # branch main: commit A & B
126         test_commit_setvar A "Commit A" main.txt &&
127         test_commit_setvar B "Commit B" main.txt &&
128
129         # branch topic/1: commit C & D, refs/pull/1/head
130         git checkout -b topic/1 &&
131         test_commit_setvar C "Commit C" topic-1.txt &&
132         test_commit_setvar D "Commit D" topic-1.txt &&
133         git update-ref refs/pull/1/head HEAD &&
134
135         # branch topic/1: commit E, tag v1
136         git checkout main &&
137         test_commit_setvar E "Commit E" main.txt &&
138         test_commit_setvar --tag TAG1 v1 &&
139
140         # branch topic/2: commit F & G, refs/pull/2/head
141         git checkout -b topic/2 &&
142         test_commit_setvar F "Commit F" topic-2.txt &&
143         test_commit_setvar G "Commit G" topic-2.txt &&
144         git update-ref refs/pull/2/head HEAD &&
145         test_commit_setvar H "Commit H" topic-2.txt &&
146
147         # branch main: merge commit I & J
148         git checkout main &&
149         test_commit_setvar --merge I topic/1 "Merge commit I" &&
150         test_commit_setvar --merge J refs/pull/2/head "Merge commit J" &&
151
152         # branch main: commit K
153         git checkout main &&
154         test_commit_setvar K "Commit K" main.txt &&
155
156         # branch release:
157         git checkout -b release &&
158         test_commit_setvar L "Commit L" release.txt &&
159         test_commit_setvar M "Commit M" release.txt &&
160         test_commit_setvar --tag TAG2 v2 &&
161         test_commit_setvar N "Commit N" release.txt &&
162         test_commit_setvar --tag TAG3 v3 &&
163
164         # branch main: merge commit O, commit P
165         git checkout main &&
166         test_commit_setvar --merge O tags/v2 "Merge commit O" &&
167         test_commit_setvar P "Commit P" main.txt
168 '
169
170 test_expect_success 'create bundle from special rev: main^!' '
171         git bundle create special-rev.bdl "main^!" &&
172
173         git bundle list-heads special-rev.bdl |
174                 make_user_friendly_and_stable_output >actual &&
175         cat >expect <<-\EOF &&
176         <COMMIT-P> refs/heads/main
177         EOF
178         test_cmp expect actual &&
179
180         git bundle verify special-rev.bdl |
181                 make_user_friendly_and_stable_output >actual &&
182         cat >expect <<-\EOF &&
183         The bundle contains this ref:
184         <COMMIT-P> refs/heads/main
185         The bundle requires this ref:
186         <COMMIT-O>
187         EOF
188         test_cmp expect actual &&
189
190         test_bundle_object_count special-rev.bdl 3
191 '
192
193 test_expect_success 'create bundle with --max-count option' '
194         git bundle create max-count.bdl --max-count 1 \
195                 main \
196                 "^release" \
197                 refs/tags/v1 \
198                 refs/pull/1/head \
199                 refs/pull/2/head &&
200
201         git bundle verify max-count.bdl |
202                 make_user_friendly_and_stable_output >actual &&
203         cat >expect <<-\EOF &&
204         The bundle contains these 2 refs:
205         <COMMIT-P> refs/heads/main
206         <TAG-1> refs/tags/v1
207         The bundle requires this ref:
208         <COMMIT-O>
209         EOF
210         test_cmp expect actual &&
211
212         test_bundle_object_count max-count.bdl 4
213 '
214
215 test_expect_success 'create bundle with --since option' '
216         git log -1 --pretty="%ad" $M >actual &&
217         cat >expect <<-\EOF &&
218         Thu Apr 7 15:26:13 2005 -0700
219         EOF
220         test_cmp expect actual &&
221
222         git bundle create since.bdl \
223                 --since "Thu Apr 7 15:27:00 2005 -0700" \
224                 --all &&
225
226         git bundle verify since.bdl |
227                 make_user_friendly_and_stable_output >actual &&
228         cat >expect <<-\EOF &&
229         The bundle contains these 5 refs:
230         <COMMIT-P> refs/heads/main
231         <COMMIT-N> refs/heads/release
232         <TAG-2> refs/tags/v2
233         <TAG-3> refs/tags/v3
234         <COMMIT-P> HEAD
235         The bundle requires these 2 refs:
236         <COMMIT-M>
237         <COMMIT-K>
238         EOF
239         test_cmp expect actual &&
240
241         test_bundle_object_count --thin since.bdl 13
242 '
243
244 test_expect_success 'create bundle 1 - no prerequisites' '
245         # create bundle from args
246         git bundle create 1.bdl topic/1 topic/2 &&
247
248         # create bundle from stdin
249         cat >input <<-\EOF &&
250         topic/1
251         topic/2
252         EOF
253         git bundle create stdin-1.bdl --stdin <input &&
254
255         cat >expect <<-\EOF &&
256         The bundle contains these 2 refs:
257         <COMMIT-D> refs/heads/topic/1
258         <COMMIT-H> refs/heads/topic/2
259         The bundle records a complete history.
260         EOF
261
262         # verify bundle, which has no prerequisites
263         git bundle verify 1.bdl |
264                 make_user_friendly_and_stable_output >actual &&
265         test_cmp expect actual &&
266
267         git bundle verify stdin-1.bdl |
268                 make_user_friendly_and_stable_output >actual &&
269         test_cmp expect actual &&
270
271         test_bundle_object_count       1.bdl 24 &&
272         test_bundle_object_count stdin-1.bdl 24
273 '
274
275 test_expect_success 'create bundle 2 - has prerequisites' '
276         # create bundle from args
277         git bundle create 2.bdl \
278                 --ignore-missing \
279                 ^topic/deleted \
280                 ^$D \
281                 ^topic/2 \
282                 release &&
283
284         # create bundle from stdin
285         # input has a non-exist reference: "topic/deleted"
286         cat >input <<-EOF &&
287         ^topic/deleted
288         ^$D
289         ^topic/2
290         EOF
291         git bundle create stdin-2.bdl \
292                 --ignore-missing \
293                 --stdin \
294                 release <input &&
295
296         cat >expect <<-\EOF &&
297         The bundle contains this ref:
298         <COMMIT-N> refs/heads/release
299         The bundle requires these 3 refs:
300         <COMMIT-D>
301         <COMMIT-E>
302         <COMMIT-G>
303         EOF
304
305         git bundle verify 2.bdl |
306                 make_user_friendly_and_stable_output >actual &&
307         test_cmp expect actual &&
308
309         git bundle verify stdin-2.bdl |
310                 make_user_friendly_and_stable_output >actual &&
311         test_cmp expect actual &&
312
313         test_bundle_object_count       2.bdl 16 &&
314         test_bundle_object_count stdin-2.bdl 16
315 '
316
317 test_expect_success 'fail to verify bundle without prerequisites' '
318         git init --bare test1.git &&
319
320         cat >expect <<-\EOF &&
321         error: Repository lacks these prerequisite commits:
322         error: <COMMIT-D>
323         error: <COMMIT-E>
324         error: <COMMIT-G>
325         EOF
326
327         test_must_fail git -C test1.git bundle verify ../2.bdl 2>&1 |
328                 make_user_friendly_and_stable_output >actual &&
329         test_cmp expect actual &&
330
331         test_must_fail git -C test1.git bundle verify ../stdin-2.bdl 2>&1 |
332                 make_user_friendly_and_stable_output >actual &&
333         test_cmp expect actual
334 '
335
336 test_expect_success 'create bundle 3 - two refs, same object' '
337         # create bundle from args
338         git bundle create --version=3 3.bdl \
339                 ^release \
340                 ^topic/1 \
341                 ^topic/2 \
342                 main \
343                 HEAD &&
344
345         # create bundle from stdin
346         cat >input <<-\EOF &&
347         ^release
348         ^topic/1
349         ^topic/2
350         EOF
351         git bundle create --version=3 stdin-3.bdl \
352                 --stdin \
353                 main HEAD <input &&
354
355         cat >expect <<-\EOF &&
356         The bundle contains these 2 refs:
357         <COMMIT-P> refs/heads/main
358         <COMMIT-P> HEAD
359         The bundle requires these 2 refs:
360         <COMMIT-M>
361         <COMMIT-K>
362         EOF
363
364         git bundle verify 3.bdl |
365                 make_user_friendly_and_stable_output >actual &&
366         test_cmp expect actual &&
367
368         git bundle verify stdin-3.bdl |
369                 make_user_friendly_and_stable_output >actual &&
370         test_cmp expect actual &&
371
372         test_bundle_object_count       3.bdl 4 &&
373         test_bundle_object_count stdin-3.bdl 4
374 '
375
376 test_expect_success 'create bundle 4 - with tags' '
377         # create bundle from args
378         git bundle create 4.bdl \
379                 ^main \
380                 ^release \
381                 ^topic/1 \
382                 ^topic/2 \
383                 --all &&
384
385         # create bundle from stdin
386         cat >input <<-\EOF &&
387         ^main
388         ^release
389         ^topic/1
390         ^topic/2
391         EOF
392         git bundle create stdin-4.bdl \
393                 --ignore-missing \
394                 --stdin \
395                 --all <input &&
396
397         cat >expect <<-\EOF &&
398         The bundle contains these 3 refs:
399         <TAG-1> refs/tags/v1
400         <TAG-2> refs/tags/v2
401         <TAG-3> refs/tags/v3
402         The bundle records a complete history.
403         EOF
404
405         git bundle verify 4.bdl |
406                 make_user_friendly_and_stable_output >actual &&
407         test_cmp expect actual &&
408
409         git bundle verify stdin-4.bdl |
410                 make_user_friendly_and_stable_output >actual &&
411         test_cmp expect actual &&
412
413         test_bundle_object_count       4.bdl 3 &&
414         test_bundle_object_count stdin-4.bdl 3
415 '
416
417 test_expect_success 'clone from bundle' '
418         git clone --mirror 1.bdl mirror.git &&
419         git -C mirror.git show-ref |
420                 make_user_friendly_and_stable_output >actual &&
421         cat >expect <<-\EOF &&
422         <COMMIT-D> refs/heads/topic/1
423         <COMMIT-H> refs/heads/topic/2
424         EOF
425         test_cmp expect actual &&
426
427         git -C mirror.git fetch ../2.bdl "+refs/*:refs/*" &&
428         git -C mirror.git show-ref |
429                 make_user_friendly_and_stable_output >actual &&
430         cat >expect <<-\EOF &&
431         <COMMIT-N> refs/heads/release
432         <COMMIT-D> refs/heads/topic/1
433         <COMMIT-H> refs/heads/topic/2
434         EOF
435         test_cmp expect actual &&
436
437         git -C mirror.git fetch ../3.bdl "+refs/*:refs/*" &&
438         git -C mirror.git show-ref |
439                 make_user_friendly_and_stable_output >actual &&
440         cat >expect <<-\EOF &&
441         <COMMIT-P> refs/heads/main
442         <COMMIT-N> refs/heads/release
443         <COMMIT-D> refs/heads/topic/1
444         <COMMIT-H> refs/heads/topic/2
445         EOF
446         test_cmp expect actual &&
447
448         git -C mirror.git fetch ../4.bdl "+refs/*:refs/*" &&
449         git -C mirror.git show-ref |
450                 make_user_friendly_and_stable_output >actual &&
451         cat >expect <<-\EOF &&
452         <COMMIT-P> refs/heads/main
453         <COMMIT-N> refs/heads/release
454         <COMMIT-D> refs/heads/topic/1
455         <COMMIT-H> refs/heads/topic/2
456         <TAG-1> refs/tags/v1
457         <TAG-2> refs/tags/v2
458         <TAG-3> refs/tags/v3
459         EOF
460         test_cmp expect actual
461 '
462
463 test_done