t / t5000-tar-tree.shon commit Merge branch 'cc/delta-islands' (7fab474)
   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-tool 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-tool chmtime --get extract/a/a >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 GZIP 'git archive with --output and --remote creates .tgz' '
 210        git archive --output=d5.tgz --remote=. HEAD &&
 211        gzip -d -c <d5.tgz >d5.tar &&
 212        test_cmp_bin b.tar d5.tar
 213'
 214
 215test_expect_success 'git archive --list outside of a git repo' '
 216        nongit git archive --list
 217'
 218
 219test_expect_success 'git archive --remote outside of a git repo' '
 220        git archive HEAD >expect.tar &&
 221        nongit git archive --remote="$PWD" HEAD >actual.tar &&
 222        test_cmp_bin expect.tar actual.tar
 223'
 224
 225test_expect_success 'clients cannot access unreachable commits' '
 226        test_commit unreachable &&
 227        sha1=$(git rev-parse HEAD) &&
 228        git reset --hard HEAD^ &&
 229        git archive $sha1 >remote.tar &&
 230        test_must_fail git archive --remote=. $sha1 >remote.tar
 231'
 232
 233test_expect_success 'upload-archive can allow unreachable commits' '
 234        test_commit unreachable1 &&
 235        sha1=$(git rev-parse HEAD) &&
 236        git reset --hard HEAD^ &&
 237        git archive $sha1 >remote.tar &&
 238        test_config uploadarchive.allowUnreachable true &&
 239        git archive --remote=. $sha1 >remote.tar
 240'
 241
 242test_expect_success 'setup tar filters' '
 243        git config tar.tar.foo.command "tr ab ba" &&
 244        git config tar.bar.command "tr ab ba" &&
 245        git config tar.bar.remote true &&
 246        git config tar.invalid baz
 247'
 248
 249test_expect_success 'archive --list mentions user filter' '
 250        git archive --list >output &&
 251        grep "^tar\.foo\$" output &&
 252        grep "^bar\$" output
 253'
 254
 255test_expect_success 'archive --list shows only enabled remote filters' '
 256        git archive --list --remote=. >output &&
 257        ! grep "^tar\.foo\$" output &&
 258        grep "^bar\$" output
 259'
 260
 261test_expect_success 'invoke tar filter by format' '
 262        git archive --format=tar.foo HEAD >config.tar.foo &&
 263        tr ab ba <config.tar.foo >config.tar &&
 264        test_cmp_bin b.tar config.tar &&
 265        git archive --format=bar HEAD >config.bar &&
 266        tr ab ba <config.bar >config.tar &&
 267        test_cmp_bin b.tar config.tar
 268'
 269
 270test_expect_success 'invoke tar filter by extension' '
 271        git archive -o config-implicit.tar.foo HEAD &&
 272        test_cmp_bin config.tar.foo config-implicit.tar.foo &&
 273        git archive -o config-implicit.bar HEAD &&
 274        test_cmp_bin config.tar.foo config-implicit.bar
 275'
 276
 277test_expect_success 'default output format remains tar' '
 278        git archive -o config-implicit.baz HEAD &&
 279        test_cmp_bin b.tar config-implicit.baz
 280'
 281
 282test_expect_success 'extension matching requires dot' '
 283        git archive -o config-implicittar.foo HEAD &&
 284        test_cmp_bin b.tar config-implicittar.foo
 285'
 286
 287test_expect_success 'only enabled filters are available remotely' '
 288        test_must_fail git archive --remote=. --format=tar.foo HEAD \
 289                >remote.tar.foo &&
 290        git archive --remote=. --format=bar >remote.bar HEAD &&
 291        test_cmp_bin remote.bar config.bar
 292'
 293
 294test_expect_success GZIP 'git archive --format=tgz' '
 295        git archive --format=tgz HEAD >j.tgz
 296'
 297
 298test_expect_success GZIP 'git archive --format=tar.gz' '
 299        git archive --format=tar.gz HEAD >j1.tar.gz &&
 300        test_cmp_bin j.tgz j1.tar.gz
 301'
 302
 303test_expect_success GZIP 'infer tgz from .tgz filename' '
 304        git archive --output=j2.tgz HEAD &&
 305        test_cmp_bin j.tgz j2.tgz
 306'
 307
 308test_expect_success GZIP 'infer tgz from .tar.gz filename' '
 309        git archive --output=j3.tar.gz HEAD &&
 310        test_cmp_bin j.tgz j3.tar.gz
 311'
 312
 313test_expect_success GZIP 'extract tgz file' '
 314        gzip -d -c <j.tgz >j.tar &&
 315        test_cmp_bin b.tar j.tar
 316'
 317
 318test_expect_success GZIP 'remote tar.gz is allowed by default' '
 319        git archive --remote=. --format=tar.gz HEAD >remote.tar.gz &&
 320        test_cmp_bin j.tgz remote.tar.gz
 321'
 322
 323test_expect_success GZIP 'remote tar.gz can be disabled' '
 324        git config tar.tar.gz.remote false &&
 325        test_must_fail git archive --remote=. --format=tar.gz HEAD \
 326                >remote.tar.gz
 327'
 328
 329test_expect_success 'archive and :(glob)' '
 330        git archive -v HEAD -- ":(glob)**/sh" >/dev/null 2>actual &&
 331        cat >expect <<EOF &&
 332a/
 333a/bin/
 334a/bin/sh
 335EOF
 336        test_cmp expect actual
 337'
 338
 339test_expect_success 'catch non-matching pathspec' '
 340        test_must_fail git archive -v HEAD -- "*.abc" >/dev/null
 341'
 342
 343# Pull the size and date of each entry in a tarfile using the system tar.
 344#
 345# We'll pull out only the year from the date; that avoids any question of
 346# timezones impacting the result (as long as we keep our test times away from a
 347# year boundary; our reference times are all in August).
 348#
 349# The output of tar_info is expected to be "<size> <year>", both in decimal. It
 350# ignores the return value of tar. We have to do this, because some of our test
 351# input is only partial (the real data is 64GB in some cases).
 352tar_info () {
 353        "$TAR" tvf "$1" |
 354        awk '{
 355                split($4, date, "-")
 356                print $3 " " date[1]
 357        }'
 358}
 359
 360# See if our system tar can handle a tar file with huge sizes and dates far in
 361# the future, and that we can actually parse its output.
 362#
 363# The reference file was generated by GNU tar, and the magic time and size are
 364# both octal 01000000000001, which overflows normal ustar fields.
 365test_lazy_prereq TAR_HUGE '
 366        echo "68719476737 4147" >expect &&
 367        tar_info "$TEST_DIRECTORY"/t5000/huge-and-future.tar >actual &&
 368        test_cmp expect actual
 369'
 370
 371test_expect_success LONG_IS_64BIT 'set up repository with huge blob' '
 372        obj_d=19 &&
 373        obj_f=f9c8273ec45a8938e6999cb59b3ff66739902a &&
 374        obj=${obj_d}${obj_f} &&
 375        mkdir -p .git/objects/$obj_d &&
 376        cp "$TEST_DIRECTORY"/t5000/$obj .git/objects/$obj_d/$obj_f &&
 377        rm -f .git/index &&
 378        git update-index --add --cacheinfo 100644,$obj,huge &&
 379        git commit -m huge
 380'
 381
 382# We expect git to die with SIGPIPE here (otherwise we
 383# would generate the whole 64GB).
 384test_expect_success LONG_IS_64BIT 'generate tar with huge size' '
 385        {
 386                git archive HEAD
 387                echo $? >exit-code
 388        } | test_copy_bytes 4096 >huge.tar &&
 389        echo 141 >expect &&
 390        test_cmp expect exit-code
 391'
 392
 393test_expect_success TAR_HUGE,LONG_IS_64BIT 'system tar can read our huge size' '
 394        echo 68719476737 >expect &&
 395        tar_info huge.tar | cut -d" " -f1 >actual &&
 396        test_cmp expect actual
 397'
 398
 399test_expect_success TIME_IS_64BIT 'set up repository with far-future commit' '
 400        rm -f .git/index &&
 401        echo content >file &&
 402        git add file &&
 403        GIT_COMMITTER_DATE="@68719476737 +0000" \
 404                git commit -m "tempori parendum"
 405'
 406
 407test_expect_success TIME_IS_64BIT 'generate tar with future mtime' '
 408        git archive HEAD >future.tar
 409'
 410
 411test_expect_success TAR_HUGE,TIME_IS_64BIT,TIME_T_IS_64BIT 'system tar can read our future mtime' '
 412        echo 4147 >expect &&
 413        tar_info future.tar | cut -d" " -f2 >actual &&
 414        test_cmp expect actual
 415'
 416
 417test_done