9106c53c4c893338e8b8e972aec350ace872947b
   1#!/bin/sh
   2
   3test_description='test corner cases of git-archive'
   4. ./test-lib.sh
   5
   6test_expect_success 'create commit with empty tree' '
   7        git commit --allow-empty -m foo
   8'
   9
  10# Make a dir and clean it up afterwards
  11make_dir() {
  12        mkdir "$1" &&
  13        test_when_finished "rm -rf '$1'"
  14}
  15
  16# Check that the dir given in "$1" contains exactly the
  17# set of paths given as arguments.
  18check_dir() {
  19        dir=$1; shift
  20        {
  21                echo "$dir" &&
  22                for i in "$@"; do
  23                        echo "$dir/$i"
  24                done
  25        } | sort >expect &&
  26        find "$dir" ! -name pax_global_header -print | sort >actual &&
  27        test_cmp expect actual
  28}
  29
  30
  31# bsdtar/libarchive versions before 3.1.3 consider a tar file with a
  32# global pax header that is not followed by a file record as corrupt.
  33if "$TAR" tf "$TEST_DIRECTORY"/t5004/empty-with-pax-header.tar >/dev/null 2>&1
  34then
  35        test_set_prereq HEADER_ONLY_TAR_OK
  36fi
  37
  38test_expect_success HEADER_ONLY_TAR_OK 'tar archive of commit with empty tree' '
  39        git archive --format=tar HEAD >empty-with-pax-header.tar &&
  40        make_dir extract &&
  41        "$TAR" xf empty-with-pax-header.tar -C extract &&
  42        check_dir extract
  43'
  44
  45test_expect_success 'tar archive of empty tree is empty' '
  46        git archive --format=tar HEAD: >empty.tar &&
  47        perl -e "print \"\\0\" x 10240" >10knuls.tar &&
  48        test_cmp_bin 10knuls.tar empty.tar
  49'
  50
  51test_expect_success 'tar archive of empty tree with prefix' '
  52        git archive --format=tar --prefix=foo/ HEAD >prefix.tar &&
  53        make_dir extract &&
  54        "$TAR" xf prefix.tar -C extract &&
  55        check_dir extract foo
  56'
  57
  58test_expect_success UNZIP 'zip archive of empty tree is empty' '
  59        # Detect the exit code produced when our particular flavor of unzip
  60        # sees an empty archive. Infozip will generate a warning and exit with
  61        # code 1. But in the name of sanity, we do not expect other unzip
  62        # implementations to do the same thing (it would be perfectly
  63        # reasonable to exit 0, for example).
  64        #
  65        # This makes our test less rigorous on some platforms (unzip may not
  66        # handle the empty repo at all, making our later check of its exit code
  67        # a no-op). But we cannot do anything reasonable except skip the test
  68        # on such platforms anyway, and this is the moral equivalent.
  69        {
  70                "$GIT_UNZIP" "$TEST_DIRECTORY"/t5004/empty.zip
  71                expect_code=$?
  72        } &&
  73
  74        git archive --format=zip HEAD >empty.zip &&
  75        make_dir extract &&
  76        (
  77                cd extract &&
  78                test_expect_code $expect_code "$GIT_UNZIP" ../empty.zip
  79        ) &&
  80        check_dir extract
  81'
  82
  83test_expect_success UNZIP 'zip archive of empty tree with prefix' '
  84        # We do not have to play exit-code tricks here, because our
  85        # result should not be empty; it has a directory in it.
  86        git archive --format=zip --prefix=foo/ HEAD >prefix.zip &&
  87        make_dir extract &&
  88        (
  89                cd extract &&
  90                "$GIT_UNZIP" ../prefix.zip
  91        ) &&
  92        check_dir extract foo
  93'
  94
  95test_expect_success 'archive complains about pathspec on empty tree' '
  96        test_must_fail git archive --format=tar HEAD -- foo >/dev/null
  97'
  98
  99test_expect_success 'create a commit with an empty subtree' '
 100        empty_tree=$(git hash-object -t tree /dev/null) &&
 101        root_tree=$(printf "040000 tree $empty_tree\tsub\n" | git mktree)
 102'
 103
 104test_expect_success 'archive empty subtree with no pathspec' '
 105        git archive --format=tar $root_tree >subtree-all.tar &&
 106        make_dir extract &&
 107        "$TAR" xf subtree-all.tar -C extract &&
 108        check_dir extract sub
 109'
 110
 111test_expect_success 'archive empty subtree by direct pathspec' '
 112        git archive --format=tar $root_tree -- sub >subtree-path.tar &&
 113        make_dir extract &&
 114        "$TAR" xf subtree-path.tar -C extract &&
 115        check_dir extract sub
 116'
 117
 118ZIPINFO=zipinfo
 119
 120test_lazy_prereq ZIPINFO '
 121        n=$("$ZIPINFO" "$TEST_DIRECTORY"/t5004/empty.zip | sed -n "2s/.* //p")
 122        test "x$n" = "x0"
 123'
 124
 125test_expect_success ZIPINFO 'zip archive with many entries' '
 126        # add a directory with 256 files
 127        mkdir 00 &&
 128        for a in 0 1 2 3 4 5 6 7 8 9 a b c d e f
 129        do
 130                for b in 0 1 2 3 4 5 6 7 8 9 a b c d e f
 131                do
 132                        : >00/$a$b
 133                done
 134        done &&
 135        git add 00 &&
 136        git commit -m "256 files in 1 directory" &&
 137
 138        # duplicate it to get 65536 files in 256 directories
 139        subtree=$(git write-tree --prefix=00/) &&
 140        for c in 0 1 2 3 4 5 6 7 8 9 a b c d e f
 141        do
 142                for d in 0 1 2 3 4 5 6 7 8 9 a b c d e f
 143                do
 144                        echo "040000 tree $subtree      $c$d"
 145                done
 146        done >tree &&
 147        tree=$(git mktree <tree) &&
 148
 149        # zip them
 150        git archive -o many.zip $tree &&
 151
 152        # check the number of entries in the ZIP file directory
 153        expr 65536 + 256 >expect &&
 154        "$ZIPINFO" many.zip | head -2 | sed -n "2s/.* //p" >actual &&
 155        test_cmp expect actual
 156'
 157
 158test_expect_success EXPENSIVE,UNZIP 'zip archive bigger than 4GB' '
 159        # build string containing 65536 characters
 160        s=0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef &&
 161        s=$s$s$s$s$s$s$s$s$s$s$s$s$s$s$s$s$s$s$s$s$s$s$s$s$s$s$s$s$s$s$s$s &&
 162        s=$s$s$s$s$s$s$s$s$s$s$s$s$s$s$s$s$s$s$s$s$s$s$s$s$s$s$s$s$s$s$s$s &&
 163
 164        # create blob with a length of 65536 + 1 bytes
 165        blob=$(echo $s | git hash-object -w --stdin) &&
 166
 167        # create tree containing 65500 entries of that blob
 168        for i in $(test_seq 1 65500)
 169        do
 170                echo "100644 blob $blob $i"
 171        done >tree &&
 172        tree=$(git mktree <tree) &&
 173
 174        # zip it, creating an archive a bit bigger than 4GB
 175        git archive -0 -o many-big.zip $tree &&
 176
 177        "$GIT_UNZIP" -t many-big.zip 9999 65500 &&
 178        "$GIT_UNZIP" -t many-big.zip
 179'
 180
 181test_expect_success EXPENSIVE,UNZIP,ZIPINFO 'zip archive with files bigger than 4GB' '
 182        # Pack created with:
 183        #   dd if=/dev/zero of=file bs=1M count=4100 && git hash-object -w file
 184        mkdir -p .git/objects/pack &&
 185        (
 186                cd .git/objects/pack &&
 187                "$GIT_UNZIP" "$TEST_DIRECTORY"/t5004/big-pack.zip
 188        ) &&
 189        blob=754a93d6fada4c6873360e6cb4b209132271ab0e &&
 190        size=$(expr 4100 "*" 1024 "*" 1024) &&
 191
 192        # create a tree containing the file
 193        tree=$(echo "100644 blob $blob  big-file" | git mktree) &&
 194
 195        # zip it, creating an archive with a file bigger than 4GB
 196        git archive -o big.zip $tree &&
 197
 198        "$GIT_UNZIP" -t big.zip &&
 199        "$ZIPINFO" big.zip >big.lst &&
 200        grep $size big.lst
 201'
 202
 203test_done