Merge branch 'jh/fsmonitor-darwin-modernize'
[git.git] / t / t5000-tar-tree.sh
blobd473048138466322e505f4b3b249e89f19101b0b
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 'invalid filter is reported only once' '
346 test_must_fail git -c tar.invalid.command= archive --format=invalid \
347 HEAD >out 2>err &&
348 test_must_be_empty out &&
349 test_line_count = 1 err
352 test_expect_success 'git archive --format=tgz' '
353 git archive --format=tgz HEAD >j.tgz
356 test_expect_success 'git archive --format=tar.gz' '
357 git archive --format=tar.gz HEAD >j1.tar.gz &&
358 test_cmp_bin j.tgz j1.tar.gz
361 test_expect_success 'infer tgz from .tgz filename' '
362 git archive --output=j2.tgz HEAD &&
363 test_cmp_bin j.tgz j2.tgz
366 test_expect_success 'infer tgz from .tar.gz filename' '
367 git archive --output=j3.tar.gz HEAD &&
368 test_cmp_bin j.tgz j3.tar.gz
371 test_expect_success GZIP 'extract tgz file' '
372 gzip -d -c <j.tgz >j.tar &&
373 test_cmp_bin b.tar j.tar
376 test_expect_success 'remote tar.gz is allowed by default' '
377 git archive --remote=. --format=tar.gz HEAD >remote.tar.gz &&
378 test_cmp_bin j.tgz remote.tar.gz
381 test_expect_success 'remote tar.gz can be disabled' '
382 git config tar.tar.gz.remote false &&
383 test_must_fail git archive --remote=. --format=tar.gz HEAD \
384 >remote.tar.gz
387 test_expect_success GZIP 'git archive --format=tgz (external gzip)' '
388 test_config tar.tgz.command "gzip -cn" &&
389 git archive --format=tgz HEAD >external_gzip.tgz
392 test_expect_success GZIP 'git archive --format=tar.gz (external gzip)' '
393 test_config tar.tar.gz.command "gzip -cn" &&
394 git archive --format=tar.gz HEAD >external_gzip.tar.gz &&
395 test_cmp_bin external_gzip.tgz external_gzip.tar.gz
398 test_expect_success GZIP 'extract tgz file (external gzip)' '
399 gzip -d -c <external_gzip.tgz >external_gzip.tar &&
400 test_cmp_bin b.tar external_gzip.tar
403 test_expect_success 'archive and :(glob)' '
404 git archive -v HEAD -- ":(glob)**/sh" >/dev/null 2>actual &&
405 cat >expect <<EOF &&
407 a/bin/
408 a/bin/sh
410 test_cmp expect actual
413 test_expect_success 'catch non-matching pathspec' '
414 test_must_fail git archive -v HEAD -- "*.abc" >/dev/null
417 # Pull the size and date of each entry in a tarfile using the system tar.
419 # We'll pull out only the year from the date; that avoids any question of
420 # timezones impacting the result (as long as we keep our test times away from a
421 # year boundary; our reference times are all in August).
423 # The output of tar_info is expected to be "<size> <year>", both in decimal. It
424 # ignores the return value of tar. We have to do this, because some of our test
425 # input is only partial (the real data is 64GB in some cases).
426 tar_info () {
427 "$TAR" tvf "$1" |
428 awk '{
429 split($4, date, "-")
430 print $3 " " date[1]
434 # See if our system tar can handle a tar file with huge sizes and dates far in
435 # the future, and that we can actually parse its output.
437 # The reference file was generated by GNU tar, and the magic time and size are
438 # both octal 01000000000001, which overflows normal ustar fields.
439 test_lazy_prereq TAR_HUGE '
440 echo "68719476737 4147" >expect &&
441 tar_info "$TEST_DIRECTORY"/t5000/huge-and-future.tar >actual &&
442 test_cmp expect actual
445 test_expect_success LONG_IS_64BIT 'set up repository with huge blob' '
446 obj=$(test_oid obj) &&
447 path=$(test_oid_to_path $obj) &&
448 mkdir -p .git/objects/$(dirname $path) &&
449 cp "$TEST_DIRECTORY"/t5000/huge-object .git/objects/$path &&
450 rm -f .git/index &&
451 git update-index --add --cacheinfo 100644,$obj,huge &&
452 git commit -m huge
455 # We expect git to die with SIGPIPE here (otherwise we
456 # would generate the whole 64GB).
457 test_expect_success LONG_IS_64BIT 'generate tar with huge size' '
459 git archive HEAD
460 echo $? >exit-code
461 } | test_copy_bytes 4096 >huge.tar &&
462 echo 141 >expect &&
463 test_cmp expect exit-code
466 test_expect_success TAR_HUGE,LONG_IS_64BIT 'system tar can read our huge size' '
467 echo 68719476737 >expect &&
468 tar_info huge.tar | cut -d" " -f1 >actual &&
469 test_cmp expect actual
472 test_expect_success TIME_IS_64BIT 'set up repository with far-future (2^34 - 1) commit' '
473 rm -f .git/index &&
474 echo foo >file &&
475 git add file &&
476 GIT_COMMITTER_DATE="@17179869183 +0000" \
477 git commit -m "tempori parendum"
480 test_expect_success TIME_IS_64BIT 'generate tar with far-future mtime' '
481 git archive HEAD >future.tar
484 test_expect_success TAR_HUGE,TIME_IS_64BIT,TIME_T_IS_64BIT 'system tar can read our future mtime' '
485 echo 2514 >expect &&
486 tar_info future.tar | cut -d" " -f2 >actual &&
487 test_cmp expect actual
490 test_expect_success TIME_IS_64BIT 'set up repository with far-far-future (2^36 + 1) commit' '
491 rm -f .git/index &&
492 echo content >file &&
493 git add file &&
494 GIT_TEST_COMMIT_GRAPH=0 GIT_COMMITTER_DATE="@68719476737 +0000" \
495 git commit -m "tempori parendum"
498 test_expect_success TIME_IS_64BIT 'generate tar with far-far-future mtime' '
499 git archive HEAD >future.tar
502 test_expect_success TAR_HUGE,TIME_IS_64BIT,TIME_T_IS_64BIT 'system tar can read our future mtime' '
503 echo 4147 >expect &&
504 tar_info future.tar | cut -d" " -f2 >actual &&
505 test_cmp expect actual
508 test_done