Skip to content

Commit 200589a

Browse files
rscharfegitster
authored andcommitted
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 <[email protected]> Signed-off-by: Junio C Hamano <[email protected]>
1 parent 385c171 commit 200589a

File tree

4 files changed

+34
-48
lines changed

4 files changed

+34
-48
lines changed

Diff for: archive-tar.c

+3-19
Original file line numberDiff line numberDiff line change
@@ -242,13 +242,12 @@ static void write_extended_header(struct archiver_args *args,
242242
static int write_tar_entry(struct archiver_args *args,
243243
const struct object_id *oid,
244244
const char *path, size_t pathlen,
245-
unsigned int mode)
245+
unsigned int mode,
246+
void *buffer, unsigned long size)
246247
{
247248
struct ustar_header header;
248249
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;
252251
int err = 0;
253252

254253
memset(&header, 0, sizeof(header));
@@ -282,20 +281,6 @@ static int write_tar_entry(struct archiver_args *args,
282281
} else
283282
memcpy(header.name, path, pathlen);
284283

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-
299284
if (S_ISLNK(mode)) {
300285
if (size > sizeof(header.linkname)) {
301286
xsnprintf(header.linkname, sizeof(header.linkname),
@@ -326,7 +311,6 @@ static int write_tar_entry(struct archiver_args *args,
326311
else
327312
err = stream_blocked(args->repo, oid);
328313
}
329-
free(buffer);
330314
return err;
331315
}
332316

Diff for: archive-zip.c

+5-17
Original file line numberDiff line numberDiff line change
@@ -285,7 +285,8 @@ static int entry_is_binary(struct index_state *istate, const char *path,
285285
static int write_zip_entry(struct archiver_args *args,
286286
const struct object_id *oid,
287287
const char *path, size_t pathlen,
288-
unsigned int mode)
288+
unsigned int mode,
289+
void *buffer, unsigned long size)
289290
{
290291
struct zip_local_header header;
291292
uintmax_t offset = zip_offset;
@@ -299,10 +300,8 @@ static int write_zip_entry(struct archiver_args *args,
299300
enum zip_method method;
300301
unsigned char *out;
301302
void *deflated = NULL;
302-
void *buffer;
303303
struct git_istream *stream = NULL;
304304
unsigned long flags = 0;
305-
unsigned long size;
306305
int is_binary = -1;
307306
const char *path_without_prefix = path + args->baselen;
308307
unsigned int creator_version = 0;
@@ -328,13 +327,8 @@ static int write_zip_entry(struct archiver_args *args,
328327
method = ZIP_METHOD_STORE;
329328
attr2 = 16;
330329
out = NULL;
331-
size = 0;
332330
compressed_size = 0;
333-
buffer = NULL;
334331
} else if (S_ISREG(mode) || S_ISLNK(mode)) {
335-
enum object_type type = oid_object_info(args->repo, oid,
336-
&size);
337-
338332
method = ZIP_METHOD_STORE;
339333
attr2 = S_ISLNK(mode) ? ((mode | 0777) << 16) :
340334
(mode & 0111) ? ((mode) << 16) : 0;
@@ -343,21 +337,16 @@ static int write_zip_entry(struct archiver_args *args,
343337
if (S_ISREG(mode) && args->compression_level != 0 && size > 0)
344338
method = ZIP_METHOD_DEFLATE;
345339

346-
if (S_ISREG(mode) && type == OBJ_BLOB && !args->convert &&
347-
size > big_file_threshold) {
340+
if (!buffer) {
341+
enum object_type type;
348342
stream = open_istream(args->repo, oid, &type, &size,
349343
NULL);
350344
if (!stream)
351345
return error(_("cannot stream blob %s"),
352346
oid_to_hex(oid));
353347
flags |= ZIP_STREAM;
354-
out = buffer = NULL;
348+
out = NULL;
355349
} 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));
361350
crc = crc32(crc, buffer, size);
362351
is_binary = entry_is_binary(args->repo->index,
363352
path_without_prefix,
@@ -511,7 +500,6 @@ static int write_zip_entry(struct archiver_args *args,
511500
}
512501

513502
free(deflated);
514-
free(buffer);
515503

516504
if (compressed_size > 0xffffffff || size > 0xffffffff ||
517505
offset > 0xffffffff) {

Diff for: archive.c

+24-7
Original file line numberDiff line numberDiff line change
@@ -70,10 +70,12 @@ static void format_subst(const struct commit *commit,
7070
free(to_free);
7171
}
7272

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)
7779
{
7880
void *buffer;
7981
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,
145147
write_archive_entry_fn_t write_entry = c->write_entry;
146148
int err;
147149
const char *path_without_prefix;
150+
unsigned long size;
151+
void *buffer;
152+
enum object_type type;
148153

149154
args->convert = 0;
150155
strbuf_reset(&path);
@@ -167,15 +172,27 @@ static int write_archive_entry(const struct object_id *oid, const char *base,
167172
if (S_ISDIR(mode) || S_ISGITLINK(mode)) {
168173
if (args->verbose)
169174
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);
171176
if (err)
172177
return err;
173178
return (S_ISDIR(mode) ? READ_TREE_RECURSIVE : 0);
174179
}
175180

176181
if (args->verbose)
177182
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;
179196
}
180197

181198
static void queue_directory(const unsigned char *sha1,
@@ -265,7 +282,7 @@ int write_archive_entries(struct archiver_args *args,
265282
if (args->verbose)
266283
fprintf(stderr, "%.*s\n", (int)len, args->base);
267284
err = write_entry(args, &args->tree->object.oid, args->base,
268-
len, 040777);
285+
len, 040777, NULL, 0);
269286
if (err)
270287
return err;
271288
}

Diff for: archive.h

+2-5
Original file line numberDiff line numberDiff line change
@@ -49,12 +49,9 @@ void init_archivers(void);
4949
typedef int (*write_archive_entry_fn_t)(struct archiver_args *args,
5050
const struct object_id *oid,
5151
const char *path, size_t pathlen,
52-
unsigned int mode);
52+
unsigned int mode,
53+
void *buffer, unsigned long size);
5354

5455
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);
5956

6057
#endif /* ARCHIVE_H */

0 commit comments

Comments
 (0)