@matheusbsbs / matheus-bagliano / commits / 0f4b377c20
Fork 0

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 <dpotapov@gmail.com> Signed-off-by: Junio C Hamano <gitster@pobox.com>

Dmitry Potapov committed Sep 14, 2009 at 00:17 UTC 0f4b377c20fb7d93f8bfeec39efb2b9392d6aebc
2 files changed +41 -3
Documentation/git-archive.txt
+11 -2
@@ -34,8 +34,11 @@ OPTIONS
34 -------
35
36 --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`.
42
43 -l::
44 --list::
@@ -130,6 +133,12 @@ git archive --format=zip --prefix=git-docs/ HEAD:Documentation/ > git-1.4.0-docs
133 Put everything in the current head's Documentation/ directory
134 into 'git-1.4.0-docs.zip', with the prefix 'git-docs/'.
135
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 +
142
143 SEE ALSO
144 --------
builtin-archive.c
+30 -1
@@ -60,6 +60,17 @@ static int run_remote_archiver(int argc, const char **argv,
60 return !!rv;
61 }
62
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 +
74 #define PARSE_OPT_KEEP_ALL ( PARSE_OPT_KEEP_DASHDASH | \
75 PARSE_OPT_KEEP_ARGV0 | \
76 PARSE_OPT_KEEP_UNKNOWN | \
@@ -70,6 +81,7 @@ int cmd_archive(int argc, const char **argv, const char *prefix)
81 const char *exec = "git-upload-archive";
82 const char *output = NULL;
83 const char *remote = NULL;
84 + const char *format = NULL;
85 struct option local_opts[] = {
86 OPT_STRING('o', "output", &output, "file",
87 "write the archive to this file"),
@@ -77,14 +89,31 @@ int cmd_archive(int argc, const char **argv, const char *prefix)
89 "retrieve the archive from remote repository <repo>"),
90 OPT_STRING(0, "exec", &exec, "cmd",
91 "path to the remote git-upload-archive command"),
92 + OPT_STRING(0, "format", &format, "fmt", "archive format"),
93 OPT_END()
94 };
95 + char fmt_opt[32];
96
97 argc = parse_options(argc, argv, prefix, local_opts, NULL,
98 PARSE_OPT_KEEP_ALL);
99
86 - if (output)
100 + if (output) {
101 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 + }
117
118 if (remote)
119 return run_remote_archiver(argc, argv, remote, exec);