]> git.ipfire.org Git - thirdparty/git.git/commitdiff
archive: read short blobs in archive.c::write_archive_entry()
authorRené Scharfe <l.s.r@web.de>
Sat, 19 Sep 2020 21:23:32 +0000 (23:23 +0200)
committerJunio C Hamano <gitster@pobox.com>
Sat, 19 Sep 2020 22:56:05 +0000 (15:56 -0700)
Centralize reading of symlink destinations and the contents of regular
files that are too small to be streamed.  This reduces code duplication
and allows future patches to add support for adding non-tracked files to
archives.  The backends are expected to stream blobs if buffer is NULL.

object_file_to_archive() is only called from archive.c and thus no
longer exported.

Signed-off-by: René Scharfe <l.s.r@web.de>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
archive-tar.c
archive-zip.c
archive.c
archive.h

index 5ceec3684be910c44216d38e11f240fa4cc22ed3..f1a1447ebda0a11b62cfead71a0f41a22439b392 100644 (file)
@@ -242,13 +242,12 @@ static void write_extended_header(struct archiver_args *args,
 static int write_tar_entry(struct archiver_args *args,
                           const struct object_id *oid,
                           const char *path, size_t pathlen,
-                          unsigned int mode)
+                          unsigned int mode,
+                          void *buffer, unsigned long size)
 {
        struct ustar_header header;
        struct strbuf ext_header = STRBUF_INIT;
-       unsigned int old_mode = mode;
-       unsigned long size, size_in_header;
-       void *buffer;
+       unsigned long size_in_header;
        int err = 0;
 
        memset(&header, 0, sizeof(header));
@@ -282,20 +281,6 @@ static int write_tar_entry(struct archiver_args *args,
        } else
                memcpy(header.name, path, pathlen);
 
-       if (S_ISREG(mode) && !args->convert &&
-           oid_object_info(args->repo, oid, &size) == OBJ_BLOB &&
-           size > big_file_threshold)
-               buffer = NULL;
-       else if (S_ISLNK(mode) || S_ISREG(mode)) {
-               enum object_type type;
-               buffer = object_file_to_archive(args, path, oid, old_mode, &type, &size);
-               if (!buffer)
-                       return error(_("cannot read %s"), oid_to_hex(oid));
-       } else {
-               buffer = NULL;
-               size = 0;
-       }
-
        if (S_ISLNK(mode)) {
                if (size > sizeof(header.linkname)) {
                        xsnprintf(header.linkname, sizeof(header.linkname),
@@ -326,7 +311,6 @@ static int write_tar_entry(struct archiver_args *args,
                else
                        err = stream_blocked(args->repo, oid);
        }
-       free(buffer);
        return err;
 }
 
index e9f426298b6d1c4ce64a1ef537a97375a8855d3c..2961e01c754fc4641af62f7d45e63458eb4f942d 100644 (file)
@@ -285,7 +285,8 @@ static int entry_is_binary(struct index_state *istate, const char *path,
 static int write_zip_entry(struct archiver_args *args,
                           const struct object_id *oid,
                           const char *path, size_t pathlen,
-                          unsigned int mode)
+                          unsigned int mode,
+                          void *buffer, unsigned long size)
 {
        struct zip_local_header header;
        uintmax_t offset = zip_offset;
@@ -299,10 +300,8 @@ static int write_zip_entry(struct archiver_args *args,
        enum zip_method method;
        unsigned char *out;
        void *deflated = NULL;
-       void *buffer;
        struct git_istream *stream = NULL;
        unsigned long flags = 0;
-       unsigned long size;
        int is_binary = -1;
        const char *path_without_prefix = path + args->baselen;
        unsigned int creator_version = 0;
@@ -328,13 +327,8 @@ static int write_zip_entry(struct archiver_args *args,
                method = ZIP_METHOD_STORE;
                attr2 = 16;
                out = NULL;
-               size = 0;
                compressed_size = 0;
-               buffer = NULL;
        } else if (S_ISREG(mode) || S_ISLNK(mode)) {
-               enum object_type type = oid_object_info(args->repo, oid,
-                                                       &size);
-
                method = ZIP_METHOD_STORE;
                attr2 = S_ISLNK(mode) ? ((mode | 0777) << 16) :
                        (mode & 0111) ? ((mode) << 16) : 0;
@@ -343,21 +337,16 @@ static int write_zip_entry(struct archiver_args *args,
                if (S_ISREG(mode) && args->compression_level != 0 && size > 0)
                        method = ZIP_METHOD_DEFLATE;
 
-               if (S_ISREG(mode) && type == OBJ_BLOB && !args->convert &&
-                   size > big_file_threshold) {
+               if (!buffer) {
+                       enum object_type type;
                        stream = open_istream(args->repo, oid, &type, &size,
                                              NULL);
                        if (!stream)
                                return error(_("cannot stream blob %s"),
                                             oid_to_hex(oid));
                        flags |= ZIP_STREAM;
-                       out = buffer = NULL;
+                       out = NULL;
                } else {
-                       buffer = object_file_to_archive(args, path, oid, mode,
-                                                       &type, &size);
-                       if (!buffer)
-                               return error(_("cannot read %s"),
-                                            oid_to_hex(oid));
                        crc = crc32(crc, buffer, size);
                        is_binary = entry_is_binary(args->repo->index,
                                                    path_without_prefix,
@@ -511,7 +500,6 @@ static int write_zip_entry(struct archiver_args *args,
        }
 
        free(deflated);
-       free(buffer);
 
        if (compressed_size > 0xffffffff || size > 0xffffffff ||
            offset > 0xffffffff) {
index 0de6048bfccb8df89a1fce9abbeb3d0f65f004fc..4fbe5329c562b4cd4ed30d92a8fc7c01fd6f73bb 100644 (file)
--- a/archive.c
+++ b/archive.c
@@ -70,10 +70,12 @@ static void format_subst(const struct commit *commit,
        free(to_free);
 }
 
-void *object_file_to_archive(const struct archiver_args *args,
-                            const char *path, const struct object_id *oid,
-                            unsigned int mode, enum object_type *type,
-                            unsigned long *sizep)
+static void *object_file_to_archive(const struct archiver_args *args,
+                                   const char *path,
+                                   const struct object_id *oid,
+                                   unsigned int mode,
+                                   enum object_type *type,
+                                   unsigned long *sizep)
 {
        void *buffer;
        const struct commit *commit = args->convert ? args->commit : NULL;
@@ -145,6 +147,9 @@ static int write_archive_entry(const struct object_id *oid, const char *base,
        write_archive_entry_fn_t write_entry = c->write_entry;
        int err;
        const char *path_without_prefix;
+       unsigned long size;
+       void *buffer;
+       enum object_type type;
 
        args->convert = 0;
        strbuf_reset(&path);
@@ -167,7 +172,7 @@ static int write_archive_entry(const struct object_id *oid, const char *base,
        if (S_ISDIR(mode) || S_ISGITLINK(mode)) {
                if (args->verbose)
                        fprintf(stderr, "%.*s\n", (int)path.len, path.buf);
-               err = write_entry(args, oid, path.buf, path.len, mode);
+               err = write_entry(args, oid, path.buf, path.len, mode, NULL, 0);
                if (err)
                        return err;
                return (S_ISDIR(mode) ? READ_TREE_RECURSIVE : 0);
@@ -175,7 +180,19 @@ static int write_archive_entry(const struct object_id *oid, const char *base,
 
        if (args->verbose)
                fprintf(stderr, "%.*s\n", (int)path.len, path.buf);
-       return write_entry(args, oid, path.buf, path.len, mode);
+
+       /* Stream it? */
+       if (S_ISREG(mode) && !args->convert &&
+           oid_object_info(args->repo, oid, &size) == OBJ_BLOB &&
+           size > big_file_threshold)
+               return write_entry(args, oid, path.buf, path.len, mode, NULL, size);
+
+       buffer = object_file_to_archive(args, path.buf, oid, mode, &type, &size);
+       if (!buffer)
+               return error(_("cannot read %s"), oid_to_hex(oid));
+       err = write_entry(args, oid, path.buf, path.len, mode, buffer, size);
+       free(buffer);
+       return err;
 }
 
 static void queue_directory(const unsigned char *sha1,
@@ -265,7 +282,7 @@ int write_archive_entries(struct archiver_args *args,
                if (args->verbose)
                        fprintf(stderr, "%.*s\n", (int)len, args->base);
                err = write_entry(args, &args->tree->object.oid, args->base,
-                                 len, 040777);
+                                 len, 040777, NULL, 0);
                if (err)
                        return err;
        }
index 3bd96bf6bba7ecaacb6b50e1f02080f95d11f17c..d83b41a01f1293cec6a1360023fad988da5a2b20 100644 (file)
--- a/archive.h
+++ b/archive.h
@@ -49,12 +49,9 @@ void init_archivers(void);
 typedef int (*write_archive_entry_fn_t)(struct archiver_args *args,
                                        const struct object_id *oid,
                                        const char *path, size_t pathlen,
-                                       unsigned int mode);
+                                       unsigned int mode,
+                                       void *buffer, unsigned long size);
 
 int write_archive_entries(struct archiver_args *args, write_archive_entry_fn_t write_entry);
-void *object_file_to_archive(const struct archiver_args *args,
-                            const char *path, const struct object_id *oid,
-                            unsigned int mode, enum object_type *type,
-                            unsigned long *sizep);
 
 #endif /* ARCHIVE_H */