Skip to content

Commit 0f4b377

Browse files
dmpotgitster
authored andcommitted
git-archive: infer output format from filename when unspecified
A command line $ git archive -o my-v2.0.zip v2.0 almost certainly wants the output in zip format, even though it does not specify any --format option. When --format is not given, but output filename is, try to infer what format is requested from the filename extension. Currently this code only knows about '.zip'. When the format is unspecified and the filename does not tell us, the output will be in 'tar' format as before. Of course, an explicit --format will not trigger this guesswork. Signed-off-by: Dmitry Potapov <[email protected]> Signed-off-by: Junio C Hamano <[email protected]>
1 parent 518ef8f commit 0f4b377

File tree

2 files changed

+41
-3
lines changed

2 files changed

+41
-3
lines changed

Documentation/git-archive.txt

Lines changed: 11 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -34,8 +34,11 @@ OPTIONS
3434
-------
3535

3636
--format=<fmt>::
37-
Format of the resulting archive: 'tar' or 'zip'. The default
38-
is 'tar'.
37+
Format of the resulting archive: 'tar' or 'zip'. If this option
38+
is not given, and the output file is specified, the format is
39+
inferred from the filename if possible (e.g. writing to "foo.zip"
40+
makes the output to be in the zip format). Otherwise the output
41+
format is `tar`.
3942

4043
-l::
4144
--list::
@@ -130,6 +133,12 @@ git archive --format=zip --prefix=git-docs/ HEAD:Documentation/ > git-1.4.0-docs
130133
Put everything in the current head's Documentation/ directory
131134
into 'git-1.4.0-docs.zip', with the prefix 'git-docs/'.
132135

136+
git archive -o latest.zip HEAD::
137+
138+
Create a Zip archive that contains the contents of the latest
139+
commit on the current branch. Note that the output format is
140+
inferred by the extension of the output file.
141+
133142

134143
SEE ALSO
135144
--------

builtin-archive.c

Lines changed: 30 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -60,6 +60,17 @@ static int run_remote_archiver(int argc, const char **argv,
6060
return !!rv;
6161
}
6262

63+
static const char *format_from_name(const char *filename)
64+
{
65+
const char *ext = strrchr(filename, '.');
66+
if (!ext)
67+
return NULL;
68+
ext++;
69+
if (!strcasecmp(ext, "zip"))
70+
return "zip";
71+
return NULL;
72+
}
73+
6374
#define PARSE_OPT_KEEP_ALL ( PARSE_OPT_KEEP_DASHDASH | \
6475
PARSE_OPT_KEEP_ARGV0 | \
6576
PARSE_OPT_KEEP_UNKNOWN | \
@@ -70,21 +81,39 @@ int cmd_archive(int argc, const char **argv, const char *prefix)
7081
const char *exec = "git-upload-archive";
7182
const char *output = NULL;
7283
const char *remote = NULL;
84+
const char *format = NULL;
7385
struct option local_opts[] = {
7486
OPT_STRING('o', "output", &output, "file",
7587
"write the archive to this file"),
7688
OPT_STRING(0, "remote", &remote, "repo",
7789
"retrieve the archive from remote repository <repo>"),
7890
OPT_STRING(0, "exec", &exec, "cmd",
7991
"path to the remote git-upload-archive command"),
92+
OPT_STRING(0, "format", &format, "fmt", "archive format"),
8093
OPT_END()
8194
};
95+
char fmt_opt[32];
8296

8397
argc = parse_options(argc, argv, prefix, local_opts, NULL,
8498
PARSE_OPT_KEEP_ALL);
8599

86-
if (output)
100+
if (output) {
87101
create_output_file(output);
102+
if (!format)
103+
format = format_from_name(output);
104+
}
105+
106+
if (format) {
107+
sprintf(fmt_opt, "--format=%s", format);
108+
/*
109+
* This is safe because either --format and/or --output must
110+
* have been given on the original command line if we get to
111+
* this point, and parse_options() must have eaten at least
112+
* one argument, i.e. we have enough room to append to argv[].
113+
*/
114+
argv[argc++] = fmt_opt;
115+
argv[argc] = NULL;
116+
}
88117

89118
if (remote)
90119
return run_remote_archiver(argc, argv, remote, exec);

0 commit comments

Comments
 (0)