Sync with 2.44.1
[git/gitster.git] / t / t5000-tar-tree.sh
blob72b8d0ff02e34be0606747c850b0815be31196d4
1 #!/bin/sh
3 # Copyright (C) 2005 Rene Scharfe
6 test_description='git archive and git get-tar-commit-id test
8 This test covers the topics of file contents, commit date handling and
9 commit id embedding:
11 The contents of the repository is compared to the extracted tar
12 archive. The repository contains simple text files, symlinks and a
13 binary file (/bin/sh). Only paths shorter than 99 characters are
14 used.
16 git archive applies the commit date to every file in the archive it
17 creates. The test sets the commit date to a specific value and checks
18 if the tar archive contains that value.
20 When giving git archive a commit id (in contrast to a tree id) it
21 embeds this commit id into the tar archive as a comment. The test
22 checks the ability of git get-tar-commit-id to figure it out from the
23 tar file.
27 TEST_CREATE_REPO_NO_TEMPLATE=1
28 . ./test-lib.sh
30 SUBSTFORMAT=%H%n
32 test_lazy_prereq TAR_NEEDS_PAX_FALLBACK '
34 mkdir pax &&
35 cd pax &&
36 "$TAR" xf "$TEST_DIRECTORY"/t5000/pax.tar &&
37 test -f PaxHeaders.1791/file
41 test_lazy_prereq GZIP 'gzip --version'
43 get_pax_header() {
44 file=$1
45 header=$2=
47 while read len rest
49 if test "$len" = $(echo "$len $rest" | wc -c)
50 then
51 case "$rest" in
52 $header*)
53 echo "${rest#$header}"
55 esac
57 done <"$file"
60 check_tar() {
61 tarfile=$1.tar
62 listfile=$1.lst
63 dir=$1
64 dir_with_prefix=$dir/$2
66 test_expect_success ' extract tar archive' '
67 (mkdir $dir && cd $dir && "$TAR" xf -) <$tarfile
70 test_expect_success TAR_NEEDS_PAX_FALLBACK ' interpret pax headers' '
72 cd $dir &&
73 for header in *.paxheader
75 data=${header%.paxheader}.data &&
76 if test -h $data || test -e $data
77 then
78 path=$(get_pax_header $header path) &&
79 if test -n "$path"
80 then
81 mv "$data" "$path" || exit 1
84 done
88 test_expect_success ' validate filenames' '
89 (cd ${dir_with_prefix}a && find .) | sort >$listfile &&
90 test_cmp a.lst $listfile
93 test_expect_success ' validate file contents' '
94 diff -r a ${dir_with_prefix}a
98 check_added() {
99 dir=$1
100 path_in_fs=$2
101 path_in_archive=$3
103 test_expect_success " validate extra file $path_in_archive" '
104 diff -r $path_in_fs $dir/$path_in_archive
108 check_mtime() {
109 dir=$1
110 path_in_archive=$2
111 mtime=$3
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
120 test_expect_success 'setup' '
121 test_oid_cache <<-EOF
122 obj sha1:19f9c8273ec45a8938e6999cb59b3ff66739902a
123 obj sha256:3c666f798798601571f5cec0adb57ce4aba8546875e7693177e0535f34d2c49b
127 test_expect_success '--list notices extra parameters' '
128 test_must_fail git archive --list blah &&
129 test_must_fail git archive --remote=. --list blah
132 test_expect_success 'end-of-options is correctly eaten' '
133 git archive --list --end-of-options &&
134 git archive --remote=. --list --end-of-options
137 test_expect_success 'populate workdir' '
138 mkdir a &&
139 echo simple textfile >a/a &&
140 ten=0123456789 &&
141 hundred="$ten$ten$ten$ten$ten$ten$ten$ten$ten$ten" &&
142 echo long filename >"a/four$hundred" &&
143 mkdir a/bin &&
144 test-tool genrandom "frotz" 500000 >a/bin/sh &&
145 printf "A\$Format:%s\$O" "$SUBSTFORMAT" >a/substfile1 &&
146 printf "A not substituted O" >a/substfile2 &&
147 if test_have_prereq SYMLINKS
148 then
149 ln -s a a/l1
150 else
151 printf %s a >a/l1
152 fi &&
154 p=long_path_to_a_file &&
155 cd a &&
156 for depth in 1 2 3 4 5
158 mkdir $p &&
159 cd $p || exit 1
160 done &&
161 echo text >file_with_long_path
162 ) &&
163 (cd a && find .) | sort >a.lst
166 test_expect_success \
167 'add ignored file' \
168 'echo ignore me >a/ignored &&
169 mkdir .git/info &&
170 echo ignored export-ignore >.git/info/attributes'
172 test_expect_success 'add files to repository' '
173 git add a &&
174 GIT_COMMITTER_DATE="2005-05-27 22:00" git commit -m initial
177 test_expect_success 'setup export-subst' '
178 echo "substfile?" export-subst >>.git/info/attributes &&
179 git log --max-count=1 "--pretty=format:A${SUBSTFORMAT}O" HEAD \
180 >a/substfile1
183 test_expect_success 'create bare clone' '
184 git clone --template= --bare . bare.git &&
185 mkdir bare.git/info &&
186 cp .git/info/attributes bare.git/info/attributes
189 test_expect_success 'remove ignored file' '
190 rm a/ignored
193 test_expect_success 'git archive' '
194 git archive HEAD >b.tar
197 check_tar b
198 check_mtime b a/a 1117231200
200 test_expect_success 'git archive --mtime' '
201 git archive --mtime=2002-02-02T02:02:02-0200 HEAD >with_mtime.tar
204 check_tar with_mtime
205 check_mtime with_mtime a/a 1012622522
207 test_expect_success 'git archive --prefix=prefix/' '
208 git archive --prefix=prefix/ HEAD >with_prefix.tar
211 check_tar with_prefix prefix/
213 test_expect_success 'git-archive --prefix=olde-' '
214 git archive --prefix=olde- HEAD >with_olde-prefix.tar
217 check_tar with_olde-prefix olde-
219 test_expect_success 'git archive --add-file' '
220 echo untracked >untracked &&
221 git archive --add-file=untracked HEAD >with_untracked.tar
224 check_tar with_untracked
225 check_added with_untracked untracked untracked
227 test_expect_success 'git archive --add-file twice' '
228 echo untracked >untracked &&
229 git archive --prefix=one/ --add-file=untracked \
230 --prefix=two/ --add-file=untracked \
231 --prefix= HEAD >with_untracked2.tar
234 check_tar with_untracked2
235 check_added with_untracked2 untracked one/untracked
236 check_added with_untracked2 untracked two/untracked
238 test_expect_success 'git archive on large files' '
239 test_config core.bigfilethreshold 1 &&
240 git archive HEAD >b3.tar &&
241 test_cmp_bin b.tar b3.tar
244 test_expect_success 'git archive in a bare repo' '
245 git --git-dir bare.git archive HEAD >b3.tar
248 test_expect_success 'git archive vs. the same in a bare repo' '
249 test_cmp_bin b.tar b3.tar
252 test_expect_success 'git archive with --output' '
253 git archive --output=b4.tar HEAD &&
254 test_cmp_bin b.tar b4.tar
257 test_expect_success 'git archive --remote' '
258 git archive --remote=. HEAD >b5.tar &&
259 test_cmp_bin b.tar b5.tar
262 test_expect_success 'git archive --remote with configured remote' '
263 git config remote.foo.url . &&
265 cd a &&
266 git archive --remote=foo --output=../b5-nick.tar HEAD
267 ) &&
268 test_cmp_bin b.tar b5-nick.tar
271 test_expect_success 'git get-tar-commit-id' '
272 git get-tar-commit-id <b.tar >actual &&
273 git rev-parse HEAD >expect &&
274 test_cmp expect actual
277 test_expect_success 'git archive with --output, override inferred format' '
278 git archive --format=tar --output=d4.zip HEAD &&
279 test_cmp_bin b.tar d4.zip
282 test_expect_success GZIP 'git archive with --output and --remote creates .tgz' '
283 git archive --output=d5.tgz --remote=. HEAD &&
284 gzip -d -c <d5.tgz >d5.tar &&
285 test_cmp_bin b.tar d5.tar
288 test_expect_success 'git archive --list outside of a git repo' '
289 nongit git archive --list
292 test_expect_success 'git archive --remote outside of a git repo' '
293 git archive HEAD >expect.tar &&
294 nongit git archive --remote="$PWD" HEAD >actual.tar &&
295 test_cmp_bin expect.tar actual.tar
298 test_expect_success 'clients cannot access unreachable commits' '
299 test_commit unreachable &&
300 sha1=$(git rev-parse HEAD) &&
301 git reset --hard HEAD^ &&
302 git archive $sha1 >remote.tar &&
303 test_must_fail git archive --remote=. $sha1 >remote.tar
306 test_expect_success 'upload-archive can allow unreachable commits' '
307 test_commit unreachable1 &&
308 sha1=$(git rev-parse HEAD) &&
309 git reset --hard HEAD^ &&
310 git archive $sha1 >remote.tar &&
311 test_config uploadarchive.allowUnreachable true &&
312 git archive --remote=. $sha1 >remote.tar
315 test_expect_success 'setup tar filters' '
316 git config tar.tar.foo.command "tr ab ba" &&
317 git config tar.bar.command "tr ab ba" &&
318 git config tar.bar.remote true &&
319 git config tar.invalid baz
322 test_expect_success 'archive --list mentions user filter' '
323 git archive --list >output &&
324 grep "^tar\.foo\$" output &&
325 grep "^bar\$" output
328 test_expect_success 'archive --list shows only enabled remote filters' '
329 git archive --list --remote=. >output &&
330 ! grep "^tar\.foo\$" output &&
331 grep "^bar\$" output
334 test_expect_success 'invoke tar filter by format' '
335 git archive --format=tar.foo HEAD >config.tar.foo &&
336 tr ab ba <config.tar.foo >config.tar &&
337 test_cmp_bin b.tar config.tar &&
338 git archive --format=bar HEAD >config.bar &&
339 tr ab ba <config.bar >config.tar &&
340 test_cmp_bin b.tar config.tar
343 test_expect_success 'invoke tar filter by extension' '
344 git archive -o config-implicit.tar.foo HEAD &&
345 test_cmp_bin config.tar.foo config-implicit.tar.foo &&
346 git archive -o config-implicit.bar HEAD &&
347 test_cmp_bin config.tar.foo config-implicit.bar
350 test_expect_success 'default output format remains tar' '
351 git archive -o config-implicit.baz HEAD &&
352 test_cmp_bin b.tar config-implicit.baz
355 test_expect_success 'extension matching requires dot' '
356 git archive -o config-implicittar.foo HEAD &&
357 test_cmp_bin b.tar config-implicittar.foo
360 test_expect_success 'only enabled filters are available remotely' '
361 test_must_fail git archive --remote=. --format=tar.foo HEAD \
362 >remote.tar.foo &&
363 git archive --remote=. --format=bar >remote.bar HEAD &&
364 test_cmp_bin remote.bar config.bar
367 test_expect_success 'invalid filter is reported only once' '
368 test_must_fail git -c tar.invalid.command= archive --format=invalid \
369 HEAD >out 2>err &&
370 test_must_be_empty out &&
371 test_line_count = 1 err
374 test_expect_success 'git archive --format=tgz' '
375 git archive --format=tgz HEAD >j.tgz
378 test_expect_success 'git archive --format=tar.gz' '
379 git archive --format=tar.gz HEAD >j1.tar.gz &&
380 test_cmp_bin j.tgz j1.tar.gz
383 test_expect_success 'infer tgz from .tgz filename' '
384 git archive --output=j2.tgz HEAD &&
385 test_cmp_bin j.tgz j2.tgz
388 test_expect_success 'infer tgz from .tar.gz filename' '
389 git archive --output=j3.tar.gz HEAD &&
390 test_cmp_bin j.tgz j3.tar.gz
393 test_expect_success GZIP 'extract tgz file' '
394 gzip -d -c <j.tgz >j.tar &&
395 test_cmp_bin b.tar j.tar
398 test_expect_success 'remote tar.gz is allowed by default' '
399 git archive --remote=. --format=tar.gz HEAD >remote.tar.gz &&
400 test_cmp_bin j.tgz remote.tar.gz
403 test_expect_success 'remote tar.gz can be disabled' '
404 git config tar.tar.gz.remote false &&
405 test_must_fail git archive --remote=. --format=tar.gz HEAD \
406 >remote.tar.gz
409 test_expect_success GZIP 'git archive --format=tgz (external gzip)' '
410 test_config tar.tgz.command "gzip -cn" &&
411 git archive --format=tgz HEAD >external_gzip.tgz
414 test_expect_success GZIP 'git archive --format=tar.gz (external gzip)' '
415 test_config tar.tar.gz.command "gzip -cn" &&
416 git archive --format=tar.gz HEAD >external_gzip.tar.gz &&
417 test_cmp_bin external_gzip.tgz external_gzip.tar.gz
420 test_expect_success GZIP 'extract tgz file (external gzip)' '
421 gzip -d -c <external_gzip.tgz >external_gzip.tar &&
422 test_cmp_bin b.tar external_gzip.tar
425 test_expect_success 'archive and :(glob)' '
426 git archive -v HEAD -- ":(glob)**/sh" >/dev/null 2>actual &&
427 cat >expect <<-\EOF &&
429 a/bin/
430 a/bin/sh
432 test_cmp expect actual
435 test_expect_success 'catch non-matching pathspec' '
436 test_must_fail git archive -v HEAD -- "*.abc" >/dev/null
439 test_expect_success 'reject paths outside the current directory' '
440 test_must_fail git -C a/bin archive HEAD .. >/dev/null 2>err &&
441 grep "outside the current directory" err
444 test_expect_success 'allow pathspecs that resolve to the current directory' '
445 git -C a/bin archive -v HEAD ../bin >/dev/null 2>actual &&
446 cat >expect <<-\EOF &&
449 test_cmp expect actual
452 # Pull the size and date of each entry in a tarfile using the system tar.
454 # We'll pull out only the year from the date; that avoids any question of
455 # timezones impacting the result (as long as we keep our test times away from a
456 # year boundary; our reference times are all in August).
458 # The output of tar_info is expected to be "<size> <year>", both in decimal. It
459 # ignores the return value of tar. We have to do this, because some of our test
460 # input is only partial (the real data is 64GB in some cases).
461 tar_info () {
462 "$TAR" tvf "$1" |
463 awk '{
464 split($4, date, "-")
465 print $3 " " date[1]
469 # See if our system tar can handle a tar file with huge sizes and dates far in
470 # the future, and that we can actually parse its output.
472 # The reference file was generated by GNU tar, and the magic time and size are
473 # both octal 01000000000001, which overflows normal ustar fields.
474 test_lazy_prereq TAR_HUGE '
475 echo "68719476737 4147" >expect &&
476 tar_info "$TEST_DIRECTORY"/t5000/huge-and-future.tar >actual &&
477 test_cmp expect actual
480 test_expect_success LONG_IS_64BIT 'set up repository with huge blob' '
481 obj=$(test_oid obj) &&
482 path=$(test_oid_to_path $obj) &&
483 mkdir -p .git/objects/$(dirname $path) &&
484 cp "$TEST_DIRECTORY"/t5000/huge-object .git/objects/$path &&
485 rm -f .git/index &&
486 git update-index --add --cacheinfo 100644,$obj,huge &&
487 git commit -m huge
490 # We expect git to die with SIGPIPE here (otherwise we
491 # would generate the whole 64GB).
492 test_expect_success LONG_IS_64BIT 'generate tar with huge size' '
494 git archive HEAD
495 echo $? >exit-code
496 } | test_copy_bytes 4096 >huge.tar &&
497 echo 141 >expect &&
498 test_cmp expect exit-code
501 test_expect_success TAR_HUGE,LONG_IS_64BIT 'system tar can read our huge size' '
502 echo 68719476737 >expect &&
503 tar_info huge.tar | cut -d" " -f1 >actual &&
504 test_cmp expect actual
507 test_expect_success TIME_IS_64BIT 'set up repository with far-future (2^34 - 1) commit' '
508 rm -f .git/index &&
509 echo foo >file &&
510 git add file &&
511 GIT_COMMITTER_DATE="@17179869183 +0000" \
512 git commit -m "tempori parendum"
515 test_expect_success TIME_IS_64BIT 'generate tar with far-future mtime' '
516 git archive HEAD >future.tar
519 test_expect_success TAR_HUGE,TIME_IS_64BIT,TIME_T_IS_64BIT 'system tar can read our future mtime' '
520 echo 2514 >expect &&
521 tar_info future.tar | cut -d" " -f2 >actual &&
522 test_cmp expect actual
525 test_expect_success TIME_IS_64BIT 'set up repository with far-far-future (2^36 + 1) commit' '
526 rm -f .git/index &&
527 echo content >file &&
528 git add file &&
529 GIT_TEST_COMMIT_GRAPH=0 GIT_COMMITTER_DATE="@68719476737 +0000" \
530 git commit -m "tempori parendum"
533 test_expect_success TIME_IS_64BIT 'generate tar with far-far-future mtime' '
534 git archive HEAD >future.tar
537 test_expect_success TAR_HUGE,TIME_IS_64BIT,TIME_T_IS_64BIT 'system tar can read our future mtime' '
538 echo 4147 >expect &&
539 tar_info future.tar | cut -d" " -f2 >actual &&
540 test_cmp expect actual
543 test_done