mirror of
https://github.com/git/git
synced 2024-08-25 02:35:46 +00:00
Merge branch 'jk/quote-env-path-list-component'
A recent update to receive-pack to make it easier to drop garbage objects made it clear that GIT_ALTERNATE_OBJECT_DIRECTORIES cannot have a pathname with a colon in it (no surprise!), and this in turn made it impossible to push into a repository at such a path. This has been fixed by introducing a quoting mechanism used when appending such a path to the colon-separated list. * jk/quote-env-path-list-component: t5615-alternate-env: double-quotes in file names do not work on Windows t5547-push-quarantine: run the path separator test on Windows, too tmp-objdir: quote paths we add to alternates alternates: accept double-quoted paths
This commit is contained in:
commit
fe05033407
|
@ -871,6 +871,12 @@ Git so take care if using a foreign front-end.
|
|||
specifies a ":" separated (on Windows ";" separated) list
|
||||
of Git object directories which can be used to search for Git
|
||||
objects. New objects will not be written to these directories.
|
||||
+
|
||||
Entries that begin with `"` (double-quote) will be interpreted
|
||||
as C-style quoted paths, removing leading and trailing
|
||||
double-quotes and respecting backslash escapes. E.g., the value
|
||||
`"path-with-\"-and-:-in-it":vanilla-path` has two paths:
|
||||
`path-with-"-and-:-in-it` and `vanilla-path`.
|
||||
|
||||
`GIT_DIR`::
|
||||
If the `GIT_DIR` environment variable is set then it
|
||||
|
|
47
sha1_file.c
47
sha1_file.c
|
@ -26,6 +26,7 @@
|
|||
#include "mru.h"
|
||||
#include "list.h"
|
||||
#include "mergesort.h"
|
||||
#include "quote.h"
|
||||
|
||||
#ifndef O_NOATIME
|
||||
#if defined(__linux__) && (defined(__i386__) || defined(__PPC__))
|
||||
|
@ -329,13 +330,40 @@ static int link_alt_odb_entry(const char *entry, const char *relative_base,
|
|||
return 0;
|
||||
}
|
||||
|
||||
static const char *parse_alt_odb_entry(const char *string,
|
||||
int sep,
|
||||
struct strbuf *out)
|
||||
{
|
||||
const char *end;
|
||||
|
||||
strbuf_reset(out);
|
||||
|
||||
if (*string == '#') {
|
||||
/* comment; consume up to next separator */
|
||||
end = strchrnul(string, sep);
|
||||
} else if (*string == '"' && !unquote_c_style(out, string, &end)) {
|
||||
/*
|
||||
* quoted path; unquote_c_style has copied the
|
||||
* data for us and set "end". Broken quoting (e.g.,
|
||||
* an entry that doesn't end with a quote) falls
|
||||
* back to the unquoted case below.
|
||||
*/
|
||||
} else {
|
||||
/* normal, unquoted path */
|
||||
end = strchrnul(string, sep);
|
||||
strbuf_add(out, string, end - string);
|
||||
}
|
||||
|
||||
if (*end)
|
||||
end++;
|
||||
return end;
|
||||
}
|
||||
|
||||
static void link_alt_odb_entries(const char *alt, int len, int sep,
|
||||
const char *relative_base, int depth)
|
||||
{
|
||||
struct string_list entries = STRING_LIST_INIT_NODUP;
|
||||
char *alt_copy;
|
||||
int i;
|
||||
struct strbuf objdirbuf = STRBUF_INIT;
|
||||
struct strbuf entry = STRBUF_INIT;
|
||||
|
||||
if (depth > 5) {
|
||||
error("%s: ignoring alternate object stores, nesting too deep.",
|
||||
|
@ -348,16 +376,13 @@ static void link_alt_odb_entries(const char *alt, int len, int sep,
|
|||
die("unable to normalize object directory: %s",
|
||||
objdirbuf.buf);
|
||||
|
||||
alt_copy = xmemdupz(alt, len);
|
||||
string_list_split_in_place(&entries, alt_copy, sep, -1);
|
||||
for (i = 0; i < entries.nr; i++) {
|
||||
const char *entry = entries.items[i].string;
|
||||
if (entry[0] == '\0' || entry[0] == '#')
|
||||
while (*alt) {
|
||||
alt = parse_alt_odb_entry(alt, sep, &entry);
|
||||
if (!entry.len)
|
||||
continue;
|
||||
link_alt_odb_entry(entry, relative_base, depth, objdirbuf.buf);
|
||||
link_alt_odb_entry(entry.buf, relative_base, depth, objdirbuf.buf);
|
||||
}
|
||||
string_list_clear(&entries, 0);
|
||||
free(alt_copy);
|
||||
strbuf_release(&entry);
|
||||
strbuf_release(&objdirbuf);
|
||||
}
|
||||
|
||||
|
|
|
@ -33,4 +33,29 @@ test_expect_success 'rejected objects are removed' '
|
|||
test_cmp expect actual
|
||||
'
|
||||
|
||||
test_expect_success 'push to repo path with path separator (colon)' '
|
||||
# The interesting failure case here is when the
|
||||
# receiving end cannot access its original object directory,
|
||||
# so make it likely for us to generate a delta by having
|
||||
# a non-trivial file with multiple versions.
|
||||
|
||||
test-genrandom foo 4096 >file.bin &&
|
||||
git add file.bin &&
|
||||
git commit -m bin &&
|
||||
|
||||
if test_have_prereq MINGW
|
||||
then
|
||||
pathsep=";"
|
||||
else
|
||||
pathsep=":"
|
||||
fi &&
|
||||
git clone --bare . "xxx${pathsep}yyy.git" &&
|
||||
|
||||
echo change >>file.bin &&
|
||||
git commit -am change &&
|
||||
# Note that we have to use the full path here, or it gets confused
|
||||
# with the ssh host:path syntax.
|
||||
git push "$(pwd)/xxx${pathsep}yyy.git" HEAD
|
||||
'
|
||||
|
||||
test_done
|
||||
|
|
|
@ -68,4 +68,22 @@ test_expect_success 'access alternate via relative path (subdir)' '
|
|||
EOF
|
||||
'
|
||||
|
||||
# set variables outside test to avoid quote insanity; the \057 is '/',
|
||||
# which doesn't need quoting, but just confirms that de-quoting
|
||||
# is working.
|
||||
quoted='"one.git\057objects"'
|
||||
unquoted='two.git/objects'
|
||||
test_expect_success 'mix of quoted and unquoted alternates' '
|
||||
check_obj "$quoted:$unquoted" <<-EOF
|
||||
$one blob
|
||||
$two blob
|
||||
'
|
||||
|
||||
test_expect_success !MINGW 'broken quoting falls back to interpreting raw' '
|
||||
mv one.git \"one.git &&
|
||||
check_obj \"one.git/objects <<-EOF
|
||||
$one blob
|
||||
EOF
|
||||
'
|
||||
|
||||
test_done
|
||||
|
|
18
tmp-objdir.c
18
tmp-objdir.c
|
@ -5,6 +5,7 @@
|
|||
#include "string-list.h"
|
||||
#include "strbuf.h"
|
||||
#include "argv-array.h"
|
||||
#include "quote.h"
|
||||
|
||||
struct tmp_objdir {
|
||||
struct strbuf path;
|
||||
|
@ -79,12 +80,27 @@ static void remove_tmp_objdir_on_signal(int signo)
|
|||
*/
|
||||
static void env_append(struct argv_array *env, const char *key, const char *val)
|
||||
{
|
||||
const char *old = getenv(key);
|
||||
struct strbuf quoted = STRBUF_INIT;
|
||||
const char *old;
|
||||
|
||||
/*
|
||||
* Avoid quoting if it's not necessary, for maximum compatibility
|
||||
* with older parsers which don't understand the quoting.
|
||||
*/
|
||||
if (*val == '"' || strchr(val, PATH_SEP)) {
|
||||
strbuf_addch("ed, '"');
|
||||
quote_c_style(val, "ed, NULL, 1);
|
||||
strbuf_addch("ed, '"');
|
||||
val = quoted.buf;
|
||||
}
|
||||
|
||||
old = getenv(key);
|
||||
if (!old)
|
||||
argv_array_pushf(env, "%s=%s", key, val);
|
||||
else
|
||||
argv_array_pushf(env, "%s=%s%c%s", key, old, PATH_SEP, val);
|
||||
|
||||
strbuf_release("ed);
|
||||
}
|
||||
|
||||
static void env_replace(struct argv_array *env, const char *key, const char *val)
|
||||
|
|
Loading…
Reference in a new issue