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