archive --add-virtual-file: allow paths containing colons
By allowing the path to be enclosed in double-quotes, we can avoid the limitation that paths cannot contain colons. Signed-off-by: Johannes Schindelin <johannes.schindelin@gmx.de> Signed-off-by: Junio C Hamano <gitster@pobox.com>
This commit is contained in:
parent
237a1d138c
commit
de1f68a968
@ -69,10 +69,16 @@ OPTIONS
|
|||||||
by concatenating the value of the last `--prefix` option (if any)
|
by concatenating the value of the last `--prefix` option (if any)
|
||||||
before this `--add-virtual-file` and `<path>`.
|
before this `--add-virtual-file` and `<path>`.
|
||||||
+
|
+
|
||||||
The `<path>` cannot contain any colon, the file mode is limited to
|
The `<path>` argument can start and end with a literal double-quote
|
||||||
a regular file, and the option may be subject to platform-dependent
|
character; the contained file name is interpreted as a C-style string,
|
||||||
command-line limits. For non-trivial cases, write an untracked file
|
i.e. the backslash is interpreted as escape character. The path must
|
||||||
and use `--add-file` instead.
|
be quoted if it contains a colon, to avoid the colon from being
|
||||||
|
misinterpreted as the separator between the path and the contents, or
|
||||||
|
if the path begins or ends with a double-quote character.
|
||||||
|
+
|
||||||
|
The file mode is limited to a regular file, and the option may be
|
||||||
|
subject to platform-dependent command-line limits. For non-trivial
|
||||||
|
cases, write an untracked file and use `--add-file` instead.
|
||||||
|
|
||||||
--worktree-attributes::
|
--worktree-attributes::
|
||||||
Look for attributes in .gitattributes files in the working tree
|
Look for attributes in .gitattributes files in the working tree
|
||||||
|
30
archive.c
30
archive.c
@ -9,6 +9,7 @@
|
|||||||
#include "parse-options.h"
|
#include "parse-options.h"
|
||||||
#include "unpack-trees.h"
|
#include "unpack-trees.h"
|
||||||
#include "dir.h"
|
#include "dir.h"
|
||||||
|
#include "quote.h"
|
||||||
|
|
||||||
static char const * const archive_usage[] = {
|
static char const * const archive_usage[] = {
|
||||||
N_("git archive [<options>] <tree-ish> [<path>...]"),
|
N_("git archive [<options>] <tree-ish> [<path>...]"),
|
||||||
@ -535,22 +536,31 @@ static int add_file_cb(const struct option *opt, const char *arg, int unset)
|
|||||||
die(_("Not a regular file: %s"), path);
|
die(_("Not a regular file: %s"), path);
|
||||||
info->content = NULL; /* read the file later */
|
info->content = NULL; /* read the file later */
|
||||||
} else if (!strcmp(opt->long_name, "add-virtual-file")) {
|
} else if (!strcmp(opt->long_name, "add-virtual-file")) {
|
||||||
const char *colon = strchr(arg, ':');
|
struct strbuf buf = STRBUF_INIT;
|
||||||
char *p;
|
const char *p = arg;
|
||||||
|
|
||||||
if (!colon)
|
if (*p != '"')
|
||||||
|
p = strchr(p, ':');
|
||||||
|
else if (unquote_c_style(&buf, p, &p) < 0)
|
||||||
|
die(_("unclosed quote: '%s'"), arg);
|
||||||
|
|
||||||
|
if (!p || *p != ':')
|
||||||
die(_("missing colon: '%s'"), arg);
|
die(_("missing colon: '%s'"), arg);
|
||||||
|
|
||||||
p = xstrndup(arg, colon - arg);
|
if (p == arg)
|
||||||
if (!args->prefix)
|
die(_("empty file name: '%s'"), arg);
|
||||||
path = p;
|
|
||||||
else {
|
path = buf.len ?
|
||||||
path = prefix_filename(args->prefix, p);
|
strbuf_detach(&buf, NULL) : xstrndup(arg, p - arg);
|
||||||
free(p);
|
|
||||||
|
if (args->prefix) {
|
||||||
|
char *save = path;
|
||||||
|
path = prefix_filename(args->prefix, path);
|
||||||
|
free(save);
|
||||||
}
|
}
|
||||||
memset(&info->stat, 0, sizeof(info->stat));
|
memset(&info->stat, 0, sizeof(info->stat));
|
||||||
info->stat.st_mode = S_IFREG | 0644;
|
info->stat.st_mode = S_IFREG | 0644;
|
||||||
info->content = xstrdup(colon + 1);
|
info->content = xstrdup(p + 1);
|
||||||
info->stat.st_size = strlen(info->content);
|
info->stat.st_size = strlen(info->content);
|
||||||
} else {
|
} else {
|
||||||
BUG("add_file_cb() called for %s", opt->long_name);
|
BUG("add_file_cb() called for %s", opt->long_name);
|
||||||
|
@ -207,13 +207,21 @@ check_zip with_untracked
|
|||||||
check_added with_untracked untracked untracked
|
check_added with_untracked untracked untracked
|
||||||
|
|
||||||
test_expect_success UNZIP 'git archive --format=zip --add-virtual-file' '
|
test_expect_success UNZIP 'git archive --format=zip --add-virtual-file' '
|
||||||
|
if test_have_prereq FUNNYNAMES
|
||||||
|
then
|
||||||
|
PATHNAME="pathname with : colon"
|
||||||
|
else
|
||||||
|
PATHNAME="pathname without colon"
|
||||||
|
fi &&
|
||||||
git archive --format=zip >with_file_with_content.zip \
|
git archive --format=zip >with_file_with_content.zip \
|
||||||
|
--add-virtual-file=\""$PATHNAME"\": \
|
||||||
--add-virtual-file=hello:world $EMPTY_TREE &&
|
--add-virtual-file=hello:world $EMPTY_TREE &&
|
||||||
test_when_finished "rm -rf tmp-unpack" &&
|
test_when_finished "rm -rf tmp-unpack" &&
|
||||||
mkdir tmp-unpack && (
|
mkdir tmp-unpack && (
|
||||||
cd tmp-unpack &&
|
cd tmp-unpack &&
|
||||||
"$GIT_UNZIP" ../with_file_with_content.zip &&
|
"$GIT_UNZIP" ../with_file_with_content.zip &&
|
||||||
test_path_is_file hello &&
|
test_path_is_file hello &&
|
||||||
|
test_path_is_file "$PATHNAME" &&
|
||||||
test world = $(cat hello)
|
test world = $(cat hello)
|
||||||
)
|
)
|
||||||
'
|
'
|
||||||
|
Loading…
Reference in New Issue
Block a user