]> git.ipfire.org Git - thirdparty/git.git/blame - t/t5000-tar-tree.sh
Merge branch 'jk/ci-retire-allow-ref'
[thirdparty/git.git] / t / t5000-tar-tree.sh
CommitLineData
d3d49c3d
RS
1#!/bin/sh
2#
3# Copyright (C) 2005 Rene Scharfe
4#
5
925ceccf 6test_description='git archive and git get-tar-commit-id test
d3d49c3d 7
5b860406
RS
8This test covers the topics of file contents, commit date handling and
9commit id embedding:
d3d49c3d
RS
10
11 The contents of the repository is compared to the extracted tar
12 archive. The repository contains simple text files, symlinks and a
3dff5379 13 binary file (/bin/sh). Only paths shorter than 99 characters are
5b860406 14 used.
d3d49c3d 15
925ceccf 16 git archive applies the commit date to every file in the archive it
d3d49c3d
RS
17 creates. The test sets the commit date to a specific value and checks
18 if the tar archive contains that value.
19
925ceccf 20 When giving git archive a commit id (in contrast to a tree id) it
d3d49c3d 21 embeds this commit id into the tar archive as a comment. The test
5be60078 22 checks the ability of git get-tar-commit-id to figure it out from the
d3d49c3d
RS
23 tar file.
24
25'
26
8da0b02d 27TEST_CREATE_REPO_NO_TEMPLATE=1
d3d49c3d
RS
28. ./test-lib.sh
29
38c9c9b7 30SUBSTFORMAT=%H%n
8460b2fc 31
9bf1ac41
RS
32test_lazy_prereq TAR_NEEDS_PAX_FALLBACK '
33 (
34 mkdir pax &&
35 cd pax &&
36 "$TAR" xf "$TEST_DIRECTORY"/t5000/pax.tar &&
37 test -f PaxHeaders.1791/file
38 )
39'
40
96174145
JK
41test_lazy_prereq GZIP 'gzip --version'
42
9bf1ac41
RS
43get_pax_header() {
44 file=$1
45 header=$2=
46
47 while read len rest
48 do
49 if test "$len" = $(echo "$len $rest" | wc -c)
50 then
51 case "$rest" in
52 $header*)
53 echo "${rest#$header}"
54 ;;
55 esac
56 fi
57 done <"$file"
58}
59
deb9c8ed
RS
60check_tar() {
61 tarfile=$1.tar
62 listfile=$1.lst
63 dir=$1
64 dir_with_prefix=$dir/$2
65
66 test_expect_success ' extract tar archive' '
67 (mkdir $dir && cd $dir && "$TAR" xf -) <$tarfile
68 '
69
9bf1ac41
RS
70 test_expect_success TAR_NEEDS_PAX_FALLBACK ' interpret pax headers' '
71 (
72 cd $dir &&
73 for header in *.paxheader
74 do
75 data=${header%.paxheader}.data &&
d0b30a3d 76 if test -h $data || test -e $data
9bf1ac41
RS
77 then
78 path=$(get_pax_header $header path) &&
79 if test -n "$path"
80 then
d0fd9931 81 mv "$data" "$path" || exit 1
9bf1ac41
RS
82 fi
83 fi
84 done
85 )
86 '
87
deb9c8ed
RS
88 test_expect_success ' validate filenames' '
89 (cd ${dir_with_prefix}a && find .) | sort >$listfile &&
90 test_cmp a.lst $listfile
91 '
92
93 test_expect_success ' validate file contents' '
94 diff -r a ${dir_with_prefix}a
95 '
96}
97
2947a793
RS
98check_added() {
99 dir=$1
100 path_in_fs=$2
101 path_in_archive=$3
102
103 test_expect_success " validate extra file $path_in_archive" '
104 diff -r $path_in_fs $dir/$path_in_archive
105 '
106}
107
fd2da4b1
RS
108check_mtime() {
109 dir=$1
110 path_in_archive=$2
111 mtime=$3
112
113 test_expect_success " validate mtime of $path_in_archive" '
114 test-tool chmtime --get $dir/$path_in_archive >actual.mtime &&
115 echo $mtime >expect.mtime &&
116 test_cmp expect.mtime actual.mtime
117 '
118}
119
0b78a1b2 120test_expect_success 'setup' '
121 test_oid_cache <<-EOF
122 obj sha1:19f9c8273ec45a8938e6999cb59b3ff66739902a
123 obj sha256:3c666f798798601571f5cec0adb57ce4aba8546875e7693177e0535f34d2c49b
124 EOF
125'
126
9c8e7e96
HWN
127test_expect_success 'populate workdir' '
128 mkdir a &&
129 echo simple textfile >a/a &&
130 ten=0123456789 &&
131 hundred="$ten$ten$ten$ten$ten$ten$ten$ten$ten$ten" &&
132 echo long filename >"a/four$hundred" &&
133 mkdir a/bin &&
134 test-tool genrandom "frotz" 500000 >a/bin/sh &&
135 printf "A\$Format:%s\$O" "$SUBSTFORMAT" >a/substfile1 &&
136 printf "A not substituted O" >a/substfile2 &&
137 if test_have_prereq SYMLINKS
138 then
139 ln -s a a/l1
140 else
141 printf %s a >a/l1
142 fi &&
143 (
144 p=long_path_to_a_file &&
145 cd a &&
146 for depth in 1 2 3 4 5
147 do
148 mkdir $p &&
d0fd9931 149 cd $p || exit 1
9c8e7e96
HWN
150 done &&
151 echo text >file_with_long_path
152 ) &&
153 (cd a && find .) | sort >a.lst
154'
d3d49c3d 155
008d896d
RS
156test_expect_success \
157 'add ignored file' \
158 'echo ignore me >a/ignored &&
8da0b02d 159 mkdir .git/info &&
ad94657f 160 echo ignored export-ignore >.git/info/attributes'
008d896d 161
21711ca4
RS
162test_expect_success 'add files to repository' '
163 git add a &&
164 GIT_COMMITTER_DATE="2005-05-27 22:00" git commit -m initial
165'
d3d49c3d 166
c420df7b
RS
167test_expect_success 'setup export-subst' '
168 echo "substfile?" export-subst >>.git/info/attributes &&
169 git log --max-count=1 "--pretty=format:A${SUBSTFORMAT}O" HEAD \
170 >a/substfile1
171'
172
9c8e7e96 173test_expect_success 'create bare clone' '
8da0b02d
ÆAB
174 git clone --template= --bare . bare.git &&
175 mkdir bare.git/info &&
9c8e7e96
HWN
176 cp .git/info/attributes bare.git/info/attributes
177'
ddff8563 178
9c8e7e96
HWN
179test_expect_success 'remove ignored file' '
180 rm a/ignored
181'
008d896d 182
9c8e7e96
HWN
183test_expect_success 'git archive' '
184 git archive HEAD >b.tar
185'
8ff21b1a 186
deb9c8ed 187check_tar b
1aaed69d 188check_mtime b a/a 1117231200
deb9c8ed 189
fd2da4b1
RS
190test_expect_success 'git archive --mtime' '
191 git archive --mtime=2002-02-02T02:02:02-0200 HEAD >with_mtime.tar
192'
193
194check_tar with_mtime
195check_mtime with_mtime a/a 1012622522
196
03d9bc56
RS
197test_expect_success 'git archive --prefix=prefix/' '
198 git archive --prefix=prefix/ HEAD >with_prefix.tar
199'
200
201check_tar with_prefix prefix/
202
203test_expect_success 'git-archive --prefix=olde-' '
204 git archive --prefix=olde- HEAD >with_olde-prefix.tar
205'
206
207check_tar with_olde-prefix olde-
208
2947a793
RS
209test_expect_success 'git archive --add-file' '
210 echo untracked >untracked &&
211 git archive --add-file=untracked HEAD >with_untracked.tar
212'
213
214check_tar with_untracked
215check_added with_untracked untracked untracked
216
217test_expect_success 'git archive --add-file twice' '
218 echo untracked >untracked &&
219 git archive --prefix=one/ --add-file=untracked \
220 --prefix=two/ --add-file=untracked \
221 --prefix= HEAD >with_untracked2.tar
222'
223
224check_tar with_untracked2
225check_added with_untracked2 untracked one/untracked
226check_added with_untracked2 untracked two/untracked
227
5544049d 228test_expect_success 'git archive on large files' '
9c8e7e96
HWN
229 test_config core.bigfilethreshold 1 &&
230 git archive HEAD >b3.tar &&
231 test_cmp_bin b.tar b3.tar
5544049d
NTND
232'
233
9c8e7e96
HWN
234test_expect_success 'git archive in a bare repo' '
235 git --git-dir bare.git archive HEAD >b3.tar
236'
ddff8563 237
9c8e7e96
HWN
238test_expect_success 'git archive vs. the same in a bare repo' '
239 test_cmp_bin b.tar b3.tar
240'
ddff8563 241
9c8e7e96
HWN
242test_expect_success 'git archive with --output' '
243 git archive --output=b4.tar HEAD &&
244 test_cmp_bin b.tar b4.tar
245'
aec0c1bb 246
9c8e7e96
HWN
247test_expect_success 'git archive --remote' '
248 git archive --remote=. HEAD >b5.tar &&
249 test_cmp_bin b.tar b5.tar
250'
48139269 251
eb0224c6
JH
252test_expect_success 'git archive --remote with configured remote' '
253 git config remote.foo.url . &&
254 (
255 cd a &&
256 git archive --remote=foo --output=../b5-nick.tar HEAD
257 ) &&
258 test_cmp_bin b.tar b5-nick.tar
259'
260
f1ed2247
HWN
261test_expect_success 'git get-tar-commit-id' '
262 git get-tar-commit-id <b.tar >actual &&
263 git rev-parse HEAD >expect &&
264 test_cmp expect actual
265'
d3d49c3d 266
fe12d8e8
RS
267test_expect_success 'git archive with --output, override inferred format' '
268 git archive --format=tar --output=d4.zip HEAD &&
b93e6e36 269 test_cmp_bin b.tar d4.zip
fe12d8e8
RS
270'
271
00436bf1
JS
272test_expect_success GZIP 'git archive with --output and --remote creates .tgz' '
273 git archive --output=d5.tgz --remote=. HEAD &&
274 gzip -d -c <d5.tgz >d5.tar &&
275 test_cmp_bin b.tar d5.tar
276'
277
eb0224c6
JH
278test_expect_success 'git archive --list outside of a git repo' '
279 nongit git archive --list
280'
281
282test_expect_success 'git archive --remote outside of a git repo' '
283 git archive HEAD >expect.tar &&
284 nongit git archive --remote="$PWD" HEAD >actual.tar &&
285 test_cmp_bin expect.tar actual.tar
286'
265d5280 287
ee27ca4a
JK
288test_expect_success 'clients cannot access unreachable commits' '
289 test_commit unreachable &&
f5efd519 290 sha1=$(git rev-parse HEAD) &&
ee27ca4a
JK
291 git reset --hard HEAD^ &&
292 git archive $sha1 >remote.tar &&
293 test_must_fail git archive --remote=. $sha1 >remote.tar
294'
295
7671b632
SG
296test_expect_success 'upload-archive can allow unreachable commits' '
297 test_commit unreachable1 &&
f5efd519 298 sha1=$(git rev-parse HEAD) &&
7671b632
SG
299 git reset --hard HEAD^ &&
300 git archive $sha1 >remote.tar &&
301 test_config uploadarchive.allowUnreachable true &&
302 git archive --remote=. $sha1 >remote.tar
303'
304
767cf457
JK
305test_expect_success 'setup tar filters' '
306 git config tar.tar.foo.command "tr ab ba" &&
7b97730b 307 git config tar.bar.command "tr ab ba" &&
785a0429
JK
308 git config tar.bar.remote true &&
309 git config tar.invalid baz
767cf457
JK
310'
311
312test_expect_success 'archive --list mentions user filter' '
313 git archive --list >output &&
314 grep "^tar\.foo\$" output &&
315 grep "^bar\$" output
316'
317
1bc01efe 318test_expect_success 'archive --list shows only enabled remote filters' '
767cf457 319 git archive --list --remote=. >output &&
7b97730b 320 ! grep "^tar\.foo\$" output &&
767cf457
JK
321 grep "^bar\$" output
322'
323
324test_expect_success 'invoke tar filter by format' '
325 git archive --format=tar.foo HEAD >config.tar.foo &&
326 tr ab ba <config.tar.foo >config.tar &&
b93e6e36 327 test_cmp_bin b.tar config.tar &&
767cf457
JK
328 git archive --format=bar HEAD >config.bar &&
329 tr ab ba <config.bar >config.tar &&
b93e6e36 330 test_cmp_bin b.tar config.tar
767cf457
JK
331'
332
333test_expect_success 'invoke tar filter by extension' '
334 git archive -o config-implicit.tar.foo HEAD &&
b93e6e36 335 test_cmp_bin config.tar.foo config-implicit.tar.foo &&
767cf457 336 git archive -o config-implicit.bar HEAD &&
b93e6e36 337 test_cmp_bin config.tar.foo config-implicit.bar
767cf457
JK
338'
339
340test_expect_success 'default output format remains tar' '
341 git archive -o config-implicit.baz HEAD &&
b93e6e36 342 test_cmp_bin b.tar config-implicit.baz
767cf457
JK
343'
344
345test_expect_success 'extension matching requires dot' '
346 git archive -o config-implicittar.foo HEAD &&
b93e6e36 347 test_cmp_bin b.tar config-implicittar.foo
767cf457
JK
348'
349
1bc01efe 350test_expect_success 'only enabled filters are available remotely' '
7b97730b
JK
351 test_must_fail git archive --remote=. --format=tar.foo HEAD \
352 >remote.tar.foo &&
353 git archive --remote=. --format=bar >remote.bar HEAD &&
b93e6e36 354 test_cmp_bin remote.bar config.bar
7b97730b
JK
355'
356
1e4ea950
RS
357test_expect_success 'invalid filter is reported only once' '
358 test_must_fail git -c tar.invalid.command= archive --format=invalid \
359 HEAD >out 2>err &&
360 test_must_be_empty out &&
361 test_line_count = 1 err
362'
363
4f4be00d 364test_expect_success 'git archive --format=tgz' '
0e804e09
JK
365 git archive --format=tgz HEAD >j.tgz
366'
367
4f4be00d 368test_expect_success 'git archive --format=tar.gz' '
0e804e09 369 git archive --format=tar.gz HEAD >j1.tar.gz &&
b93e6e36 370 test_cmp_bin j.tgz j1.tar.gz
0e804e09
JK
371'
372
4f4be00d 373test_expect_success 'infer tgz from .tgz filename' '
0e804e09 374 git archive --output=j2.tgz HEAD &&
b93e6e36 375 test_cmp_bin j.tgz j2.tgz
0e804e09
JK
376'
377
4f4be00d 378test_expect_success 'infer tgz from .tar.gz filename' '
0e804e09 379 git archive --output=j3.tar.gz HEAD &&
b93e6e36 380 test_cmp_bin j.tgz j3.tar.gz
0e804e09
JK
381'
382
96174145
JK
383test_expect_success GZIP 'extract tgz file' '
384 gzip -d -c <j.tgz >j.tar &&
b93e6e36 385 test_cmp_bin b.tar j.tar
0e804e09
JK
386'
387
4f4be00d 388test_expect_success 'remote tar.gz is allowed by default' '
7b97730b 389 git archive --remote=. --format=tar.gz HEAD >remote.tar.gz &&
b93e6e36 390 test_cmp_bin j.tgz remote.tar.gz
7b97730b
JK
391'
392
4f4be00d 393test_expect_success 'remote tar.gz can be disabled' '
7b97730b
JK
394 git config tar.tar.gz.remote false &&
395 test_must_fail git archive --remote=. --format=tar.gz HEAD \
396 >remote.tar.gz
397'
398
4f4be00d
RS
399test_expect_success GZIP 'git archive --format=tgz (external gzip)' '
400 test_config tar.tgz.command "gzip -cn" &&
401 git archive --format=tgz HEAD >external_gzip.tgz
76d76026
RS
402'
403
4f4be00d
RS
404test_expect_success GZIP 'git archive --format=tar.gz (external gzip)' '
405 test_config tar.tar.gz.command "gzip -cn" &&
406 git archive --format=tar.gz HEAD >external_gzip.tar.gz &&
407 test_cmp_bin external_gzip.tgz external_gzip.tar.gz
76d76026
RS
408'
409
4f4be00d
RS
410test_expect_success GZIP 'extract tgz file (external gzip)' '
411 gzip -d -c <external_gzip.tgz >external_gzip.tar &&
412 test_cmp_bin b.tar external_gzip.tar
76d76026
RS
413'
414
ed22b417
NTND
415test_expect_success 'archive and :(glob)' '
416 git archive -v HEAD -- ":(glob)**/sh" >/dev/null 2>actual &&
d912a603
KF
417 cat >expect <<-\EOF &&
418 a/
419 a/bin/
420 a/bin/sh
421 EOF
ed22b417
NTND
422 test_cmp expect actual
423'
424
425test_expect_success 'catch non-matching pathspec' '
426 test_must_fail git archive -v HEAD -- "*.abc" >/dev/null
427'
428
92b1dd1b
RS
429test_expect_success 'reject paths outside the current directory' '
430 test_must_fail git -C a/bin archive HEAD .. >/dev/null 2>err &&
431 grep "outside the current directory" err
432'
433
434test_expect_success 'allow pathspecs that resolve to the current directory' '
435 git -C a/bin archive -v HEAD ../bin >/dev/null 2>actual &&
436 cat >expect <<-\EOF &&
437 sh
438 EOF
439 test_cmp expect actual
440'
441
e51217e1
JK
442# Pull the size and date of each entry in a tarfile using the system tar.
443#
444# We'll pull out only the year from the date; that avoids any question of
445# timezones impacting the result (as long as we keep our test times away from a
446# year boundary; our reference times are all in August).
447#
448# The output of tar_info is expected to be "<size> <year>", both in decimal. It
449# ignores the return value of tar. We have to do this, because some of our test
450# input is only partial (the real data is 64GB in some cases).
451tar_info () {
452 "$TAR" tvf "$1" |
453 awk '{
454 split($4, date, "-")
455 print $3 " " date[1]
456 }'
457}
458
459# See if our system tar can handle a tar file with huge sizes and dates far in
460# the future, and that we can actually parse its output.
461#
462# The reference file was generated by GNU tar, and the magic time and size are
463# both octal 01000000000001, which overflows normal ustar fields.
464test_lazy_prereq TAR_HUGE '
465 echo "68719476737 4147" >expect &&
466 tar_info "$TEST_DIRECTORY"/t5000/huge-and-future.tar >actual &&
467 test_cmp expect actual
468'
469
29493589 470test_expect_success LONG_IS_64BIT 'set up repository with huge blob' '
0b78a1b2 471 obj=$(test_oid obj) &&
472 path=$(test_oid_to_path $obj) &&
473 mkdir -p .git/objects/$(dirname $path) &&
474 cp "$TEST_DIRECTORY"/t5000/huge-object .git/objects/$path &&
e51217e1
JK
475 rm -f .git/index &&
476 git update-index --add --cacheinfo 100644,$obj,huge &&
477 git commit -m huge
478'
479
480# We expect git to die with SIGPIPE here (otherwise we
481# would generate the whole 64GB).
29493589 482test_expect_success LONG_IS_64BIT 'generate tar with huge size' '
e51217e1
JK
483 {
484 git archive HEAD
485 echo $? >exit-code
486 } | test_copy_bytes 4096 >huge.tar &&
487 echo 141 >expect &&
488 test_cmp expect exit-code
489'
490
29493589 491test_expect_success TAR_HUGE,LONG_IS_64BIT 'system tar can read our huge size' '
e51217e1
JK
492 echo 68719476737 >expect &&
493 tar_info huge.tar | cut -d" " -f1 >actual &&
494 test_cmp expect actual
495'
496
f90fca63
AK
497test_expect_success TIME_IS_64BIT 'set up repository with far-future (2^34 - 1) commit' '
498 rm -f .git/index &&
499 echo foo >file &&
500 git add file &&
501 GIT_COMMITTER_DATE="@17179869183 +0000" \
502 git commit -m "tempori parendum"
503'
504
505test_expect_success TIME_IS_64BIT 'generate tar with far-future mtime' '
506 git archive HEAD >future.tar
507'
508
509test_expect_success TAR_HUGE,TIME_IS_64BIT,TIME_T_IS_64BIT 'system tar can read our future mtime' '
510 echo 2514 >expect &&
511 tar_info future.tar | cut -d" " -f2 >actual &&
512 test_cmp expect actual
513'
514
515test_expect_success TIME_IS_64BIT 'set up repository with far-far-future (2^36 + 1) commit' '
e51217e1
JK
516 rm -f .git/index &&
517 echo content >file &&
518 git add file &&
f90fca63 519 GIT_TEST_COMMIT_GRAPH=0 GIT_COMMITTER_DATE="@68719476737 +0000" \
e51217e1
JK
520 git commit -m "tempori parendum"
521'
522
f90fca63 523test_expect_success TIME_IS_64BIT 'generate tar with far-far-future mtime' '
e51217e1
JK
524 git archive HEAD >future.tar
525'
526
efac8ac8 527test_expect_success TAR_HUGE,TIME_IS_64BIT,TIME_T_IS_64BIT 'system tar can read our future mtime' '
e51217e1
JK
528 echo 4147 >expect &&
529 tar_info future.tar | cut -d" " -f2 >actual &&
530 test_cmp expect actual
531'
532
d3d49c3d 533test_done