Skip to content

Commit bd64de4

Browse files
derrickstoleegitster
authored andcommitted
sparse-checkout: unquote C-style strings over --stdin
If a user somehow creates a directory with an asterisk (*) or backslash (\), then the "git sparse-checkout set" command will struggle to provide the correct pattern in the sparse-checkout file. When not in cone mode, the provided pattern is written directly into the sparse-checkout file. However, in cone mode we expect a list of paths to directories and then we convert those into patterns. Even more specifically, the goal is to always allow the following from the root of a repo: git ls-tree --name-only -d HEAD | git sparse-checkout set --stdin The ls-tree command provides directory names with an unescaped asterisk. It also quotes the directories that contain an escaped backslash. We must remove these quotes, then keep the escaped backslashes. Use unquote_c_style() when parsing lines from stdin. Command-line arguments will be parsed as-is, assuming the user can do the correct level of escaping from their environment to match the exact directory names. Signed-off-by: Derrick Stolee <[email protected]> Signed-off-by: Junio C Hamano <[email protected]>
1 parent d585f0e commit bd64de4

File tree

2 files changed

+27
-2
lines changed

2 files changed

+27
-2
lines changed

builtin/sparse-checkout.c

Lines changed: 14 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -442,8 +442,21 @@ static int sparse_checkout_set(int argc, const char **argv, const char *prefix)
442442
pl.use_cone_patterns = 1;
443443

444444
if (set_opts.use_stdin) {
445-
while (!strbuf_getline(&line, stdin))
445+
struct strbuf unquoted = STRBUF_INIT;
446+
while (!strbuf_getline(&line, stdin)) {
447+
if (line.buf[0] == '"') {
448+
strbuf_reset(&unquoted);
449+
if (unquote_c_style(&unquoted, line.buf, NULL))
450+
die(_("unable to unquote C-style string '%s'"),
451+
line.buf);
452+
453+
strbuf_swap(&unquoted, &line);
454+
}
455+
446456
strbuf_to_cone_pattern(&line, &pl);
457+
}
458+
459+
strbuf_release(&unquoted);
447460
} else {
448461
for (i = 0; i < argc; i++) {
449462
strbuf_setlen(&line, 0);

t/t1091-sparse-checkout-builtin.sh

Lines changed: 13 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -405,7 +405,19 @@ test_expect_success BSLASHPSPEC 'pattern-checks: escaped "*"' '
405405
/zdoes\*not\*exist/
406406
EOF
407407
test_cmp expect escaped/.git/info/sparse-checkout &&
408-
check_read_tree_errors escaped "a zbad\\dir zdoes*exist"
408+
check_read_tree_errors escaped "a zbad\\dir zdoes*exist" &&
409+
git -C escaped ls-tree -d --name-only HEAD | git -C escaped sparse-checkout set --stdin &&
410+
cat >expect <<-\EOF &&
411+
/*
412+
!/*/
413+
/deep/
414+
/folder1/
415+
/folder2/
416+
/zbad\\dir/
417+
/zdoes\*exist/
418+
EOF
419+
test_cmp expect escaped/.git/info/sparse-checkout &&
420+
check_files escaped "a deep folder1 folder2 zbad\\dir zdoes*exist"
409421
'
410422

411423
test_done

0 commit comments

Comments
 (0)