Skip to content

Commit aae2ae4

Browse files
peffgitster
authored andcommitted
tmp-objdir: quote paths we add to alternates
Commit 722ff7f (receive-pack: quarantine objects until pre-receive accepts, 2016-10-03) regressed pushes to repositories with colon (or semi-colon in Windows in them) because it adds the repository's main object directory to GIT_ALTERNATE_OBJECT_DIRECTORIES. The receiver interprets the colon as a delimiter, not as part of the path, and index-pack is unable to find objects which it needs to resolve deltas. The previous commit introduced a quoting mechanism for the alternates list; let's use it here to cover this case. We'll avoid quoting when we can, though. This alternate setup is also used when calling hooks, so it's possible that the user may call older git implementations which don't understand the quoting mechanism. By quoting only when necessary, this setup will continue to work unless the user _also_ has a repository whose path contains the delimiter. Signed-off-by: Jeff King <[email protected]> Signed-off-by: Junio C Hamano <[email protected]>
1 parent cf3c635 commit aae2ae4

File tree

2 files changed

+36
-1
lines changed

2 files changed

+36
-1
lines changed

t/t5547-push-quarantine.sh

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -33,4 +33,23 @@ test_expect_success 'rejected objects are removed' '
3333
test_cmp expect actual
3434
'
3535

36+
# MINGW does not allow colons in pathnames in the first place
37+
test_expect_success !MINGW 'push to repo path with colon' '
38+
# The interesting failure case here is when the
39+
# receiving end cannot access its original object directory,
40+
# so make it likely for us to generate a delta by having
41+
# a non-trivial file with multiple versions.
42+
43+
test-genrandom foo 4096 >file.bin &&
44+
git add file.bin &&
45+
git commit -m bin &&
46+
git clone --bare . xxx:yyy.git &&
47+
48+
echo change >>file.bin &&
49+
git commit -am change &&
50+
# Note that we have to use the full path here, or it gets confused
51+
# with the ssh host:path syntax.
52+
git push "$PWD/xxx:yyy.git" HEAD
53+
'
54+
3655
test_done

tmp-objdir.c

Lines changed: 17 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@
55
#include "string-list.h"
66
#include "strbuf.h"
77
#include "argv-array.h"
8+
#include "quote.h"
89

910
struct tmp_objdir {
1011
struct strbuf path;
@@ -79,12 +80,27 @@ static void remove_tmp_objdir_on_signal(int signo)
7980
*/
8081
static void env_append(struct argv_array *env, const char *key, const char *val)
8182
{
82-
const char *old = getenv(key);
83+
struct strbuf quoted = STRBUF_INIT;
84+
const char *old;
8385

86+
/*
87+
* Avoid quoting if it's not necessary, for maximum compatibility
88+
* with older parsers which don't understand the quoting.
89+
*/
90+
if (*val == '"' || strchr(val, PATH_SEP)) {
91+
strbuf_addch(&quoted, '"');
92+
quote_c_style(val, &quoted, NULL, 1);
93+
strbuf_addch(&quoted, '"');
94+
val = quoted.buf;
95+
}
96+
97+
old = getenv(key);
8498
if (!old)
8599
argv_array_pushf(env, "%s=%s", key, val);
86100
else
87101
argv_array_pushf(env, "%s=%s%c%s", key, old, PATH_SEP, val);
102+
103+
strbuf_release(&quoted);
88104
}
89105

90106
static void env_replace(struct argv_array *env, const char *key, const char *val)

0 commit comments

Comments
 (0)