Signed-off-by: Nguyễn Thái Ngọc Duy <pclouds@xxxxxxxxx> --- archive.c | 4 +++- builtin/add.c | 8 +++++--- builtin/checkout.c | 4 +++- builtin/clean.c | 4 +++- builtin/commit.c | 6 ++++-- builtin/diff.c | 2 +- builtin/grep.c | 4 +++- builtin/ls-files.c | 3 ++- builtin/ls-tree.c | 4 +++- builtin/rerere.c | 4 +++- builtin/reset.c | 4 +++- builtin/rm.c | 4 +++- builtin/update-index.c | 4 +++- cache.h | 1 + dir.c | 6 +++--- revision.c | 5 +++-- setup.c | 7 ++++--- t/t6130-pathspec-noglob.sh | 18 ++++++++++++++++++ tree-diff.c | 2 +- tree-walk.c | 2 +- 20 files changed, 70 insertions(+), 26 deletions(-) diff --git a/archive.c b/archive.c index d9da58b..d3b6969 100644 --- a/archive.c +++ b/archive.c @@ -234,7 +234,9 @@ static void parse_pathspec_arg(const char **pathspec, * mark "used" pathspec. The magic mask cannot be lifted until * it does. */ - parse_pathspec(&ar_args->pathspec, PATHSPEC_FROMTOP, 0, "", pathspec); + parse_pathspec(&ar_args->pathspec, + PATHSPEC_FROMTOP | PATHSPEC_LITERAL, + 0, "", pathspec); if (ar_args->pathspec.nr) { pathspec = ar_args->pathspec._raw; while (*pathspec) { diff --git a/builtin/add.c b/builtin/add.c index a7840c8..d09a07a 100644 --- a/builtin/add.c +++ b/builtin/add.c @@ -202,7 +202,8 @@ int interactive_add(int argc, const char **argv, const char *prefix, int patch) * Do not enable fancy magic here. git-add--interactive may * not be able to handle it. */ - parse_pathspec(&pathspec, PATHSPEC_FROMTOP, + parse_pathspec(&pathspec, + PATHSPEC_FROMTOP | PATHSPEC_LITERAL, PATHSPEC_EMPTY_MATCH_ALL | PATHSPEC_SYMLINK_LEADING_PATH, prefix, argv); @@ -377,7 +378,8 @@ int cmd_add(int argc, const char **argv, const char *prefix) * Check the "pathspec '%s' did not match any files" block * below before enabling new magic. */ - parse_pathspec(&pathspec, PATHSPEC_FROMTOP, + parse_pathspec(&pathspec, + PATHSPEC_FROMTOP | PATHSPEC_LITERAL, PATHSPEC_SYMLINK_LEADING_PATH | PATHSPEC_STRIP_SUBMODULE_SLASH_EXPENSIVE, prefix, argv); @@ -414,7 +416,7 @@ int cmd_add(int argc, const char **argv, const char *prefix) /* * file_exists() assumes exact match */ - GUARD_PATHSPEC(&pathspec, PATHSPEC_FROMTOP); + GUARD_PATHSPEC(&pathspec, PATHSPEC_FROMTOP | PATHSPEC_LITERAL); for (i = 0; i < pathspec.nr; i++) { const char *path = pathspec.items[i].match; diff --git a/builtin/checkout.c b/builtin/checkout.c index 1b413e2..90f4a01 100644 --- a/builtin/checkout.c +++ b/builtin/checkout.c @@ -1112,7 +1112,9 @@ int cmd_checkout(int argc, const char **argv, const char *prefix) * cannot handle. Magic mask is pretty safe to be * lifted for new magic when opts.patch_mode == 0. */ - parse_pathspec(&opts.pathspec, PATHSPEC_FROMTOP, 0, prefix, argv); + parse_pathspec(&opts.pathspec, + PATHSPEC_FROMTOP | PATHSPEC_LITERAL, + 0, prefix, argv); if (!opts.pathspec.nr) die(_("invalid path specification")); diff --git a/builtin/clean.c b/builtin/clean.c index 1d8ff5f..b4ffa2b 100644 --- a/builtin/clean.c +++ b/builtin/clean.c @@ -100,7 +100,9 @@ int cmd_clean(int argc, const char **argv, const char *prefix) add_exclude(exclude_list.items[i].string, "", 0, &dir.exclude_list[EXC_CMDL]); - parse_pathspec(&pathspec, PATHSPEC_FROMTOP, 0, prefix, argv); + parse_pathspec(&pathspec, + PATHSPEC_FROMTOP | PATHSPEC_LITERAL, + 0, prefix, argv); fill_directory(&dir, &pathspec); diff --git a/builtin/commit.c b/builtin/commit.c index 2011f98..433fdb9 100644 --- a/builtin/commit.c +++ b/builtin/commit.c @@ -281,7 +281,8 @@ static char *prepare_index(int argc, const char **argv, const char *prefix, if (is_status) refresh_flags |= REFRESH_UNMERGED; - parse_pathspec(&pathspec, PATHSPEC_FROMTOP, + parse_pathspec(&pathspec, + PATHSPEC_FROMTOP | PATHSPEC_LITERAL, PATHSPEC_EMPTY_MATCH_ALL, prefix, argv); @@ -1203,7 +1204,8 @@ int cmd_status(int argc, const char **argv, const char *prefix) handle_untracked_files_arg(&s); if (show_ignored_in_status) s.show_ignored_files = 1; - parse_pathspec(&s.pathspec, PATHSPEC_FROMTOP, + parse_pathspec(&s.pathspec, + PATHSPEC_FROMTOP | PATHSPEC_LITERAL, PATHSPEC_EMPTY_MATCH_ALL, prefix, argv); diff --git a/builtin/diff.c b/builtin/diff.c index 6b4e3f9..b78435f 100644 --- a/builtin/diff.c +++ b/builtin/diff.c @@ -372,7 +372,7 @@ int cmd_diff(int argc, const char **argv, const char *prefix) } if (rev.prune_data.nr) { /* builtin_diff_b_f() */ - GUARD_PATHSPEC(&rev.prune_data, PATHSPEC_FROMTOP); + GUARD_PATHSPEC(&rev.prune_data, PATHSPEC_FROMTOP | PATHSPEC_LITERAL); if (!path) path = rev.prune_data.items[0].match; paths += rev.prune_data.nr; diff --git a/builtin/grep.c b/builtin/grep.c index f370bad..4d8e82c 100644 --- a/builtin/grep.c +++ b/builtin/grep.c @@ -856,7 +856,9 @@ int cmd_grep(int argc, const char **argv, const char *prefix) verify_filename(prefix, argv[j], j == i); } - parse_pathspec(&pathspec, PATHSPEC_FROMTOP, 0, prefix, argv + i); + parse_pathspec(&pathspec, + PATHSPEC_FROMTOP | PATHSPEC_LITERAL, + 0, prefix, argv + i); pathspec.max_depth = opt.max_depth; pathspec.recursive = 1; diff --git a/builtin/ls-files.c b/builtin/ls-files.c index e3ccf50..1cbd211 100644 --- a/builtin/ls-files.c +++ b/builtin/ls-files.c @@ -535,7 +535,8 @@ int cmd_ls_files(int argc, const char **argv, const char *cmd_prefix) if (require_work_tree && !is_inside_work_tree()) setup_work_tree(); - parse_pathspec(&pathspec, PATHSPEC_FROMTOP, + parse_pathspec(&pathspec, + PATHSPEC_FROMTOP | PATHSPEC_LITERAL, PATHSPEC_STRIP_SUBMODULE_SLASH_CHEAP, prefix, argv); diff --git a/builtin/ls-tree.c b/builtin/ls-tree.c index 58899a5..4764683 100644 --- a/builtin/ls-tree.c +++ b/builtin/ls-tree.c @@ -172,7 +172,9 @@ int cmd_ls_tree(int argc, const char **argv, const char *prefix) * cannot be lifted until it is converted to use * match_pathspec_depth() or tree_entry_interesting() */ - parse_pathspec(&pathspec, PATHSPEC_FROMTOP, 0, prefix, argv + 1); + parse_pathspec(&pathspec, + PATHSPEC_FROMTOP | PATHSPEC_LITERAL, + 0, prefix, argv + 1); for (i = 0; i < pathspec.nr; i++) pathspec.items[i].nowildcard_len = pathspec.items[i].len; pathspec.has_wildcard = 0; diff --git a/builtin/rerere.c b/builtin/rerere.c index a573c4a..779fc77 100644 --- a/builtin/rerere.c +++ b/builtin/rerere.c @@ -71,7 +71,9 @@ int cmd_rerere(int argc, const char **argv, const char *prefix) struct pathspec pathspec; if (argc < 2) warning("'git rerere forget' without paths is deprecated"); - parse_pathspec(&pathspec, PATHSPEC_FROMTOP, 0, prefix, argv + 1); + parse_pathspec(&pathspec, + PATHSPEC_FROMTOP | PATHSPEC_LITERAL, + 0, prefix, argv + 1); return rerere_forget(&pathspec); } diff --git a/builtin/reset.c b/builtin/reset.c index 0185bb0..69ce164 100644 --- a/builtin/reset.c +++ b/builtin/reset.c @@ -183,7 +183,9 @@ static int read_from_tree(const char *prefix, const char **argv, struct diff_options opt; memset(&opt, 0, sizeof(opt)); - parse_pathspec(&opt.pathspec, PATHSPEC_FROMTOP, 0, prefix, argv); + parse_pathspec(&opt.pathspec, + PATHSPEC_FROMTOP | PATHSPEC_LITERAL, + 0, prefix, argv); opt.output_format = DIFF_FORMAT_CALLBACK; opt.format_callback = update_index_from_diff; opt.format_callback_data = &index_was_discarded; diff --git a/builtin/rm.c b/builtin/rm.c index b2a99c2..d46f1aa 100644 --- a/builtin/rm.c +++ b/builtin/rm.c @@ -249,7 +249,9 @@ int cmd_rm(int argc, const char **argv, const char *prefix) } } - parse_pathspec(&pathspec, PATHSPEC_FROMTOP, 0, prefix, argv); + parse_pathspec(&pathspec, + PATHSPEC_FROMTOP | PATHSPEC_LITERAL, + 0, prefix, argv); refresh_index(&the_index, REFRESH_QUIET, &pathspec, NULL, NULL); seen = NULL; diff --git a/builtin/update-index.c b/builtin/update-index.c index 6728e59..1dd6178 100644 --- a/builtin/update-index.c +++ b/builtin/update-index.c @@ -548,7 +548,9 @@ static int do_reupdate(int ac, const char **av, int has_head = 1; struct pathspec pathspec; - parse_pathspec(&pathspec, PATHSPEC_FROMTOP, 0, prefix, av + 1); + parse_pathspec(&pathspec, + PATHSPEC_FROMTOP | PATHSPEC_LITERAL, + 0, prefix, av + 1); if (read_ref("HEAD", head_sha1)) /* If there is no HEAD, that means it is an initial diff --git a/cache.h b/cache.h index f3de28d..900b81a 100644 --- a/cache.h +++ b/cache.h @@ -478,6 +478,7 @@ extern int ie_modified(const struct index_state *, struct cache_entry *, struct /* Pathspec magic */ #define PATHSPEC_FROMTOP (1<<0) +#define PATHSPEC_LITERAL (1<<1) #define PATHSPEC_ONESTAR 1 /* the pathspec pattern sastisfies GFNM_ONESTAR */ diff --git a/dir.c b/dir.c index efc676c..63d07cd 100644 --- a/dir.c +++ b/dir.c @@ -64,7 +64,7 @@ static size_t common_prefix_len(const struct pathspec *pathspec) int n; size_t max = 0; - GUARD_PATHSPEC(pathspec, PATHSPEC_FROMTOP); + GUARD_PATHSPEC(pathspec, PATHSPEC_FROMTOP | PATHSPEC_LITERAL); for (n = 0; n < pathspec->nr; n++) { size_t i = 0, len = 0; @@ -181,7 +181,7 @@ int match_pathspec_depth(const struct pathspec *ps, { int i, retval = 0; - GUARD_PATHSPEC(ps, PATHSPEC_FROMTOP); + GUARD_PATHSPEC(ps, PATHSPEC_FROMTOP | PATHSPEC_LITERAL); if (!ps->nr) { if (!ps->recursive || ps->max_depth == -1) @@ -1230,7 +1230,7 @@ int read_directory(struct dir_struct *dir, const char *path, int len, const stru * Check out create_simplify() */ if (pathspec) - GUARD_PATHSPEC(pathspec, PATHSPEC_FROMTOP); + GUARD_PATHSPEC(pathspec, PATHSPEC_FROMTOP | PATHSPEC_LITERAL); if (has_symlink_leading_path(path, len)) return dir->nr; diff --git a/revision.c b/revision.c index 231f53b..079955f 100644 --- a/revision.c +++ b/revision.c @@ -1851,8 +1851,9 @@ int setup_revisions(int argc, const char **argv, struct rev_info *revs, struct s */ ALLOC_GROW(prune_data.path, prune_data.nr+1, prune_data.alloc); prune_data.path[prune_data.nr++] = NULL; - parse_pathspec(&revs->prune_data, PATHSPEC_FROMTOP, 0, - revs->prefix, prune_data.path); + parse_pathspec(&revs->prune_data, + PATHSPEC_FROMTOP | PATHSPEC_LITERAL, + 0, revs->prefix, prune_data.path); } if (revs->def == NULL) diff --git a/setup.c b/setup.c index c5e97c9..6b48f1b 100644 --- a/setup.c +++ b/setup.c @@ -157,7 +157,6 @@ void verify_non_filename(const char *prefix, const char *arg) * * Possible future magic semantics include stuff like: * - * { PATHSPEC_NOGLOB, '!', "noglob" }, * { PATHSPEC_ICASE, '\0', "icase" }, * { PATHSPEC_RECURSIVE, '*', "recursive" }, * { PATHSPEC_REGEXP, '\0', "regexp" }, @@ -170,6 +169,7 @@ static struct pathspec_magic { const char *name; } pathspec_magic[] = { { PATHSPEC_FROMTOP, '/', "top" }, + { PATHSPEC_LITERAL, 0, "literal" }, }; /* @@ -303,7 +303,7 @@ static unsigned prefix_pathspec(struct pathspec_item *item, } item->flags = 0; - if (limit_pathspec_to_literal()) + if (limit_pathspec_to_literal() || (magic & PATHSPEC_LITERAL)) item->nowildcard_len = item->len; else { item->nowildcard_len = simple_length(item->match); @@ -397,7 +397,8 @@ void parse_pathspec(struct pathspec *pathspec, const char **get_pathspec(const char *prefix, const char **pathspec) { struct pathspec ps; - parse_pathspec(&ps, PATHSPEC_FROMTOP, 0, prefix, pathspec); + parse_pathspec(&ps, PATHSPEC_FROMTOP | PATHSPEC_LITERAL, + 0, prefix, pathspec); return ps._raw; } diff --git a/t/t6130-pathspec-noglob.sh b/t/t6130-pathspec-noglob.sh index 39ef619..49c148e 100755 --- a/t/t6130-pathspec-noglob.sh +++ b/t/t6130-pathspec-noglob.sh @@ -47,18 +47,36 @@ test_expect_success 'no-glob option matches literally (vanilla)' ' test_cmp expect actual ' +test_expect_success 'no-glob option matches literally (vanilla)' ' + echo vanilla >expect && + git log --format=%s -- ":(literal)foo" >actual && + test_cmp expect actual +' + test_expect_success 'no-glob option matches literally (star)' ' echo star >expect && git --literal-pathspecs log --format=%s -- "f*" >actual && test_cmp expect actual ' +test_expect_success 'no-glob option matches literally (star)' ' + echo star >expect && + git log --format=%s -- ":(literal)f*" >actual && + test_cmp expect actual +' + test_expect_success 'no-glob option matches literally (bracket)' ' echo bracket >expect && git --literal-pathspecs log --format=%s -- "f[o][o]" >actual && test_cmp expect actual ' +test_expect_success 'no-glob option matches literally (bracket)' ' + echo bracket >expect && + git log --format=%s -- ":(literal)f[o][o]" >actual && + test_cmp expect actual +' + test_expect_success 'no-glob environment variable works' ' echo star >expect && GIT_LITERAL_PATHSPECS=1 git log --format=%s -- "f*" >actual && diff --git a/tree-diff.c b/tree-diff.c index 718f938..0e2e138 100644 --- a/tree-diff.c +++ b/tree-diff.c @@ -203,7 +203,7 @@ static void try_to_follow_renames(struct tree_desc *t1, struct tree_desc *t2, co * path. Magic that matches more than one path is not * supported. */ - GUARD_PATHSPEC(&opt->pathspec, PATHSPEC_FROMTOP); + GUARD_PATHSPEC(&opt->pathspec, PATHSPEC_FROMTOP | PATHSPEC_LITERAL); #if 0 /* * We should reject wildcards as well. Unfortunately we diff --git a/tree-walk.c b/tree-walk.c index dd03750..d4ed51f 100644 --- a/tree-walk.c +++ b/tree-walk.c @@ -635,7 +635,7 @@ enum interesting tree_entry_interesting(const struct name_entry *entry, enum interesting never_interesting = ps->has_wildcard ? entry_not_interesting : all_entries_not_interesting; - GUARD_PATHSPEC(ps, PATHSPEC_FROMTOP); + GUARD_PATHSPEC(ps, PATHSPEC_FROMTOP | PATHSPEC_LITERAL); if (!ps->nr) { if (!ps->recursive || ps->max_depth == -1) -- 1.8.0.rc2.23.g1fb49df -- To unsubscribe from this list: send the line "unsubscribe git" in the body of a message to majordomo@xxxxxxxxxxxxxxx More majordomo info at http://vger.kernel.org/majordomo-info.html