From cf72fb07b77c73b4777b6a2e0836e3029c5f0f3c Mon Sep 17 00:00:00 2001 From: Rene Scharfe Date: Sat, 7 Oct 2006 01:47:24 +0200 Subject: [PATCH 1/2] git-archive --format=zip: use default version ID Use 10 for the "version needed to extract" field. This is the default value, and we want to use it because we don't do anything special. Info-ZIP's zip uses it, too. Signed-off-by: Rene Scharfe Signed-off-by: Junio C Hamano --- archive-zip.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/archive-zip.c b/archive-zip.c index 3ffdad68d1..ae7462353d 100644 --- a/archive-zip.c +++ b/archive-zip.c @@ -214,7 +214,7 @@ static int write_zip_entry(const unsigned char *sha1, copy_le32(dirent.magic, 0x02014b50); copy_le16(dirent.creator_version, 0); - copy_le16(dirent.version, 20); + copy_le16(dirent.version, 10); copy_le16(dirent.flags, 0); copy_le16(dirent.compression_method, method); copy_le16(dirent.mtime, zip_time); @@ -236,7 +236,7 @@ static int write_zip_entry(const unsigned char *sha1, zip_dir_entries++; copy_le32(header.magic, 0x04034b50); - copy_le16(header.version, 20); + copy_le16(header.version, 10); copy_le16(header.flags, 0); copy_le16(header.compression_method, method); copy_le16(header.mtime, zip_time); From 62cdce17c57a28240048c5064fab57edae19657f Mon Sep 17 00:00:00 2001 From: Rene Scharfe Date: Sat, 7 Oct 2006 01:47:35 +0200 Subject: [PATCH 2/2] git-archive --format=zip: add symlink support Add symlink support to ZIP file creation, and a few tests. This implementation sets the "version made by" field (creator_version) to Unix for symlinks, only; regular files and directories are still marked as originating from FAT/VFAT/NTFS. Also set "external file attributes" (attr2) to 0 for regular files and 16 for directories (FAT attribute), and to the file mode for symlinks. We could always set the creator_version to Unix and include the mode, but then Info-ZIP unzip would set the mode of the extracted files to *exactly* the value stored in attr2. The FAT trick makes it apply the umask instead. Note: FAT has no executable bit, so this information is not stored in the ZIP file. Signed-off-by: Rene Scharfe Signed-off-by: Junio C Hamano --- archive-zip.c | 13 +++++++++---- t/t5000-tar-tree.sh | 35 +++++++++++++++++++++++++++++++++++ 2 files changed, 44 insertions(+), 4 deletions(-) diff --git a/archive-zip.c b/archive-zip.c index ae7462353d..28e7352e98 100644 --- a/archive-zip.c +++ b/archive-zip.c @@ -145,6 +145,7 @@ static int write_zip_entry(const unsigned char *sha1, { struct zip_local_header header; struct zip_dir_header dirent; + unsigned long attr2; unsigned long compressed_size; unsigned long uncompressed_size; unsigned long crc; @@ -172,12 +173,16 @@ static int write_zip_entry(const unsigned char *sha1, if (S_ISDIR(mode)) { method = 0; + attr2 = 16; result = READ_TREE_RECURSIVE; out = NULL; uncompressed_size = 0; compressed_size = 0; - } else if (S_ISREG(mode)) { - method = zlib_compression_level == 0 ? 0 : 8; + } else if (S_ISREG(mode) || S_ISLNK(mode)) { + method = 0; + attr2 = S_ISLNK(mode) ? ((mode | 0777) << 16) : 0; + if (S_ISREG(mode) && zlib_compression_level != 0) + method = 8; result = 0; buffer = read_sha1_file(sha1, type, &size); if (!buffer) @@ -213,7 +218,7 @@ static int write_zip_entry(const unsigned char *sha1, } copy_le32(dirent.magic, 0x02014b50); - copy_le16(dirent.creator_version, 0); + copy_le16(dirent.creator_version, S_ISLNK(mode) ? 0x0317 : 0); copy_le16(dirent.version, 10); copy_le16(dirent.flags, 0); copy_le16(dirent.compression_method, method); @@ -227,7 +232,7 @@ static int write_zip_entry(const unsigned char *sha1, copy_le16(dirent.comment_length, 0); copy_le16(dirent.disk, 0); copy_le16(dirent.attr1, 0); - copy_le32(dirent.attr2, 0); + copy_le32(dirent.attr2, attr2); copy_le32(dirent.offset, zip_offset); memcpy(zip_dir + zip_dir_offset, &dirent, sizeof(struct zip_dir_header)); zip_dir_offset += sizeof(struct zip_dir_header); diff --git a/t/t5000-tar-tree.sh b/t/t5000-tar-tree.sh index 278eb66701..cf08e9279c 100755 --- a/t/t5000-tar-tree.sh +++ b/t/t5000-tar-tree.sh @@ -26,6 +26,7 @@ commit id embedding: . ./test-lib.sh TAR=${TAR:-tar} +UNZIP=${UNZIP:-unzip} test_expect_success \ 'populate workdir' \ @@ -95,4 +96,38 @@ test_expect_success \ 'validate file contents with prefix' \ 'diff -r a c/prefix/a' +test_expect_success \ + 'git-archive --format=zip' \ + 'git-archive --format=zip HEAD >d.zip' + +test_expect_success \ + 'extract ZIP archive' \ + '(mkdir d && cd d && $UNZIP ../d.zip)' + +test_expect_success \ + 'validate filenames' \ + '(cd d/a && find .) | sort >d.lst && + diff a.lst d.lst' + +test_expect_success \ + 'validate file contents' \ + 'diff -r a d/a' + +test_expect_success \ + 'git-archive --format=zip with prefix' \ + 'git-archive --format=zip --prefix=prefix/ HEAD >e.zip' + +test_expect_success \ + 'extract ZIP archive with prefix' \ + '(mkdir e && cd e && $UNZIP ../e.zip)' + +test_expect_success \ + 'validate filenames with prefix' \ + '(cd e/prefix/a && find .) | sort >e.lst && + diff a.lst e.lst' + +test_expect_success \ + 'validate file contents with prefix' \ + 'diff -r a e/prefix/a' + test_done