@matheusbsbs / matheus-bagliano / commits / 200589abcb
Fork 0

archive: read short blobs in archive.c::write_archive_entry()

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>

René Scharfe committed Sep 19, 2020 at 23:23 UTC 200589abcb4d7f107ed9da85e43b9a7268016c23
4 files changed +34 -48
archive-tar.c
+3 -19
@@ -242,13 +242,12 @@ static void write_extended_header(struct archiver_args *args,
242 static int write_tar_entry(struct archiver_args *args,
243 const struct object_id *oid,
244 const char *path, size_t pathlen,
245 - unsigned int mode)
245 + unsigned int mode,
246 + void *buffer, unsigned long size)
247 {
248 struct ustar_header header;
249 struct strbuf ext_header = STRBUF_INIT;
249 - unsigned int old_mode = mode;
250 - unsigned long size, size_in_header;
251 - void *buffer;
250 + unsigned long size_in_header;
251 int err = 0;
252
253 memset(&header, 0, sizeof(header));
@@ -282,20 +281,6 @@ static int write_tar_entry(struct archiver_args *args,
281 } else
282 memcpy(header.name, path, pathlen);
283
285 - if (S_ISREG(mode) && !args->convert &&
286 - oid_object_info(args->repo, oid, &size) == OBJ_BLOB &&
287 - size > big_file_threshold)
288 - buffer = NULL;
289 - else if (S_ISLNK(mode) || S_ISREG(mode)) {
290 - enum object_type type;
291 - buffer = object_file_to_archive(args, path, oid, old_mode, &type, &size);
292 - if (!buffer)
293 - return error(_("cannot read %s"), oid_to_hex(oid));
294 - } else {
295 - buffer = NULL;
296 - size = 0;
297 - }
298 -
284 if (S_ISLNK(mode)) {
285 if (size > sizeof(header.linkname)) {
286 xsnprintf(header.linkname, sizeof(header.linkname),
@@ -326,7 +311,6 @@ static int write_tar_entry(struct archiver_args *args,
311 else
312 err = stream_blocked(args->repo, oid);
313 }
329 - free(buffer);
314 return err;
315 }
316
archive-zip.c
+5 -17
@@ -285,7 +285,8 @@ static int entry_is_binary(struct index_state *istate, const char *path,
285 static int write_zip_entry(struct archiver_args *args,
286 const struct object_id *oid,
287 const char *path, size_t pathlen,
288 - unsigned int mode)
288 + unsigned int mode,
289 + void *buffer, unsigned long size)
290 {
291 struct zip_local_header header;
292 uintmax_t offset = zip_offset;
@@ -299,10 +300,8 @@ static int write_zip_entry(struct archiver_args *args,
300 enum zip_method method;
301 unsigned char *out;
302 void *deflated = NULL;
302 - void *buffer;
303 struct git_istream *stream = NULL;
304 unsigned long flags = 0;
305 - unsigned long size;
305 int is_binary = -1;
306 const char *path_without_prefix = path + args->baselen;
307 unsigned int creator_version = 0;
@@ -328,13 +327,8 @@ static int write_zip_entry(struct archiver_args *args,
327 method = ZIP_METHOD_STORE;
328 attr2 = 16;
329 out = NULL;
331 - size = 0;
330 compressed_size = 0;
333 - buffer = NULL;
331 } else if (S_ISREG(mode) || S_ISLNK(mode)) {
335 - enum object_type type = oid_object_info(args->repo, oid,
336 - &size);
337 -
332 method = ZIP_METHOD_STORE;
333 attr2 = S_ISLNK(mode) ? ((mode | 0777) << 16) :
334 (mode & 0111) ? ((mode) << 16) : 0;
@@ -343,21 +337,16 @@ static int write_zip_entry(struct archiver_args *args,
337 if (S_ISREG(mode) && args->compression_level != 0 && size > 0)
338 method = ZIP_METHOD_DEFLATE;
339
346 - if (S_ISREG(mode) && type == OBJ_BLOB && !args->convert &&
347 - size > big_file_threshold) {
340 + if (!buffer) {
341 + enum object_type type;
342 stream = open_istream(args->repo, oid, &type, &size,
343 NULL);
344 if (!stream)
345 return error(_("cannot stream blob %s"),
346 oid_to_hex(oid));
347 flags |= ZIP_STREAM;
354 - out = buffer = NULL;
348 + out = NULL;
349 } else {
356 - buffer = object_file_to_archive(args, path, oid, mode,
357 - &type, &size);
358 - if (!buffer)
359 - return error(_("cannot read %s"),
360 - oid_to_hex(oid));
350 crc = crc32(crc, buffer, size);
351 is_binary = entry_is_binary(args->repo->index,
352 path_without_prefix,
@@ -511,7 +500,6 @@ static int write_zip_entry(struct archiver_args *args,
500 }
501
502 free(deflated);
514 - free(buffer);
503
504 if (compressed_size > 0xffffffff || size > 0xffffffff ||
505 offset > 0xffffffff) {
archive.c
+24 -7
@@ -70,10 +70,12 @@ static void format_subst(const struct commit *commit,
70 free(to_free);
71 }
72
73 -void *object_file_to_archive(const struct archiver_args *args,
74 - const char *path, const struct object_id *oid,
75 - unsigned int mode, enum object_type *type,
76 - unsigned long *sizep)
73 +static void *object_file_to_archive(const struct archiver_args *args,
74 + const char *path,
75 + const struct object_id *oid,
76 + unsigned int mode,
77 + enum object_type *type,
78 + unsigned long *sizep)
79 {
80 void *buffer;
81 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,
147 write_archive_entry_fn_t write_entry = c->write_entry;
148 int err;
149 const char *path_without_prefix;
150 + unsigned long size;
151 + void *buffer;
152 + enum object_type type;
153
154 args->convert = 0;
155 strbuf_reset(&path);
@@ -167,7 +172,7 @@ static int write_archive_entry(const struct object_id *oid, const char *base,
172 if (S_ISDIR(mode) || S_ISGITLINK(mode)) {
173 if (args->verbose)
174 fprintf(stderr, "%.*s\n", (int)path.len, path.buf);
170 - err = write_entry(args, oid, path.buf, path.len, mode);
175 + err = write_entry(args, oid, path.buf, path.len, mode, NULL, 0);
176 if (err)
177 return err;
178 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,
180
181 if (args->verbose)
182 fprintf(stderr, "%.*s\n", (int)path.len, path.buf);
178 - return write_entry(args, oid, path.buf, path.len, mode);
183 +
184 + /* Stream it? */
185 + if (S_ISREG(mode) && !args->convert &&
186 + oid_object_info(args->repo, oid, &size) == OBJ_BLOB &&
187 + size > big_file_threshold)
188 + return write_entry(args, oid, path.buf, path.len, mode, NULL, size);
189 +
190 + buffer = object_file_to_archive(args, path.buf, oid, mode, &type, &size);
191 + if (!buffer)
192 + return error(_("cannot read %s"), oid_to_hex(oid));
193 + err = write_entry(args, oid, path.buf, path.len, mode, buffer, size);
194 + free(buffer);
195 + return err;
196 }
197
198 static void queue_directory(const unsigned char *sha1,
@@ -265,7 +282,7 @@ int write_archive_entries(struct archiver_args *args,
282 if (args->verbose)
283 fprintf(stderr, "%.*s\n", (int)len, args->base);
284 err = write_entry(args, &args->tree->object.oid, args->base,
268 - len, 040777);
285 + len, 040777, NULL, 0);
286 if (err)
287 return err;
288 }
archive.h
+2 -5
@@ -49,12 +49,9 @@ void init_archivers(void);
49 typedef int (*write_archive_entry_fn_t)(struct archiver_args *args,
50 const struct object_id *oid,
51 const char *path, size_t pathlen,
52 - unsigned int mode);
52 + unsigned int mode,
53 + void *buffer, unsigned long size);
54
55 int write_archive_entries(struct archiver_args *args, write_archive_entry_fn_t write_entry);
55 -void *object_file_to_archive(const struct archiver_args *args,
56 - const char *path, const struct object_id *oid,
57 - unsigned int mode, enum object_type *type,
58 - unsigned long *sizep);
56
57 #endif /* ARCHIVE_H */