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