packfile: add repository argument to cache_or_unpack_entry
[gitweb.git] / archive-zip.c
index 44ed78f163e38449862663bf89153945e274a6c5..74f3fe9103420571c9f22273ae44ebb9d5715c78 100644 (file)
@@ -2,6 +2,7 @@
  * Copyright (c) 2006 Rene Scharfe
  */
 #include "cache.h"
+#include "config.h"
 #include "archive.h"
 #include "streaming.h"
 #include "utf8.h"
@@ -275,7 +276,7 @@ static int entry_is_binary(const char *path, const void *buffer, size_t size)
 #define STREAM_BUFFER_SIZE (1024 * 16)
 
 static int write_zip_entry(struct archiver_args *args,
-                          const unsigned char *sha1,
+                          const struct object_id *oid,
                           const char *path, size_t pathlen,
                           unsigned int mode)
 {
@@ -298,6 +299,7 @@ static int write_zip_entry(struct archiver_args *args,
        int is_binary = -1;
        const char *path_without_prefix = path + args->baselen;
        unsigned int creator_version = 0;
+       unsigned int version_needed = 10;
        size_t zip_dir_extra_size = ZIP_EXTRA_MTIME_SIZE;
        size_t zip64_dir_extra_payload_size = 0;
 
@@ -312,7 +314,7 @@ static int write_zip_entry(struct archiver_args *args,
 
        if (pathlen > 0xffff) {
                return error("path too long (%d chars, SHA1: %s): %s",
-                               (int)pathlen, sha1_to_hex(sha1), path);
+                               (int)pathlen, oid_to_hex(oid), path);
        }
 
        if (S_ISDIR(mode) || S_ISGITLINK(mode)) {
@@ -323,7 +325,8 @@ static int write_zip_entry(struct archiver_args *args,
                compressed_size = 0;
                buffer = NULL;
        } else if (S_ISREG(mode) || S_ISLNK(mode)) {
-               enum object_type type = sha1_object_info(sha1, &size);
+               enum object_type type = oid_object_info(the_repository, oid,
+                                                       &size);
 
                method = 0;
                attr2 = S_ISLNK(mode) ? ((mode | 0777) << 16) :
@@ -335,18 +338,18 @@ static int write_zip_entry(struct archiver_args *args,
 
                if (S_ISREG(mode) && type == OBJ_BLOB && !args->convert &&
                    size > big_file_threshold) {
-                       stream = open_istream(sha1, &type, &size, NULL);
+                       stream = open_istream(oid, &type, &size, NULL);
                        if (!stream)
                                return error("cannot stream blob %s",
-                                            sha1_to_hex(sha1));
+                                            oid_to_hex(oid));
                        flags |= ZIP_STREAM;
                        out = buffer = NULL;
                } else {
-                       buffer = sha1_file_to_archive(args, path, sha1, mode,
-                                                     &type, &size);
+                       buffer = object_file_to_archive(args, path, oid, mode,
+                                                       &type, &size);
                        if (!buffer)
                                return error("cannot read %s",
-                                            sha1_to_hex(sha1));
+                                            oid_to_hex(oid));
                        crc = crc32(crc, buffer, size);
                        is_binary = entry_is_binary(path_without_prefix,
                                                    buffer, size);
@@ -355,7 +358,7 @@ static int write_zip_entry(struct archiver_args *args,
                compressed_size = (method == 0) ? size : 0;
        } else {
                return error("unsupported file mode: 0%o (SHA1: %s)", mode,
-                               sha1_to_hex(sha1));
+                               oid_to_hex(oid));
        }
 
        if (creator_version > max_creator_version)
@@ -382,8 +385,11 @@ static int write_zip_entry(struct archiver_args *args,
        if (stream && size > 0x7fffffff)
                need_zip64_extra = 1;
 
+       if (need_zip64_extra)
+               version_needed = 45;
+
        copy_le32(header.magic, 0x04034b50);
-       copy_le16(header.version, 10);
+       copy_le16(header.version, version_needed);
        copy_le16(header.flags, flags);
        copy_le16(header.compression_method, method);
        copy_le16(header.mtime, zip_time);
@@ -509,7 +515,7 @@ static int write_zip_entry(struct archiver_args *args,
 
        strbuf_add_le(&zip_dir, 4, 0x02014b50); /* magic */
        strbuf_add_le(&zip_dir, 2, creator_version);
-       strbuf_add_le(&zip_dir, 2, 10);         /* version */
+       strbuf_add_le(&zip_dir, 2, version_needed);
        strbuf_add_le(&zip_dir, 2, flags);
        strbuf_add_le(&zip_dir, 2, method);
        strbuf_add_le(&zip_dir, 2, zip_time);
@@ -589,9 +595,17 @@ static void write_zip_trailer(const unsigned char *sha1)
                write_or_die(1, sha1_to_hex(sha1), GIT_SHA1_HEXSZ);
 }
 
-static void dos_time(time_t *time, int *dos_date, int *dos_time)
+static void dos_time(timestamp_t *timestamp, int *dos_date, int *dos_time)
 {
-       struct tm *t = localtime(time);
+       time_t time;
+       struct tm *t;
+
+       if (date_overflows(*timestamp))
+               die("timestamp too large for this system: %"PRItime,
+                   *timestamp);
+       time = (time_t)*timestamp;
+       t = localtime(&time);
+       *timestamp = time;
 
        *dos_date = t->tm_mday + (t->tm_mon + 1) * 32 +
                    (t->tm_year + 1900 - 1980) * 512;