archive: refactor list of archive formats

Most of the tar and zip code was nicely split out into two abstracted files which knew only about their specific formats. The entry point to this code was a single "write archive" function. However, as these basic formats grow more complex (e.g., by handling multiple file extensions and format names), a static list of the entry point functions won't be enough. Instead, let's provide a way for the tar and zip code to tell the main archive code what they support by registering archiver names and functions. Signed-off-by: Jeff King <peff@peff.net> Signed-off-by: Junio C Hamano <gitster@pobox.com>

Jeff King committed Jun 21, 2011 at 21:23 UTC 13e0f88d4aba326da9217c225d6ab5e642eb611d
4 files changed +52 -27
archive-tar.c
+13 -3
@@ -234,12 +234,10 @@ static int git_tar_config(const char *var, const char *value, void *cb)
234 return 0;
235 }
236
237 -int write_tar_archive(struct archiver_args *args)
237 +static int write_tar_archive(struct archiver_args *args)
238 {
239 int err = 0;
240
241 - git_config(git_tar_config, NULL);
242 -
241 if (args->commit_sha1)
242 err = write_global_extended_header(args);
243 if (!err)
@@ -248,3 +246,15 @@ int write_tar_archive(struct archiver_args *args)
246 write_trailer();
247 return err;
248 }
249 +
250 +static struct archiver tar_archiver = {
251 + "tar",
252 + write_tar_archive,
253 + 0
254 +};
255 +
256 +void init_tar_archiver(void)
257 +{
258 + register_archiver(&tar_archiver);
259 + git_config(git_tar_config, NULL);
260 +}
archive-zip.c
+12 -1
@@ -261,7 +261,7 @@ static void dos_time(time_t *time, int *dos_date, int *dos_time)
261 *dos_time = t->tm_sec / 2 + t->tm_min * 32 + t->tm_hour * 2048;
262 }
263
264 -int write_zip_archive(struct archiver_args *args)
264 +static int write_zip_archive(struct archiver_args *args)
265 {
266 int err;
267
@@ -278,3 +278,14 @@ int write_zip_archive(struct archiver_args *args)
278
279 return err;
280 }
281 +
282 +static struct archiver zip_archiver = {
283 + "zip",
284 + write_zip_archive,
285 + ARCHIVER_WANT_COMPRESSION_LEVELS
286 +};
287 +
288 +void init_zip_archiver(void)
289 +{
290 + register_archiver(&zip_archiver);
291 +}
archive.c
+17 -16
@@ -14,16 +14,15 @@ static char const * const archive_usage[] = {
14 NULL
15 };
16
17 -#define USES_ZLIB_COMPRESSION 1
18 -
19 -static const struct archiver {
20 - const char *name;
21 - write_archive_fn_t write_archive;
22 - unsigned int flags;
23 -} archivers[] = {
24 - { "tar", write_tar_archive },
25 - { "zip", write_zip_archive, USES_ZLIB_COMPRESSION },
26 -};
17 +static const struct archiver **archivers;
18 +static int nr_archivers;
19 +static int alloc_archivers;
20 +
21 +void register_archiver(struct archiver *ar)
22 +{
23 + ALLOC_GROW(archivers, nr_archivers + 1, alloc_archivers);
24 + archivers[nr_archivers++] = ar;
25 +}
26
27 static void format_subst(const struct commit *commit,
28 const char *src, size_t len,
@@ -208,9 +207,9 @@ static const struct archiver *lookup_archiver(const char *name)
207 if (!name)
208 return NULL;
209
211 - for (i = 0; i < ARRAY_SIZE(archivers); i++) {
212 - if (!strcmp(name, archivers[i].name))
213 - return &archivers[i];
210 + for (i = 0; i < nr_archivers; i++) {
211 + if (!strcmp(name, archivers[i]->name))
212 + return archivers[i];
213 }
214 return NULL;
215 }
@@ -355,8 +354,8 @@ static int parse_archive_args(int argc, const char **argv,
354 base = "";
355
356 if (list) {
358 - for (i = 0; i < ARRAY_SIZE(archivers); i++)
359 - printf("%s\n", archivers[i].name);
357 + for (i = 0; i < nr_archivers; i++)
358 + printf("%s\n", archivers[i]->name);
359 exit(0);
360 }
361
@@ -369,7 +368,7 @@ static int parse_archive_args(int argc, const char **argv,
368
369 args->compression_level = Z_DEFAULT_COMPRESSION;
370 if (compression_level != -1) {
372 - if ((*ar)->flags & USES_ZLIB_COMPRESSION)
371 + if ((*ar)->flags & ARCHIVER_WANT_COMPRESSION_LEVELS)
372 args->compression_level = compression_level;
373 else {
374 die("Argument not supported for format '%s': -%d",
@@ -395,6 +394,8 @@ int write_archive(int argc, const char **argv, const char *prefix,
394 prefix = setup_git_directory_gently(&nongit);
395
396 git_config(git_default_config, NULL);
397 + init_tar_archiver();
398 + init_zip_archiver();
399
400 argc = parse_archive_args(argc, argv, &ar, &args);
401 if (nongit) {
archive.h
+10 -7
@@ -14,15 +14,18 @@ struct archiver_args {
14 int compression_level;
15 };
16
17 -typedef int (*write_archive_fn_t)(struct archiver_args *);
17 +#define ARCHIVER_WANT_COMPRESSION_LEVELS 1
18 +struct archiver {
19 + const char *name;
20 + int (*write_archive)(struct archiver_args *);
21 + unsigned flags;
22 +};
23 +extern void register_archiver(struct archiver *);
24
19 -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);
25 +extern void init_tar_archiver(void);
26 +extern void init_zip_archiver(void);
27
21 -/*
22 - * Archive-format specific backends.
23 - */
24 -extern int write_tar_archive(struct archiver_args *);
25 -extern int write_zip_archive(struct archiver_args *);
28 +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);
29
30 extern int write_archive_entries(struct archiver_args *args, write_archive_entry_fn_t write_entry);
31 extern int write_archive(int argc, const char **argv, const char *prefix, int setup_prefix);