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 */