@@ -140,6 +140,22 @@ static int update_working_directory(struct pattern_list *pl)
return result;
}
+static char *escaped_pattern(char *pattern)
+{
+ char *p = pattern;
+ struct strbuf final = STRBUF_INIT;
+
+ while (*p) {
+ if (*p == '*' || *p == '\\')
+ strbuf_addch(&final, '\\');
+
+ strbuf_addch(&final, *p);
+ p++;
+ }
+
+ return strbuf_detach(&final, NULL);
+}
+
static void write_cone_to_file(FILE *fp, struct pattern_list *pl)
{
int i;
@@ -164,10 +180,11 @@ static void write_cone_to_file(FILE *fp, struct pattern_list *pl)
fprintf(fp, "/*\n!/*/\n");
for (i = 0; i < sl.nr; i++) {
- char *pattern = sl.items[i].string;
+ char *pattern = escaped_pattern(sl.items[i].string);
if (strlen(pattern))
fprintf(fp, "%s/\n!%s/*/\n", pattern, pattern);
+ free(pattern);
}
string_list_clear(&sl, 0);
@@ -185,8 +202,9 @@ static void write_cone_to_file(FILE *fp, struct pattern_list *pl)
string_list_remove_duplicates(&sl, 0);
for (i = 0; i < sl.nr; i++) {
- char *pattern = sl.items[i].string;
+ char *pattern = escaped_pattern(sl.items[i].string);
fprintf(fp, "%s/\n", pattern);
+ free(pattern);
}
}
@@ -337,7 +355,9 @@ static void insert_recursive_pattern(struct pattern_list *pl, struct strbuf *pat
{
struct pattern_entry *e = xmalloc(sizeof(*e));
e->patternlen = path->len;
- e->pattern = strbuf_detach(path, NULL);
+ e->pattern = dup_and_filter_pattern(path->buf);
+ strbuf_release(path);
+
hashmap_entry_init(&e->ent,
ignore_case ?
strihash(e->pattern) :
@@ -369,6 +389,7 @@ static void insert_recursive_pattern(struct pattern_list *pl, struct strbuf *pat
static void strbuf_to_cone_pattern(struct strbuf *line, struct pattern_list *pl)
{
+ int i;
strbuf_trim(line);
strbuf_trim_trailing_dir_sep(line);
@@ -376,6 +397,27 @@ static void strbuf_to_cone_pattern(struct strbuf *line, struct pattern_list *pl)
if (!line->len)
return;
+ for (i = 0; i < line->len; i++) {
+ if (line->buf[i] == '*') {
+ strbuf_insert(line, i, "\\", 1);
+ i++;
+ }
+
+ if (line->buf[i] == '\\') {
+ if (i < line->len - 1 && line->buf[i + 1] == '\\')
+ i++;
+ else
+ strbuf_insert(line, i, "\\", 1);
+
+ i++;
+ }
+ }
+
+ if (line->buf[0] == '"' && line->buf[line->len - 1] == '"') {
+ strbuf_remove(line, 0, 1);
+ strbuf_remove(line, line->len - 1, 1);
+ }
+
if (line->buf[0] != '/')
strbuf_insert(line, 0, "/", 1);
@@ -309,6 +309,9 @@ check_read_tree_errors () {
REPO=$1
FILES=$2
ERRORS=$3
+ git -C $REPO -c core.sparseCheckoutCone=false read-tree -mu HEAD 2>err &&
+ test_must_be_empty err &&
+ check_files $REPO "$FILES" &&
git -C $REPO read-tree -mu HEAD 2>err &&
if test -z "$ERRORS"
then
@@ -379,14 +382,28 @@ test_expect_success BSLASHPSPEC 'pattern-checks: escaped "*"' '
git -C escaped reset --hard $COMMIT &&
check_files escaped "a deep folder1 folder2 zbad\\dir zdoes*exist" &&
git -C escaped sparse-checkout init --cone &&
- cat >escaped/.git/info/sparse-checkout <<-\EOF &&
+ git -C escaped sparse-checkout set zbad\\dir zdoes\*not\*exist zdoes\*exist &&
+ cat >expect <<-\EOF &&
/*
!/*/
/zbad\\dir/
+ /zdoes\*exist/
/zdoes\*not\*exist/
+ EOF
+ test_cmp expect escaped/.git/info/sparse-checkout &&
+ check_read_tree_errors escaped "a zbad\\dir zdoes*exist" &&
+ git -C escaped ls-tree -d --name-only HEAD | git -C escaped sparse-checkout set --stdin &&
+ cat >expect <<-\EOF &&
+ /*
+ !/*/
+ /deep/
+ /folder1/
+ /folder2/
+ /zbad\\dir/
/zdoes\*exist/
EOF
- check_read_tree_errors escaped "a zbad\\dir zdoes*exist"
+ test_cmp expect escaped/.git/info/sparse-checkout &&
+ check_files escaped "a deep folder1 folder2 zbad\\dir zdoes*exist"
'
test_done