Merge branch 'main' of github.com:git/git
[alt-git.git] / t / t5000-tar-tree.sh
blobeaa0b22ece4ff3ce7d79faed2edf8ab829c97051
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 test_expect_success 'setup' '
109 test_oid_cache <<-EOF
110 obj sha1:19f9c8273ec45a8938e6999cb59b3ff66739902a
111 obj sha256:3c666f798798601571f5cec0adb57ce4aba8546875e7693177e0535f34d2c49b
115 test_expect_success 'populate workdir' '
116 mkdir a &&
117 echo simple textfile >a/a &&
118 ten=0123456789 &&
119 hundred="$ten$ten$ten$ten$ten$ten$ten$ten$ten$ten" &&
120 echo long filename >"a/four$hundred" &&
121 mkdir a/bin &&
122 test-tool genrandom "frotz" 500000 >a/bin/sh &&
123 printf "A\$Format:%s\$O" "$SUBSTFORMAT" >a/substfile1 &&
124 printf "A not substituted O" >a/substfile2 &&
125 if test_have_prereq SYMLINKS
126 then
127 ln -s a a/l1
128 else
129 printf %s a >a/l1
130 fi &&
132 p=long_path_to_a_file &&
133 cd a &&
134 for depth in 1 2 3 4 5
136 mkdir $p &&
137 cd $p || exit 1
138 done &&
139 echo text >file_with_long_path
140 ) &&
141 (cd a && find .) | sort >a.lst
144 test_expect_success \
145 'add ignored file' \
146 'echo ignore me >a/ignored &&
147 mkdir .git/info &&
148 echo ignored export-ignore >.git/info/attributes'
150 test_expect_success 'add files to repository' '
151 git add a &&
152 GIT_COMMITTER_DATE="2005-05-27 22:00" git commit -m initial
155 test_expect_success 'setup export-subst' '
156 echo "substfile?" export-subst >>.git/info/attributes &&
157 git log --max-count=1 "--pretty=format:A${SUBSTFORMAT}O" HEAD \
158 >a/substfile1
161 test_expect_success 'create bare clone' '
162 git clone --template= --bare . bare.git &&
163 mkdir bare.git/info &&
164 cp .git/info/attributes bare.git/info/attributes
167 test_expect_success 'remove ignored file' '
168 rm a/ignored
171 test_expect_success 'git archive' '
172 git archive HEAD >b.tar
175 check_tar b
177 test_expect_success 'git archive --prefix=prefix/' '
178 git archive --prefix=prefix/ HEAD >with_prefix.tar
181 check_tar with_prefix prefix/
183 test_expect_success 'git-archive --prefix=olde-' '
184 git archive --prefix=olde- HEAD >with_olde-prefix.tar
187 check_tar with_olde-prefix olde-
189 test_expect_success 'git archive --add-file' '
190 echo untracked >untracked &&
191 git archive --add-file=untracked HEAD >with_untracked.tar
194 check_tar with_untracked
195 check_added with_untracked untracked untracked
197 test_expect_success 'git archive --add-file twice' '
198 echo untracked >untracked &&
199 git archive --prefix=one/ --add-file=untracked \
200 --prefix=two/ --add-file=untracked \
201 --prefix= HEAD >with_untracked2.tar
204 check_tar with_untracked2
205 check_added with_untracked2 untracked one/untracked
206 check_added with_untracked2 untracked two/untracked
208 test_expect_success 'git archive on large files' '
209 test_config core.bigfilethreshold 1 &&
210 git archive HEAD >b3.tar &&
211 test_cmp_bin b.tar b3.tar
214 test_expect_success 'git archive in a bare repo' '
215 git --git-dir bare.git archive HEAD >b3.tar
218 test_expect_success 'git archive vs. the same in a bare repo' '
219 test_cmp_bin b.tar b3.tar
222 test_expect_success 'git archive with --output' '
223 git archive --output=b4.tar HEAD &&
224 test_cmp_bin b.tar b4.tar
227 test_expect_success 'git archive --remote' '
228 git archive --remote=. HEAD >b5.tar &&
229 test_cmp_bin b.tar b5.tar
232 test_expect_success 'git archive --remote with configured remote' '
233 git config remote.foo.url . &&
235 cd a &&
236 git archive --remote=foo --output=../b5-nick.tar HEAD
237 ) &&
238 test_cmp_bin b.tar b5-nick.tar
241 test_expect_success 'validate file modification time' '
242 mkdir extract &&
243 "$TAR" xf b.tar -C extract a/a &&
244 test-tool chmtime --get extract/a/a >b.mtime &&
245 echo "1117231200" >expected.mtime &&
246 test_cmp expected.mtime b.mtime
249 test_expect_success 'git get-tar-commit-id' '
250 git get-tar-commit-id <b.tar >actual &&
251 git rev-parse HEAD >expect &&
252 test_cmp expect actual
255 test_expect_success 'git archive with --output, override inferred format' '
256 git archive --format=tar --output=d4.zip HEAD &&
257 test_cmp_bin b.tar d4.zip
260 test_expect_success GZIP 'git archive with --output and --remote creates .tgz' '
261 git archive --output=d5.tgz --remote=. HEAD &&
262 gzip -d -c <d5.tgz >d5.tar &&
263 test_cmp_bin b.tar d5.tar
266 test_expect_success 'git archive --list outside of a git repo' '
267 nongit git archive --list
270 test_expect_success 'git archive --remote outside of a git repo' '
271 git archive HEAD >expect.tar &&
272 nongit git archive --remote="$PWD" HEAD >actual.tar &&
273 test_cmp_bin expect.tar actual.tar
276 test_expect_success 'clients cannot access unreachable commits' '
277 test_commit unreachable &&
278 sha1=$(git rev-parse HEAD) &&
279 git reset --hard HEAD^ &&
280 git archive $sha1 >remote.tar &&
281 test_must_fail git archive --remote=. $sha1 >remote.tar
284 test_expect_success 'upload-archive can allow unreachable commits' '
285 test_commit unreachable1 &&
286 sha1=$(git rev-parse HEAD) &&
287 git reset --hard HEAD^ &&
288 git archive $sha1 >remote.tar &&
289 test_config uploadarchive.allowUnreachable true &&
290 git archive --remote=. $sha1 >remote.tar
293 test_expect_success 'setup tar filters' '
294 git config tar.tar.foo.command "tr ab ba" &&
295 git config tar.bar.command "tr ab ba" &&
296 git config tar.bar.remote true &&
297 git config tar.invalid baz
300 test_expect_success 'archive --list mentions user filter' '
301 git archive --list >output &&
302 grep "^tar\.foo\$" output &&
303 grep "^bar\$" output
306 test_expect_success 'archive --list shows only enabled remote filters' '
307 git archive --list --remote=. >output &&
308 ! grep "^tar\.foo\$" output &&
309 grep "^bar\$" output
312 test_expect_success 'invoke tar filter by format' '
313 git archive --format=tar.foo HEAD >config.tar.foo &&
314 tr ab ba <config.tar.foo >config.tar &&
315 test_cmp_bin b.tar config.tar &&
316 git archive --format=bar HEAD >config.bar &&
317 tr ab ba <config.bar >config.tar &&
318 test_cmp_bin b.tar config.tar
321 test_expect_success 'invoke tar filter by extension' '
322 git archive -o config-implicit.tar.foo HEAD &&
323 test_cmp_bin config.tar.foo config-implicit.tar.foo &&
324 git archive -o config-implicit.bar HEAD &&
325 test_cmp_bin config.tar.foo config-implicit.bar
328 test_expect_success 'default output format remains tar' '
329 git archive -o config-implicit.baz HEAD &&
330 test_cmp_bin b.tar config-implicit.baz
333 test_expect_success 'extension matching requires dot' '
334 git archive -o config-implicittar.foo HEAD &&
335 test_cmp_bin b.tar config-implicittar.foo
338 test_expect_success 'only enabled filters are available remotely' '
339 test_must_fail git archive --remote=. --format=tar.foo HEAD \
340 >remote.tar.foo &&
341 git archive --remote=. --format=bar >remote.bar HEAD &&
342 test_cmp_bin remote.bar config.bar
345 test_expect_success 'git archive --format=tgz' '
346 git archive --format=tgz HEAD >j.tgz
349 test_expect_success 'git archive --format=tar.gz' '
350 git archive --format=tar.gz HEAD >j1.tar.gz &&
351 test_cmp_bin j.tgz j1.tar.gz
354 test_expect_success 'infer tgz from .tgz filename' '
355 git archive --output=j2.tgz HEAD &&
356 test_cmp_bin j.tgz j2.tgz
359 test_expect_success 'infer tgz from .tar.gz filename' '
360 git archive --output=j3.tar.gz HEAD &&
361 test_cmp_bin j.tgz j3.tar.gz
364 test_expect_success GZIP 'extract tgz file' '
365 gzip -d -c <j.tgz >j.tar &&
366 test_cmp_bin b.tar j.tar
369 test_expect_success 'remote tar.gz is allowed by default' '
370 git archive --remote=. --format=tar.gz HEAD >remote.tar.gz &&
371 test_cmp_bin j.tgz remote.tar.gz
374 test_expect_success 'remote tar.gz can be disabled' '
375 git config tar.tar.gz.remote false &&
376 test_must_fail git archive --remote=. --format=tar.gz HEAD \
377 >remote.tar.gz
380 test_expect_success GZIP 'git archive --format=tgz (external gzip)' '
381 test_config tar.tgz.command "gzip -cn" &&
382 git archive --format=tgz HEAD >external_gzip.tgz
385 test_expect_success GZIP 'git archive --format=tar.gz (external gzip)' '
386 test_config tar.tar.gz.command "gzip -cn" &&
387 git archive --format=tar.gz HEAD >external_gzip.tar.gz &&
388 test_cmp_bin external_gzip.tgz external_gzip.tar.gz
391 test_expect_success GZIP 'extract tgz file (external gzip)' '
392 gzip -d -c <external_gzip.tgz >external_gzip.tar &&
393 test_cmp_bin b.tar external_gzip.tar
396 test_expect_success 'archive and :(glob)' '
397 git archive -v HEAD -- ":(glob)**/sh" >/dev/null 2>actual &&
398 cat >expect <<EOF &&
400 a/bin/
401 a/bin/sh
403 test_cmp expect actual
406 test_expect_success 'catch non-matching pathspec' '
407 test_must_fail git archive -v HEAD -- "*.abc" >/dev/null
410 # Pull the size and date of each entry in a tarfile using the system tar.
412 # We'll pull out only the year from the date; that avoids any question of
413 # timezones impacting the result (as long as we keep our test times away from a
414 # year boundary; our reference times are all in August).
416 # The output of tar_info is expected to be "<size> <year>", both in decimal. It
417 # ignores the return value of tar. We have to do this, because some of our test
418 # input is only partial (the real data is 64GB in some cases).
419 tar_info () {
420 "$TAR" tvf "$1" |
421 awk '{
422 split($4, date, "-")
423 print $3 " " date[1]
427 # See if our system tar can handle a tar file with huge sizes and dates far in
428 # the future, and that we can actually parse its output.
430 # The reference file was generated by GNU tar, and the magic time and size are
431 # both octal 01000000000001, which overflows normal ustar fields.
432 test_lazy_prereq TAR_HUGE '
433 echo "68719476737 4147" >expect &&
434 tar_info "$TEST_DIRECTORY"/t5000/huge-and-future.tar >actual &&
435 test_cmp expect actual
438 test_expect_success LONG_IS_64BIT 'set up repository with huge blob' '
439 obj=$(test_oid obj) &&
440 path=$(test_oid_to_path $obj) &&
441 mkdir -p .git/objects/$(dirname $path) &&
442 cp "$TEST_DIRECTORY"/t5000/huge-object .git/objects/$path &&
443 rm -f .git/index &&
444 git update-index --add --cacheinfo 100644,$obj,huge &&
445 git commit -m huge
448 # We expect git to die with SIGPIPE here (otherwise we
449 # would generate the whole 64GB).
450 test_expect_success LONG_IS_64BIT 'generate tar with huge size' '
452 git archive HEAD
453 echo $? >exit-code
454 } | test_copy_bytes 4096 >huge.tar &&
455 echo 141 >expect &&
456 test_cmp expect exit-code
459 test_expect_success TAR_HUGE,LONG_IS_64BIT 'system tar can read our huge size' '
460 echo 68719476737 >expect &&
461 tar_info huge.tar | cut -d" " -f1 >actual &&
462 test_cmp expect actual
465 test_expect_success TIME_IS_64BIT 'set up repository with far-future (2^34 - 1) commit' '
466 rm -f .git/index &&
467 echo foo >file &&
468 git add file &&
469 GIT_COMMITTER_DATE="@17179869183 +0000" \
470 git commit -m "tempori parendum"
473 test_expect_success TIME_IS_64BIT 'generate tar with far-future mtime' '
474 git archive HEAD >future.tar
477 test_expect_success TAR_HUGE,TIME_IS_64BIT,TIME_T_IS_64BIT 'system tar can read our future mtime' '
478 echo 2514 >expect &&
479 tar_info future.tar | cut -d" " -f2 >actual &&
480 test_cmp expect actual
483 test_expect_success TIME_IS_64BIT 'set up repository with far-far-future (2^36 + 1) commit' '
484 rm -f .git/index &&
485 echo content >file &&
486 git add file &&
487 GIT_TEST_COMMIT_GRAPH=0 GIT_COMMITTER_DATE="@68719476737 +0000" \
488 git commit -m "tempori parendum"
491 test_expect_success TIME_IS_64BIT 'generate tar with far-far-future mtime' '
492 git archive HEAD >future.tar
495 test_expect_success TAR_HUGE,TIME_IS_64BIT,TIME_T_IS_64BIT 'system tar can read our future mtime' '
496 echo 4147 >expect &&
497 tar_info future.tar | cut -d" " -f2 >actual &&
498 test_cmp expect actual
501 test_done