Sync with 'maint'
[alt-git.git] / t / t5000-tar-tree.sh
blobb9fda973f7bfbfcfc5e6395ffaca1c3857f84e01
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_PASSES_SANITIZE_LEAK=true
29 . ./test-lib.sh
31 SUBSTFORMAT=%H%n
33 test_lazy_prereq TAR_NEEDS_PAX_FALLBACK '
35 mkdir pax &&
36 cd pax &&
37 "$TAR" xf "$TEST_DIRECTORY"/t5000/pax.tar &&
38 test -f PaxHeaders.1791/file
42 test_lazy_prereq GZIP 'gzip --version'
44 get_pax_header() {
45 file=$1
46 header=$2=
48 while read len rest
50 if test "$len" = $(echo "$len $rest" | wc -c)
51 then
52 case "$rest" in
53 $header*)
54 echo "${rest#$header}"
56 esac
58 done <"$file"
61 check_tar() {
62 tarfile=$1.tar
63 listfile=$1.lst
64 dir=$1
65 dir_with_prefix=$dir/$2
67 test_expect_success ' extract tar archive' '
68 (mkdir $dir && cd $dir && "$TAR" xf -) <$tarfile
71 test_expect_success TAR_NEEDS_PAX_FALLBACK ' interpret pax headers' '
73 cd $dir &&
74 for header in *.paxheader
76 data=${header%.paxheader}.data &&
77 if test -h $data || test -e $data
78 then
79 path=$(get_pax_header $header path) &&
80 if test -n "$path"
81 then
82 mv "$data" "$path" || exit 1
85 done
89 test_expect_success ' validate filenames' '
90 (cd ${dir_with_prefix}a && find .) | sort >$listfile &&
91 test_cmp a.lst $listfile
94 test_expect_success ' validate file contents' '
95 diff -r a ${dir_with_prefix}a
99 check_added() {
100 dir=$1
101 path_in_fs=$2
102 path_in_archive=$3
104 test_expect_success " validate extra file $path_in_archive" '
105 diff -r $path_in_fs $dir/$path_in_archive
109 check_mtime() {
110 dir=$1
111 path_in_archive=$2
112 mtime=$3
114 test_expect_success " validate mtime of $path_in_archive" '
115 test-tool chmtime --get $dir/$path_in_archive >actual.mtime &&
116 echo $mtime >expect.mtime &&
117 test_cmp expect.mtime actual.mtime
121 test_expect_success 'setup' '
122 test_oid_cache <<-EOF
123 obj sha1:19f9c8273ec45a8938e6999cb59b3ff66739902a
124 obj sha256:3c666f798798601571f5cec0adb57ce4aba8546875e7693177e0535f34d2c49b
128 test_expect_success '--list notices extra parameters' '
129 test_must_fail git archive --list blah &&
130 test_must_fail git archive --remote=. --list blah
133 test_expect_success 'end-of-options is correctly eaten' '
134 git archive --list --end-of-options &&
135 git archive --remote=. --list --end-of-options
138 test_expect_success 'populate workdir' '
139 mkdir a &&
140 echo "a files_named_a" >.gitattributes &&
141 git add .gitattributes &&
142 echo simple textfile >a/a &&
143 ten=0123456789 &&
144 hundred="$ten$ten$ten$ten$ten$ten$ten$ten$ten$ten" &&
145 echo long filename >"a/four$hundred" &&
146 mkdir a/bin &&
147 test-tool genrandom "frotz" 500000 >a/bin/sh &&
148 printf "A\$Format:%s\$O" "$SUBSTFORMAT" >a/substfile1 &&
149 printf "A not substituted O" >a/substfile2 &&
150 if test_have_prereq SYMLINKS
151 then
152 ln -s a a/l1
153 else
154 printf %s a >a/l1
155 fi &&
157 p=long_path_to_a_file &&
158 cd a &&
159 for depth in 1 2 3 4 5
161 mkdir $p &&
162 cd $p || exit 1
163 done &&
164 echo text >file_with_long_path
165 ) &&
166 (cd a && find .) | sort >a.lst
169 test_expect_success \
170 'add ignored file' \
171 'echo ignore me >a/ignored &&
172 mkdir .git/info &&
173 echo ignored export-ignore >.git/info/attributes'
175 test_expect_success 'add files to repository' '
176 git add a &&
177 GIT_COMMITTER_DATE="2005-05-27 22:00" git commit -m initial
180 test_expect_success 'setup export-subst' '
181 echo "substfile?" export-subst >>.git/info/attributes &&
182 git log --max-count=1 "--pretty=format:A${SUBSTFORMAT}O" HEAD \
183 >a/substfile1
186 test_expect_success 'create bare clone' '
187 git clone --template= --bare . bare.git &&
188 mkdir bare.git/info &&
189 cp .git/info/attributes bare.git/info/attributes
192 test_expect_success 'remove ignored file' '
193 rm a/ignored
196 test_expect_success 'git archive' '
197 git archive HEAD >b.tar
200 check_tar b
201 check_mtime b a/a 1117231200
203 test_expect_success 'git archive --mtime' '
204 git archive --mtime=2002-02-02T02:02:02-0200 HEAD >with_mtime.tar
207 check_tar with_mtime
208 check_mtime with_mtime a/a 1012622522
210 test_expect_success 'git archive --prefix=prefix/' '
211 git archive --prefix=prefix/ HEAD >with_prefix.tar
214 check_tar with_prefix prefix/
216 test_expect_success 'git-archive --prefix=olde-' '
217 git archive --prefix=olde- HEAD >with_olde-prefix.tar
220 check_tar with_olde-prefix olde-
222 test_expect_success 'git archive --add-file' '
223 echo untracked >untracked &&
224 git archive --add-file=untracked HEAD >with_untracked.tar
227 check_tar with_untracked
228 check_added with_untracked untracked untracked
230 test_expect_success 'git archive --add-file twice' '
231 echo untracked >untracked &&
232 git archive --prefix=one/ --add-file=untracked \
233 --prefix=two/ --add-file=untracked \
234 --prefix= HEAD >with_untracked2.tar
237 check_tar with_untracked2
238 check_added with_untracked2 untracked one/untracked
239 check_added with_untracked2 untracked two/untracked
241 test_expect_success 'git archive on large files' '
242 test_config core.bigfilethreshold 1 &&
243 git archive HEAD >b3.tar &&
244 test_cmp_bin b.tar b3.tar
247 test_expect_success 'git archive in a bare repo' '
248 git --git-dir bare.git archive HEAD >b3.tar
251 test_expect_success 'git archive vs. the same in a bare repo' '
252 test_cmp_bin b.tar b3.tar
255 test_expect_success 'git archive with --output' '
256 git archive --output=b4.tar HEAD &&
257 test_cmp_bin b.tar b4.tar
260 test_expect_success 'git archive --remote' '
261 git archive --remote=. HEAD >b5.tar &&
262 test_cmp_bin b.tar b5.tar
265 test_expect_success 'git archive --remote with configured remote' '
266 git config remote.foo.url . &&
268 cd a &&
269 git archive --remote=foo --output=../b5-nick.tar HEAD
270 ) &&
271 test_cmp_bin b.tar b5-nick.tar
274 test_expect_success 'git get-tar-commit-id' '
275 git get-tar-commit-id <b.tar >actual &&
276 git rev-parse HEAD >expect &&
277 test_cmp expect actual
280 test_expect_success 'git archive with --output, override inferred format' '
281 git archive --format=tar --output=d4.zip HEAD &&
282 test_cmp_bin b.tar d4.zip
285 test_expect_success GZIP 'git archive with --output and --remote creates .tgz' '
286 git archive --output=d5.tgz --remote=. HEAD &&
287 gzip -d -c <d5.tgz >d5.tar &&
288 test_cmp_bin b.tar d5.tar
291 test_expect_success 'git archive --list outside of a git repo' '
292 nongit git archive --list
295 test_expect_success 'git archive --remote outside of a git repo' '
296 git archive HEAD >expect.tar &&
297 nongit git archive --remote="$PWD" HEAD >actual.tar &&
298 test_cmp_bin expect.tar actual.tar
301 test_expect_success 'clients cannot access unreachable commits' '
302 test_commit unreachable &&
303 sha1=$(git rev-parse HEAD) &&
304 git reset --hard HEAD^ &&
305 git archive $sha1 >remote.tar &&
306 test_must_fail git archive --remote=. $sha1 >remote.tar
309 test_expect_success 'upload-archive can allow unreachable commits' '
310 test_commit unreachable1 &&
311 sha1=$(git rev-parse HEAD) &&
312 git reset --hard HEAD^ &&
313 git archive $sha1 >remote.tar &&
314 test_config uploadarchive.allowUnreachable true &&
315 git archive --remote=. $sha1 >remote.tar
318 test_expect_success 'setup tar filters' '
319 git config tar.tar.foo.command "tr ab ba" &&
320 git config tar.bar.command "tr ab ba" &&
321 git config tar.bar.remote true &&
322 git config tar.invalid baz
325 test_expect_success 'archive --list mentions user filter' '
326 git archive --list >output &&
327 grep "^tar\.foo\$" output &&
328 grep "^bar\$" output
331 test_expect_success 'archive --list shows only enabled remote filters' '
332 git archive --list --remote=. >output &&
333 ! grep "^tar\.foo\$" output &&
334 grep "^bar\$" output
337 test_expect_success 'invoke tar filter by format' '
338 git archive --format=tar.foo HEAD >config.tar.foo &&
339 tr ab ba <config.tar.foo >config.tar &&
340 test_cmp_bin b.tar config.tar &&
341 git archive --format=bar HEAD >config.bar &&
342 tr ab ba <config.bar >config.tar &&
343 test_cmp_bin b.tar config.tar
346 test_expect_success 'invoke tar filter by extension' '
347 git archive -o config-implicit.tar.foo HEAD &&
348 test_cmp_bin config.tar.foo config-implicit.tar.foo &&
349 git archive -o config-implicit.bar HEAD &&
350 test_cmp_bin config.tar.foo config-implicit.bar
353 test_expect_success 'default output format remains tar' '
354 git archive -o config-implicit.baz HEAD &&
355 test_cmp_bin b.tar config-implicit.baz
358 test_expect_success 'extension matching requires dot' '
359 git archive -o config-implicittar.foo HEAD &&
360 test_cmp_bin b.tar config-implicittar.foo
363 test_expect_success 'only enabled filters are available remotely' '
364 test_must_fail git archive --remote=. --format=tar.foo HEAD \
365 >remote.tar.foo &&
366 git archive --remote=. --format=bar >remote.bar HEAD &&
367 test_cmp_bin remote.bar config.bar
370 test_expect_success 'invalid filter is reported only once' '
371 test_must_fail git -c tar.invalid.command= archive --format=invalid \
372 HEAD >out 2>err &&
373 test_must_be_empty out &&
374 test_line_count = 1 err
377 test_expect_success 'git archive --format=tgz' '
378 git archive --format=tgz HEAD >j.tgz
381 test_expect_success 'git archive --format=tar.gz' '
382 git archive --format=tar.gz HEAD >j1.tar.gz &&
383 test_cmp_bin j.tgz j1.tar.gz
386 test_expect_success 'infer tgz from .tgz filename' '
387 git archive --output=j2.tgz HEAD &&
388 test_cmp_bin j.tgz j2.tgz
391 test_expect_success 'infer tgz from .tar.gz filename' '
392 git archive --output=j3.tar.gz HEAD &&
393 test_cmp_bin j.tgz j3.tar.gz
396 test_expect_success GZIP 'extract tgz file' '
397 gzip -d -c <j.tgz >j.tar &&
398 test_cmp_bin b.tar j.tar
401 test_expect_success 'remote tar.gz is allowed by default' '
402 git archive --remote=. --format=tar.gz HEAD >remote.tar.gz &&
403 test_cmp_bin j.tgz remote.tar.gz
406 test_expect_success 'remote tar.gz can be disabled' '
407 git config tar.tar.gz.remote false &&
408 test_must_fail git archive --remote=. --format=tar.gz HEAD \
409 >remote.tar.gz
412 test_expect_success GZIP 'git archive --format=tgz (external gzip)' '
413 test_config tar.tgz.command "gzip -cn" &&
414 git archive --format=tgz HEAD >external_gzip.tgz
417 test_expect_success GZIP 'git archive --format=tar.gz (external gzip)' '
418 test_config tar.tar.gz.command "gzip -cn" &&
419 git archive --format=tar.gz HEAD >external_gzip.tar.gz &&
420 test_cmp_bin external_gzip.tgz external_gzip.tar.gz
423 test_expect_success GZIP 'extract tgz file (external gzip)' '
424 gzip -d -c <external_gzip.tgz >external_gzip.tar &&
425 test_cmp_bin b.tar external_gzip.tar
428 test_expect_success 'archive and :(glob)' '
429 git archive -v HEAD -- ":(glob)**/sh" >/dev/null 2>actual &&
430 cat >expect <<-\EOF &&
432 a/bin/
433 a/bin/sh
435 test_cmp expect actual
438 test_expect_success 'catch non-matching pathspec' '
439 test_must_fail git archive -v HEAD -- "*.abc" >/dev/null
442 test_expect_success 'reject paths outside the current directory' '
443 test_must_fail git -C a/bin archive HEAD .. >/dev/null 2>err &&
444 grep "outside the current directory" err
447 test_expect_success 'allow pathspecs that resolve to the current directory' '
448 git -C a/bin archive -v HEAD ../bin >/dev/null 2>actual &&
449 cat >expect <<-\EOF &&
452 test_cmp expect actual
455 test_expect_success 'attr pathspec in bare repo' '
456 test_expect_code 0 git --git-dir=bare.git archive -v HEAD \
457 ":(attr:files_named_a)" >/dev/null 2>actual &&
458 cat >expect <<-\EOF &&
462 test_cmp expect actual
465 # Pull the size and date of each entry in a tarfile using the system tar.
467 # We'll pull out only the year from the date; that avoids any question of
468 # timezones impacting the result (as long as we keep our test times away from a
469 # year boundary; our reference times are all in August).
471 # The output of tar_info is expected to be "<size> <year>", both in decimal. It
472 # ignores the return value of tar. We have to do this, because some of our test
473 # input is only partial (the real data is 64GB in some cases).
474 tar_info () {
475 "$TAR" tvf "$1" |
476 awk '{
477 split($4, date, "-")
478 print $3 " " date[1]
482 # See if our system tar can handle a tar file with huge sizes and dates far in
483 # the future, and that we can actually parse its output.
485 # The reference file was generated by GNU tar, and the magic time and size are
486 # both octal 01000000000001, which overflows normal ustar fields.
487 test_lazy_prereq TAR_HUGE '
488 echo "68719476737 4147" >expect &&
489 tar_info "$TEST_DIRECTORY"/t5000/huge-and-future.tar >actual &&
490 test_cmp expect actual
493 test_expect_success LONG_IS_64BIT 'set up repository with huge blob' '
494 obj=$(test_oid obj) &&
495 path=$(test_oid_to_path $obj) &&
496 mkdir -p .git/objects/$(dirname $path) &&
497 cp "$TEST_DIRECTORY"/t5000/huge-object .git/objects/$path &&
498 rm -f .git/index &&
499 git update-index --add --cacheinfo 100644,$obj,huge &&
500 git commit -m huge
503 # We expect git to die with SIGPIPE here (otherwise we
504 # would generate the whole 64GB).
505 test_expect_success LONG_IS_64BIT 'generate tar with huge size' '
507 git archive HEAD
508 echo $? >exit-code
509 } | test_copy_bytes 4096 >huge.tar &&
510 echo 141 >expect &&
511 test_cmp expect exit-code
514 test_expect_success TAR_HUGE,LONG_IS_64BIT 'system tar can read our huge size' '
515 echo 68719476737 >expect &&
516 tar_info huge.tar | cut -d" " -f1 >actual &&
517 test_cmp expect actual
520 test_expect_success TIME_IS_64BIT 'set up repository with far-future (2^34 - 1) commit' '
521 rm -f .git/index &&
522 echo foo >file &&
523 git add file &&
524 GIT_COMMITTER_DATE="@17179869183 +0000" \
525 git commit -m "tempori parendum"
528 test_expect_success TIME_IS_64BIT 'generate tar with far-future mtime' '
529 git archive HEAD >future.tar
532 test_expect_success TAR_HUGE,TIME_IS_64BIT,TIME_T_IS_64BIT 'system tar can read our future mtime' '
533 echo 2514 >expect &&
534 tar_info future.tar | cut -d" " -f2 >actual &&
535 test_cmp expect actual
538 test_expect_success TIME_IS_64BIT 'set up repository with far-far-future (2^36 + 1) commit' '
539 rm -f .git/index &&
540 echo content >file &&
541 git add file &&
542 GIT_TEST_COMMIT_GRAPH=0 GIT_COMMITTER_DATE="@68719476737 +0000" \
543 git commit -m "tempori parendum"
546 test_expect_success TIME_IS_64BIT 'generate tar with far-far-future mtime' '
547 git archive HEAD >future.tar
550 test_expect_success TAR_HUGE,TIME_IS_64BIT,TIME_T_IS_64BIT 'system tar can read our future mtime' '
551 echo 4147 >expect &&
552 tar_info future.tar | cut -d" " -f2 >actual &&
553 test_cmp expect actual
556 test_done