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