archive: delegate blob reading to backend
archive-tar.c and archive-zip.c now perform conversion check, with help of sha1_file_to_archive() from archive.c This gives backends more freedom in dealing with (streaming) large blobs. Signed-off-by: Nguyễn Thái Ngọc Duy <pclouds@gmail.com> Signed-off-by: Junio C Hamano <gitster@pobox.com>
Nguyễn Thái Ngọc Duy committed
May 3, 2012 at 08:51 UTC
9cb513b7988c2fe443c47186e42dd827b76ddb14
4 files changed
+54
-24
archive-tar.c
+21
-4
@@ -161,11 +161,15 @@ static int write_extended_header(struct archiver_args *args,
161
}
162
163
static int write_tar_entry(struct archiver_args *args,
164
- const unsigned char *sha1, const char *path, size_t pathlen,
165
- unsigned int mode, void *buffer, unsigned long size)
164
+ const unsigned char *sha1,
165
+ const char *path, size_t pathlen,
166
+ unsigned int mode)
167
{
168
struct ustar_header header;
169
struct strbuf ext_header = STRBUF_INIT;
170
+ unsigned int old_mode = mode;
171
+ unsigned long size;
172
+ void *buffer;
173
int err = 0;
174
175
memset(&header, 0, sizeof(header));
@@ -199,7 +203,17 @@ static int write_tar_entry(struct archiver_args *args,
203
} else
204
memcpy(header.name, path, pathlen);
205
202
- if (S_ISLNK(mode) && buffer) {
206
+ if (S_ISLNK(mode) || S_ISREG(mode)) {
207
+ enum object_type type;
208
+ buffer = sha1_file_to_archive(args, path, sha1, old_mode, &type, &size);
209
+ if (!buffer)
210
+ return error("cannot read %s", sha1_to_hex(sha1));
211
+ } else {
212
+ buffer = NULL;
213
+ size = 0;
214
+ }
215
+
216
+ if (S_ISLNK(mode)) {
217
if (size > sizeof(header.linkname)) {
218
sprintf(header.linkname, "see %s.paxheader",
219
sha1_to_hex(sha1));
@@ -214,13 +228,16 @@ static int write_tar_entry(struct archiver_args *args,
228
if (ext_header.len > 0) {
229
err = write_extended_header(args, sha1, ext_header.buf,
230
ext_header.len);
217
- if (err)
231
+ if (err) {
232
+ free(buffer);
233
return err;
234
+ }
235
}
236
strbuf_release(&ext_header);
237
write_blocked(&header, sizeof(header));
238
if (S_ISREG(mode) && buffer && size > 0)
239
write_blocked(buffer, size);
240
+ free(buffer);
241
return err;
242
}
243
archive-zip.c
+13
-2
@@ -121,8 +121,9 @@ static void *zlib_deflate(void *data, unsigned long size,
121
}
122
123
static int write_zip_entry(struct archiver_args *args,
124
- const unsigned char *sha1, const char *path, size_t pathlen,
125
- unsigned int mode, void *buffer, unsigned long size)
124
+ const unsigned char *sha1,
125
+ const char *path, size_t pathlen,
126
+ unsigned int mode)
127
{
128
struct zip_local_header header;
129
struct zip_dir_header dirent;
@@ -134,6 +135,8 @@ static int write_zip_entry(struct archiver_args *args,
135
int method;
136
unsigned char *out;
137
void *deflated = NULL;
138
+ void *buffer;
139
+ unsigned long size;
140
141
crc = crc32(0, NULL, 0);
142
@@ -148,7 +151,14 @@ static int write_zip_entry(struct archiver_args *args,
151
out = NULL;
152
uncompressed_size = 0;
153
compressed_size = 0;
154
+ buffer = NULL;
155
+ size = 0;
156
} else if (S_ISREG(mode) || S_ISLNK(mode)) {
157
+ enum object_type type;
158
+ buffer = sha1_file_to_archive(args, path, sha1, mode, &type, &size);
159
+ if (!buffer)
160
+ return error("cannot read %s", sha1_to_hex(sha1));
161
+
162
method = 0;
163
attr2 = S_ISLNK(mode) ? ((mode | 0777) << 16) :
164
(mode & 0111) ? ((mode) << 16) : 0;
@@ -229,6 +239,7 @@ static int write_zip_entry(struct archiver_args *args,
239
}
240
241
free(deflated);
242
+ free(buffer);
243
244
return 0;
245
}
archive.c
+11
-17
@@ -59,12 +59,15 @@ static void format_subst(const struct commit *commit,
59
free(to_free);
60
}
61
62
-static void *sha1_file_to_archive(const char *path, const unsigned char *sha1,
63
- unsigned int mode, enum object_type *type,
64
- unsigned long *sizep, const struct commit *commit)
62
+void *sha1_file_to_archive(const struct archiver_args *args,
63
+ const char *path, const unsigned char *sha1,
64
+ unsigned int mode, enum object_type *type,
65
+ unsigned long *sizep)
66
{
67
void *buffer;
68
+ const struct commit *commit = args->convert ? args->commit : NULL;
69
70
+ path += args->baselen;
71
buffer = read_sha1_file(sha1, type, sizep);
72
if (buffer && S_ISREG(mode)) {
73
struct strbuf buf = STRBUF_INIT;
@@ -109,12 +112,9 @@ static int write_archive_entry(const unsigned char *sha1, const char *base,
112
write_archive_entry_fn_t write_entry = c->write_entry;
113
struct git_attr_check check[2];
114
const char *path_without_prefix;
112
- int convert = 0;
115
int err;
114
- enum object_type type;
115
- unsigned long size;
116
- void *buffer;
116
117
+ args->convert = 0;
118
strbuf_reset(&path);
119
strbuf_grow(&path, PATH_MAX);
120
strbuf_add(&path, args->base, args->baselen);
@@ -126,28 +126,22 @@ static int write_archive_entry(const unsigned char *sha1, const char *base,
126
if (!git_check_attr(path_without_prefix, ARRAY_SIZE(check), check)) {
127
if (ATTR_TRUE(check[0].value))
128
return 0;
129
- convert = ATTR_TRUE(check[1].value);
129
+ args->convert = ATTR_TRUE(check[1].value);
130
}
131
132
if (S_ISDIR(mode) || S_ISGITLINK(mode)) {
133
strbuf_addch(&path, '/');
134
if (args->verbose)
135
fprintf(stderr, "%.*s\n", (int)path.len, path.buf);
136
- err = write_entry(args, sha1, path.buf, path.len, mode, NULL, 0);
136
+ err = write_entry(args, sha1, path.buf, path.len, mode);
137
if (err)
138
return err;
139
return (S_ISDIR(mode) ? READ_TREE_RECURSIVE : 0);
140
}
141
142
- buffer = sha1_file_to_archive(path_without_prefix, sha1, mode,
143
- &type, &size, convert ? args->commit : NULL);
144
- if (!buffer)
145
- return error("cannot read %s", sha1_to_hex(sha1));
142
if (args->verbose)
143
fprintf(stderr, "%.*s\n", (int)path.len, path.buf);
148
- err = write_entry(args, sha1, path.buf, path.len, mode, buffer, size);
149
- free(buffer);
150
- return err;
144
+ return write_entry(args, sha1, path.buf, path.len, mode);
145
}
146
147
int write_archive_entries(struct archiver_args *args,
@@ -167,7 +161,7 @@ int write_archive_entries(struct archiver_args *args,
161
if (args->verbose)
162
fprintf(stderr, "%.*s\n", (int)len, args->base);
163
err = write_entry(args, args->tree->object.sha1, args->base,
170
- len, 040777, NULL, 0);
164
+ len, 040777);
165
if (err)
166
return err;
167
}
archive.h
+9
-1
@@ -11,6 +11,7 @@ struct archiver_args {
11
const char **pathspec;
12
unsigned int verbose : 1;
13
unsigned int worktree_attributes : 1;
14
+ unsigned int convert : 1;
15
int compression_level;
16
};
17
@@ -27,11 +28,18 @@ extern void register_archiver(struct archiver *);
28
extern void init_tar_archiver(void);
29
extern void init_zip_archiver(void);
30
30
-typedef int (*write_archive_entry_fn_t)(struct archiver_args *args, const unsigned char *sha1, const char *path, size_t pathlen, unsigned int mode, void *buffer, unsigned long size);
31
+typedef int (*write_archive_entry_fn_t)(struct archiver_args *args,
32
+ const unsigned char *sha1,
33
+ const char *path, size_t pathlen,
34
+ unsigned int mode);
35
36
extern int write_archive_entries(struct archiver_args *args, write_archive_entry_fn_t write_entry);
37
extern int write_archive(int argc, const char **argv, const char *prefix, int setup_prefix, const char *name_hint, int remote);
38
39
const char *archive_format_from_filename(const char *filename);
40
+extern void *sha1_file_to_archive(const struct archiver_args *args,
41
+ const char *path, const unsigned char *sha1,
42
+ unsigned int mode, enum object_type *type,
43
+ unsigned long *sizep);
44
45
#endif /* ARCHIVE_H */