aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJeff King <peff@peff.net>2011-06-21 21:25:25 -0400
committerJunio C Hamano <gitster@pobox.com>2011-06-22 11:12:35 -0700
commit08716b3c11f4899c1be046eca735761b30ca686d (patch)
treeb7a6ae9a16f127580fc14d140fb34c72897ad3ce
parent56baa61d011e9ed5199766fea89ea8c2c183f0ba (diff)
downloadgit-08716b3c11f4899c1be046eca735761b30ca686d.tar.gz
git-08716b3c11f4899c1be046eca735761b30ca686d.tar.xz
archive: refactor file extension format-guessing
Git-archive will guess a format from the output filename if no format is explicitly given. The current function just hardcodes "zip" to the zip format, and leaves everything else NULL (which will default to tar). Since we are about to add user-specified formats, we need to be more flexible. The new rule is "if a filename ends with a dot and the name of a format, it matches that format". For the existing "tar" and "zip" formats, this is identical to the current behavior. For new user-specified formats, this will do what the user expects if they name their formats appropriately. Because we will eventually start matching arbitrary user-specified extensions that may include dots, the strrchr search for the final dot is not sufficient. We need to do an actual suffix match with each extension. Signed-off-by: Jeff King <peff@peff.net> Signed-off-by: Junio C Hamano <gitster@pobox.com>
-rw-r--r--archive.c25
1 files changed, 19 insertions, 6 deletions
diff --git a/archive.c b/archive.c
index 7d0ca323c..41065a8e2 100644
--- a/archive.c
+++ b/archive.c
@@ -419,13 +419,26 @@ int write_archive(int argc, const char **argv, const char *prefix,
return ar->write_archive(ar, &args);
}
+static int match_extension(const char *filename, const char *ext)
+{
+ int prefixlen = strlen(filename) - strlen(ext);
+
+ /*
+ * We need 1 character for the '.', and 1 character to ensure that the
+ * prefix is non-empty (k.e., we don't match .tar.gz with no actual
+ * filename).
+ */
+ if (prefixlen < 2 || filename[prefixlen-1] != '.')
+ return 0;
+ return !strcmp(filename + prefixlen, ext);
+}
+
const char *archive_format_from_filename(const char *filename)
{
- const char *ext = strrchr(filename, '.');
- if (!ext)
- return NULL;
- ext++;
- if (!strcasecmp(ext, "zip"))
- return "zip";
+ int i;
+
+ for (i = 0; i < nr_archivers; i++)
+ if (match_extension(filename, archivers[i]->name))
+ return archivers[i]->name;
return NULL;
}