Skip to content

Commit 08716b3

Browse files
peffgitster
authored andcommitted
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 <[email protected]> Signed-off-by: Junio C Hamano <[email protected]>
1 parent 56baa61 commit 08716b3

File tree

1 file changed

+19
-6
lines changed

1 file changed

+19
-6
lines changed

archive.c

Lines changed: 19 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -419,13 +419,26 @@ int write_archive(int argc, const char **argv, const char *prefix,
419419
return ar->write_archive(ar, &args);
420420
}
421421

422+
static int match_extension(const char *filename, const char *ext)
423+
{
424+
int prefixlen = strlen(filename) - strlen(ext);
425+
426+
/*
427+
* We need 1 character for the '.', and 1 character to ensure that the
428+
* prefix is non-empty (k.e., we don't match .tar.gz with no actual
429+
* filename).
430+
*/
431+
if (prefixlen < 2 || filename[prefixlen-1] != '.')
432+
return 0;
433+
return !strcmp(filename + prefixlen, ext);
434+
}
435+
422436
const char *archive_format_from_filename(const char *filename)
423437
{
424-
const char *ext = strrchr(filename, '.');
425-
if (!ext)
426-
return NULL;
427-
ext++;
428-
if (!strcasecmp(ext, "zip"))
429-
return "zip";
438+
int i;
439+
440+
for (i = 0; i < nr_archivers; i++)
441+
if (match_extension(filename, archivers[i]->name))
442+
return archivers[i]->name;
430443
return NULL;
431444
}

0 commit comments

Comments
 (0)