1#!/bin/sh
   2#
   3# Copyright (C) 2005 Rene Scharfe
   4#
   5test_description='git archive and git get-tar-commit-id test
   7This test covers the topics of file contents, commit date handling and
   9commit id embedding:
  10  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  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  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'
  26. ./test-lib.sh
  28SUBSTFORMAT=%H%n
  30test_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'
  39test_lazy_prereq GZIP 'gzip --version'
  41get_pax_header() {
  43        file=$1
  44        header=$2=
  45        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}
  58check_tar() {
  60        tarfile=$1.tar
  61        listfile=$1.lst
  62        dir=$1
  63        dir_with_prefix=$dir/$2
  64        test_expect_success ' extract tar archive' '
  66                (mkdir $dir && cd $dir && "$TAR" xf -) <$tarfile
  67        '
  68        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        test_expect_success ' validate filenames' '
  88                (cd ${dir_with_prefix}a && find .) | sort >$listfile &&
  89                test_cmp a.lst $listfile
  90        '
  91        test_expect_success ' validate file contents' '
  93                diff -r a ${dir_with_prefix}a
  94        '
  95}
  96test_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'
 116test_expect_success \
 118    'add ignored file' \
 119    'echo ignore me >a/ignored &&
 120     echo ignored export-ignore >.git/info/attributes'
 121test_expect_success 'add files to repository' '
 123        git add a &&
 124        GIT_COMMITTER_DATE="2005-05-27 22:00" git commit -m initial
 125'
 126test_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'
 132test_expect_success \
 134    'create bare clone' \
 135    'git clone --bare . bare.git &&
 136     cp .git/info/attributes bare.git/info/attributes'
 137test_expect_success \
 139    'remove ignored file' \
 140    'rm a/ignored'
 141test_expect_success \
 143    'git archive' \
 144    'git archive HEAD >b.tar'
 145check_tar b
 147test_expect_success 'git archive --prefix=prefix/' '
 149        git archive --prefix=prefix/ HEAD >with_prefix.tar
 150'
 151check_tar with_prefix prefix/
 153test_expect_success 'git-archive --prefix=olde-' '
 155        git archive --prefix=olde- HEAD >with_olde-prefix.tar
 156'
 157check_tar with_olde-prefix olde-
 159test_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'
 165test_expect_success \
 167    'git archive in a bare repo' \
 168    '(cd bare.git && git archive HEAD) >b3.tar'
 169test_expect_success \
 171    'git archive vs. the same in a bare repo' \
 172    'test_cmp_bin b.tar b3.tar'
 173test_expect_success 'git archive with --output' \
 175    'git archive --output=b4.tar HEAD &&
 176    test_cmp_bin b.tar b4.tar'
 177test_expect_success 'git archive --remote' \
 179    'git archive --remote=. HEAD >b5.tar &&
 180    test_cmp_bin b.tar b5.tar'
 181test_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'
 189test_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'
 194test_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'
 199test_expect_success \
 201    'git archive --list outside of a git repo' \
 202    'GIT_DIR=some/non-existing/directory git archive --list'
 203test_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'
 211test_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'
 220test_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'
 227test_expect_success 'archive --list mentions user filter' '
 229        git archive --list >output &&
 230        grep "^tar\.foo\$" output &&
 231        grep "^bar\$" output
 232'
 233test_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'
 239test_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'
 248test_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'
 255test_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'
 260test_expect_success 'extension matching requires dot' '
 262        git archive -o config-implicittar.foo HEAD &&
 263        test_cmp_bin b.tar config-implicittar.foo
 264'
 265test_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'
 272test_expect_success GZIP 'git archive --format=tgz' '
 274        git archive --format=tgz HEAD >j.tgz
 275'
 276test_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'
 281test_expect_success GZIP 'infer tgz from .tgz filename' '
 283        git archive --output=j2.tgz HEAD &&
 284        test_cmp_bin j.tgz j2.tgz
 285'
 286test_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'
 291test_expect_success GZIP 'extract tgz file' '
 293        gzip -d -c <j.tgz >j.tar &&
 294        test_cmp_bin b.tar j.tar
 295'
 296test_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'
 301test_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'
 307test_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'
 317test_expect_success 'catch non-matching pathspec' '
 319        test_must_fail git archive -v HEAD -- "*.abc" >/dev/null
 320'
 321test_done