archive: refactor list of archive formats
authorJeff King <peff@peff.net>
Wed, 22 Jun 2011 01:23:33 +0000 (21:23 -0400)
committerJunio C Hamano <gitster@pobox.com>
Wed, 22 Jun 2011 18:12:35 +0000 (11:12 -0700)
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>
archive-tar.c
archive-zip.c
archive.c
archive.h

index 1ab1a2caf53b01b5704cb9f61e9584d2ca3e553d..930375bf2101be2b25472afaddc192f3c8cf32f9 100644 (file)
@@ -234,12 +234,10 @@ static int git_tar_config(const char *var, const char *value, void *cb)
        return 0;
 }
 
-int write_tar_archive(struct archiver_args *args)
+static int write_tar_archive(struct archiver_args *args)
 {
        int err = 0;
 
-       git_config(git_tar_config, NULL);
-
        if (args->commit_sha1)
                err = write_global_extended_header(args);
        if (!err)
@@ -248,3 +246,15 @@ int write_tar_archive(struct archiver_args *args)
                write_trailer();
        return err;
 }
+
+static struct archiver tar_archiver = {
+       "tar",
+       write_tar_archive,
+       0
+};
+
+void init_tar_archiver(void)
+{
+       register_archiver(&tar_archiver);
+       git_config(git_tar_config, NULL);
+}
index cf285044e3576d0127c3215cb1253443d67517dc..a776d8359c98f6f67229c3f1f015b7c2f3ac1c60 100644 (file)
@@ -261,7 +261,7 @@ static void dos_time(time_t *time, int *dos_date, int *dos_time)
        *dos_time = t->tm_sec / 2 + t->tm_min * 32 + t->tm_hour * 2048;
 }
 
-int write_zip_archive(struct archiver_args *args)
+static int write_zip_archive(struct archiver_args *args)
 {
        int err;
 
@@ -278,3 +278,14 @@ int write_zip_archive(struct archiver_args *args)
 
        return err;
 }
+
+static struct archiver zip_archiver = {
+       "zip",
+       write_zip_archive,
+       ARCHIVER_WANT_COMPRESSION_LEVELS
+};
+
+void init_zip_archiver(void)
+{
+       register_archiver(&zip_archiver);
+}
index 2616676fc784275aac46d208ff279d476ca60c04..f0b4e85513eaab597225a23e2d132389224ea4c6 100644 (file)
--- a/archive.c
+++ b/archive.c
@@ -14,16 +14,15 @@ static char const * const archive_usage[] = {
        NULL
 };
 
-#define USES_ZLIB_COMPRESSION 1
-
-static const struct archiver {
-       const char *name;
-       write_archive_fn_t write_archive;
-       unsigned int flags;
-} archivers[] = {
-       { "tar", write_tar_archive },
-       { "zip", write_zip_archive, USES_ZLIB_COMPRESSION },
-};
+static const struct archiver **archivers;
+static int nr_archivers;
+static int alloc_archivers;
+
+void register_archiver(struct archiver *ar)
+{
+       ALLOC_GROW(archivers, nr_archivers + 1, alloc_archivers);
+       archivers[nr_archivers++] = ar;
+}
 
 static void format_subst(const struct commit *commit,
                          const char *src, size_t len,
@@ -208,9 +207,9 @@ static const struct archiver *lookup_archiver(const char *name)
        if (!name)
                return NULL;
 
-       for (i = 0; i < ARRAY_SIZE(archivers); i++) {
-               if (!strcmp(name, archivers[i].name))
-                       return &archivers[i];
+       for (i = 0; i < nr_archivers; i++) {
+               if (!strcmp(name, archivers[i]->name))
+                       return archivers[i];
        }
        return NULL;
 }
@@ -355,8 +354,8 @@ static int parse_archive_args(int argc, const char **argv,
                base = "";
 
        if (list) {
-               for (i = 0; i < ARRAY_SIZE(archivers); i++)
-                       printf("%s\n", archivers[i].name);
+               for (i = 0; i < nr_archivers; i++)
+                       printf("%s\n", archivers[i]->name);
                exit(0);
        }
 
@@ -369,7 +368,7 @@ static int parse_archive_args(int argc, const char **argv,
 
        args->compression_level = Z_DEFAULT_COMPRESSION;
        if (compression_level != -1) {
-               if ((*ar)->flags & USES_ZLIB_COMPRESSION)
+               if ((*ar)->flags & ARCHIVER_WANT_COMPRESSION_LEVELS)
                        args->compression_level = compression_level;
                else {
                        die("Argument not supported for format '%s': -%d",
@@ -395,6 +394,8 @@ int write_archive(int argc, const char **argv, const char *prefix,
                prefix = setup_git_directory_gently(&nongit);
 
        git_config(git_default_config, NULL);
+       init_tar_archiver();
+       init_zip_archiver();
 
        argc = parse_archive_args(argc, argv, &ar, &args);
        if (nongit) {
index 038ac353d40567029403e3e7a2933af73a130720..f39cede0c6de829953d0ed3806b564b609ae2566 100644 (file)
--- a/archive.h
+++ b/archive.h
@@ -14,15 +14,18 @@ struct archiver_args {
        int compression_level;
 };
 
-typedef int (*write_archive_fn_t)(struct archiver_args *);
+#define ARCHIVER_WANT_COMPRESSION_LEVELS 1
+struct archiver {
+       const char *name;
+       int (*write_archive)(struct archiver_args *);
+       unsigned flags;
+};
+extern void register_archiver(struct archiver *);
 
-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);
+extern void init_tar_archiver(void);
+extern void init_zip_archiver(void);
 
-/*
- * Archive-format specific backends.
- */
-extern int write_tar_archive(struct archiver_args *);
-extern int write_zip_archive(struct archiver_args *);
+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);
 
 extern int write_archive_entries(struct archiver_args *args, write_archive_entry_fn_t write_entry);
 extern int write_archive(int argc, const char **argv, const char *prefix, int setup_prefix);