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