t / t5000-tar-tree.shon commit Merge branch 'jk/trailers-parse' into next (2d4d937)
   1#!/bin/sh
   2#
   3# Copyright (C) 2005 Rene Scharfe
   4#
   5
   6test_description='git archive and git get-tar-commit-id test
   7
   8This test covers the topics of file contents, commit date handling and
   9commit id embedding:
  10
  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.
  15
  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.
  19
  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.
  24
  25'
  26
  27. ./test-lib.sh
  28
  29SUBSTFORMAT=%H%n
  30
  31test_lazy_prereq TAR_NEEDS_PAX_FALLBACK '
  32        (
  33                mkdir pax &&
  34                cd pax &&
  35                "$TAR" xf "$TEST_DIRECTORY"/t5000/pax.tar &&
  36                test -f PaxHeaders.1791/file
  37        )
  38'
  39
  40test_lazy_prereq GZIP 'gzip --version'
  41
  42get_pax_header() {
  43        file=$1
  44        header=$2=
  45
  46        while read len rest
  47        do
  48                if test "$len" = $(echo "$len $rest" | wc -c)
  49                then
  50                        case "$rest" in
  51                        $header*)
  52                                echo "${rest#$header}"
  53                                ;;
  54                        esac
  55                fi
  56        done <"$file"
  57}
  58
  59check_tar() {
  60        tarfile=$1.tar
  61        listfile=$1.lst
  62        dir=$1
  63        dir_with_prefix=$dir/$2
  64
  65        test_expect_success ' extract tar archive' '
  66                (mkdir $dir && cd $dir && "$TAR" xf -) <$tarfile
  67        '
  68
  69        test_expect_success TAR_NEEDS_PAX_FALLBACK ' interpret pax headers' '
  70                (
  71                        cd $dir &&
  72                        for header in *.paxheader
  73                        do
  74                                data=${header%.paxheader}.data &&
  75                                if test -h $data || test -e $data
  76                                then
  77                                        path=$(get_pax_header $header path) &&
  78                                        if test -n "$path"
  79                                        then
  80                                                mv "$data" "$path"
  81                                        fi
  82                                fi
  83                        done
  84                )
  85        '
  86
  87        test_expect_success ' validate filenames' '
  88                (cd ${dir_with_prefix}a && find .) | sort >$listfile &&
  89                test_cmp a.lst $listfile
  90        '
  91
  92        test_expect_success ' validate file contents' '
  93                diff -r a ${dir_with_prefix}a
  94        '
  95}
  96
  97test_expect_success \
  98    'populate workdir' \
  99    'mkdir a &&
 100     echo simple textfile >a/a &&
 101     ten=0123456789 && hundred=$ten$ten$ten$ten$ten$ten$ten$ten$ten$ten &&
 102     echo long filename >a/four$hundred &&
 103     mkdir a/bin &&
 104     test-genrandom "frotz" 500000 >a/bin/sh &&
 105     printf "A\$Format:%s\$O" "$SUBSTFORMAT" >a/substfile1 &&
 106     printf "A not substituted O" >a/substfile2 &&
 107     if test_have_prereq SYMLINKS; then
 108        ln -s a a/l1
 109     else
 110        printf %s a > a/l1
 111     fi &&
 112     (p=long_path_to_a_file && cd a &&
 113      for depth in 1 2 3 4 5; do mkdir $p && cd $p; done &&
 114      echo text >file_with_long_path) &&
 115     (cd a && find .) | sort >a.lst'
 116
 117test_expect_success \
 118    'add ignored file' \
 119    'echo ignore me >a/ignored &&
 120     echo ignored export-ignore >.git/info/attributes'
 121
 122test_expect_success 'add files to repository' '
 123        git add a &&
 124        GIT_COMMITTER_DATE="2005-05-27 22:00" git commit -m initial
 125'
 126
 127test_expect_success 'setup export-subst' '
 128        echo "substfile?" export-subst >>.git/info/attributes &&
 129        git log --max-count=1 "--pretty=format:A${SUBSTFORMAT}O" HEAD \
 130                >a/substfile1
 131'
 132
 133test_expect_success \
 134    'create bare clone' \
 135    'git clone --bare . bare.git &&
 136     cp .git/info/attributes bare.git/info/attributes'
 137
 138test_expect_success \
 139    'remove ignored file' \
 140    'rm a/ignored'
 141
 142test_expect_success \
 143    'git archive' \
 144    'git archive HEAD >b.tar'
 145
 146check_tar b
 147
 148test_expect_success 'git archive --prefix=prefix/' '
 149        git archive --prefix=prefix/ HEAD >with_prefix.tar
 150'
 151
 152check_tar with_prefix prefix/
 153
 154test_expect_success 'git-archive --prefix=olde-' '
 155        git archive --prefix=olde- HEAD >with_olde-prefix.tar
 156'
 157
 158check_tar with_olde-prefix olde-
 159
 160test_expect_success 'git archive on large files' '
 161    test_config core.bigfilethreshold 1 &&
 162    git archive HEAD >b3.tar &&
 163    test_cmp_bin b.tar b3.tar
 164'
 165
 166test_expect_success \
 167    'git archive in a bare repo' \
 168    '(cd bare.git && git archive HEAD) >b3.tar'
 169
 170test_expect_success \
 171    'git archive vs. the same in a bare repo' \
 172    'test_cmp_bin b.tar b3.tar'
 173
 174test_expect_success 'git archive with --output' \
 175    'git archive --output=b4.tar HEAD &&
 176    test_cmp_bin b.tar b4.tar'
 177
 178test_expect_success 'git archive --remote' \
 179    'git archive --remote=. HEAD >b5.tar &&
 180    test_cmp_bin b.tar b5.tar'
 181
 182test_expect_success 'git archive --remote with configured remote' '
 183        git config remote.foo.url . &&
 184        (
 185                cd a &&
 186                git archive --remote=foo --output=../b5-nick.tar HEAD
 187        ) &&
 188        test_cmp_bin b.tar b5-nick.tar
 189'
 190
 191test_expect_success \
 192    'validate file modification time' \
 193    'mkdir extract &&
 194     "$TAR" xf b.tar -C extract a/a &&
 195     test-chmtime -v +0 extract/a/a |cut -f 1 >b.mtime &&
 196     echo "1117231200" >expected.mtime &&
 197     test_cmp expected.mtime b.mtime'
 198
 199test_expect_success \
 200    'git get-tar-commit-id' \
 201    'git get-tar-commit-id <b.tar >b.commitid &&
 202     test_cmp .git/$(git symbolic-ref HEAD) b.commitid'
 203
 204test_expect_success 'git archive with --output, override inferred format' '
 205        git archive --format=tar --output=d4.zip HEAD &&
 206        test_cmp_bin b.tar d4.zip
 207'
 208
 209test_expect_success 'git archive --list outside of a git repo' '
 210        nongit git archive --list
 211'
 212
 213test_expect_success 'git archive --remote outside of a git repo' '
 214        git archive HEAD >expect.tar &&
 215        nongit git archive --remote="$PWD" HEAD >actual.tar &&
 216        test_cmp_bin expect.tar actual.tar
 217'
 218
 219test_expect_success 'clients cannot access unreachable commits' '
 220        test_commit unreachable &&
 221        sha1=$(git rev-parse HEAD) &&
 222        git reset --hard HEAD^ &&
 223        git archive $sha1 >remote.tar &&
 224        test_must_fail git archive --remote=. $sha1 >remote.tar
 225'
 226
 227test_expect_success 'upload-archive can allow unreachable commits' '
 228        test_commit unreachable1 &&
 229        sha1=$(git rev-parse HEAD) &&
 230        git reset --hard HEAD^ &&
 231        git archive $sha1 >remote.tar &&
 232        test_config uploadarchive.allowUnreachable true &&
 233        git archive --remote=. $sha1 >remote.tar
 234'
 235
 236test_expect_success 'setup tar filters' '
 237        git config tar.tar.foo.command "tr ab ba" &&
 238        git config tar.bar.command "tr ab ba" &&
 239        git config tar.bar.remote true &&
 240        git config tar.invalid baz
 241'
 242
 243test_expect_success 'archive --list mentions user filter' '
 244        git archive --list >output &&
 245        grep "^tar\.foo\$" output &&
 246        grep "^bar\$" output
 247'
 248
 249test_expect_success 'archive --list shows only enabled remote filters' '
 250        git archive --list --remote=. >output &&
 251        ! grep "^tar\.foo\$" output &&
 252        grep "^bar\$" output
 253'
 254
 255test_expect_success 'invoke tar filter by format' '
 256        git archive --format=tar.foo HEAD >config.tar.foo &&
 257        tr ab ba <config.tar.foo >config.tar &&
 258        test_cmp_bin b.tar config.tar &&
 259        git archive --format=bar HEAD >config.bar &&
 260        tr ab ba <config.bar >config.tar &&
 261        test_cmp_bin b.tar config.tar
 262'
 263
 264test_expect_success 'invoke tar filter by extension' '
 265        git archive -o config-implicit.tar.foo HEAD &&
 266        test_cmp_bin config.tar.foo config-implicit.tar.foo &&
 267        git archive -o config-implicit.bar HEAD &&
 268        test_cmp_bin config.tar.foo config-implicit.bar
 269'
 270
 271test_expect_success 'default output format remains tar' '
 272        git archive -o config-implicit.baz HEAD &&
 273        test_cmp_bin b.tar config-implicit.baz
 274'
 275
 276test_expect_success 'extension matching requires dot' '
 277        git archive -o config-implicittar.foo HEAD &&
 278        test_cmp_bin b.tar config-implicittar.foo
 279'
 280
 281test_expect_success 'only enabled filters are available remotely' '
 282        test_must_fail git archive --remote=. --format=tar.foo HEAD \
 283                >remote.tar.foo &&
 284        git archive --remote=. --format=bar >remote.bar HEAD &&
 285        test_cmp_bin remote.bar config.bar
 286'
 287
 288test_expect_success GZIP 'git archive --format=tgz' '
 289        git archive --format=tgz HEAD >j.tgz
 290'
 291
 292test_expect_success GZIP 'git archive --format=tar.gz' '
 293        git archive --format=tar.gz HEAD >j1.tar.gz &&
 294        test_cmp_bin j.tgz j1.tar.gz
 295'
 296
 297test_expect_success GZIP 'infer tgz from .tgz filename' '
 298        git archive --output=j2.tgz HEAD &&
 299        test_cmp_bin j.tgz j2.tgz
 300'
 301
 302test_expect_success GZIP 'infer tgz from .tar.gz filename' '
 303        git archive --output=j3.tar.gz HEAD &&
 304        test_cmp_bin j.tgz j3.tar.gz
 305'
 306
 307test_expect_success GZIP 'extract tgz file' '
 308        gzip -d -c <j.tgz >j.tar &&
 309        test_cmp_bin b.tar j.tar
 310'
 311
 312test_expect_success GZIP 'remote tar.gz is allowed by default' '
 313        git archive --remote=. --format=tar.gz HEAD >remote.tar.gz &&
 314        test_cmp_bin j.tgz remote.tar.gz
 315'
 316
 317test_expect_success GZIP 'remote tar.gz can be disabled' '
 318        git config tar.tar.gz.remote false &&
 319        test_must_fail git archive --remote=. --format=tar.gz HEAD \
 320                >remote.tar.gz
 321'
 322
 323test_expect_success 'archive and :(glob)' '
 324        git archive -v HEAD -- ":(glob)**/sh" >/dev/null 2>actual &&
 325        cat >expect <<EOF &&
 326a/
 327a/bin/
 328a/bin/sh
 329EOF
 330        test_cmp expect actual
 331'
 332
 333test_expect_success 'catch non-matching pathspec' '
 334        test_must_fail git archive -v HEAD -- "*.abc" >/dev/null
 335'
 336
 337# Pull the size and date of each entry in a tarfile using the system tar.
 338#
 339# We'll pull out only the year from the date; that avoids any question of
 340# timezones impacting the result (as long as we keep our test times away from a
 341# year boundary; our reference times are all in August).
 342#
 343# The output of tar_info is expected to be "<size> <year>", both in decimal. It
 344# ignores the return value of tar. We have to do this, because some of our test
 345# input is only partial (the real data is 64GB in some cases).
 346tar_info () {
 347        "$TAR" tvf "$1" |
 348        awk '{
 349                split($4, date, "-")
 350                print $3 " " date[1]
 351        }'
 352}
 353
 354# See if our system tar can handle a tar file with huge sizes and dates far in
 355# the future, and that we can actually parse its output.
 356#
 357# The reference file was generated by GNU tar, and the magic time and size are
 358# both octal 01000000000001, which overflows normal ustar fields.
 359test_lazy_prereq TAR_HUGE '
 360        echo "68719476737 4147" >expect &&
 361        tar_info "$TEST_DIRECTORY"/t5000/huge-and-future.tar >actual &&
 362        test_cmp expect actual
 363'
 364
 365test_expect_success LONG_IS_64BIT 'set up repository with huge blob' '
 366        obj_d=19 &&
 367        obj_f=f9c8273ec45a8938e6999cb59b3ff66739902a &&
 368        obj=${obj_d}${obj_f} &&
 369        mkdir -p .git/objects/$obj_d &&
 370        cp "$TEST_DIRECTORY"/t5000/$obj .git/objects/$obj_d/$obj_f &&
 371        rm -f .git/index &&
 372        git update-index --add --cacheinfo 100644,$obj,huge &&
 373        git commit -m huge
 374'
 375
 376# We expect git to die with SIGPIPE here (otherwise we
 377# would generate the whole 64GB).
 378test_expect_success LONG_IS_64BIT 'generate tar with huge size' '
 379        {
 380                git archive HEAD
 381                echo $? >exit-code
 382        } | test_copy_bytes 4096 >huge.tar &&
 383        echo 141 >expect &&
 384        test_cmp expect exit-code
 385'
 386
 387test_expect_success TAR_HUGE,LONG_IS_64BIT 'system tar can read our huge size' '
 388        echo 68719476737 >expect &&
 389        tar_info huge.tar | cut -d" " -f1 >actual &&
 390        test_cmp expect actual
 391'
 392
 393test_expect_success TIME_IS_64BIT 'set up repository with far-future commit' '
 394        rm -f .git/index &&
 395        echo content >file &&
 396        git add file &&
 397        GIT_COMMITTER_DATE="@68719476737 +0000" \
 398                git commit -m "tempori parendum"
 399'
 400
 401test_expect_success TIME_IS_64BIT 'generate tar with future mtime' '
 402        git archive HEAD >future.tar
 403'
 404
 405test_expect_success TAR_HUGE,TIME_IS_64BIT,TIME_T_IS_64BIT 'system tar can read our future mtime' '
 406        echo 4147 >expect &&
 407        tar_info future.tar | cut -d" " -f2 >actual &&
 408        test_cmp expect actual
 409'
 410
 411test_done