pathspec: pass directory indicator to match_pathspec_item()

This patch activates the DO_MATCH_DIRECTORY code in m_p_i(), which
makes "git diff HEAD submodule/" and "git diff HEAD submodule" produce
the same output. Previously only the version without trailing slash
returns the difference (if any).

That's the effect of new ce_path_match(). dir_path_match() is not
executed by the new tests. And it should not introduce regressions.

Previously if path "dir/" is passed in with pathspec "dir/", they
obviously match. With new dir_path_match(), the path becomes
_directory_ "dir" vs pathspec "dir/", which is not executed by the old
code path in m_p_i(). The new code path is executed and produces the
same result.

The other case is pathspec "dir" and path "dir/" is now turned to
"dir" (with DO_MATCH_DIRECTORY). Still the same result before or after
the patch.

So why change? Because of the next patch about clean.c.

Signed-off-by: Nguyễn Thái Ngọc Duy <pclouds@gmail.com>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
This commit is contained in:
Nguyễn Thái Ngọc Duy 2014-01-24 20:40:33 +07:00 committed by Junio C Hamano
parent 68690fdd0b
commit ae8d082421
6 changed files with 20 additions and 9 deletions

View File

@ -962,7 +962,7 @@ int cmd_clean(int argc, const char **argv, const char *prefix)
if (pathspec.nr) if (pathspec.nr)
matches = match_pathspec(&pathspec, ent->name, matches = match_pathspec(&pathspec, ent->name,
len, 0, NULL); len, 0, NULL, 0);
if (S_ISDIR(st.st_mode)) { if (S_ISDIR(st.st_mode)) {
if (remove_directories || (matches == MATCHED_EXACTLY)) { if (remove_directories || (matches == MATCHED_EXACTLY)) {

View File

@ -140,7 +140,8 @@ static void show_ce_entry(const char *tag, const struct cache_entry *ce)
die("git ls-files: internal error - cache entry not superset of prefix"); die("git ls-files: internal error - cache entry not superset of prefix");
if (!match_pathspec(&pathspec, ce->name, ce_namelen(ce), if (!match_pathspec(&pathspec, ce->name, ce_namelen(ce),
len, ps_matched)) len, ps_matched,
S_ISDIR(ce->ce_mode) || S_ISGITLINK(ce->ce_mode)))
return; return;
if (tag && *tag && show_valid_bit && if (tag && *tag && show_valid_bit &&
@ -197,7 +198,7 @@ static void show_ru_info(void)
if (len < max_prefix_len) if (len < max_prefix_len)
continue; /* outside of the prefix */ continue; /* outside of the prefix */
if (!match_pathspec(&pathspec, path, len, if (!match_pathspec(&pathspec, path, len,
max_prefix_len, ps_matched)) max_prefix_len, ps_matched, 0))
continue; /* uninterested */ continue; /* uninterested */
for (i = 0; i < 3; i++) { for (i = 0; i < 3; i++) {
if (!ui->mode[i]) if (!ui->mode[i])

4
dir.c
View File

@ -360,10 +360,10 @@ static int do_match_pathspec(const struct pathspec *ps,
int match_pathspec(const struct pathspec *ps, int match_pathspec(const struct pathspec *ps,
const char *name, int namelen, const char *name, int namelen,
int prefix, char *seen) int prefix, char *seen, int is_dir)
{ {
int positive, negative; int positive, negative;
unsigned flags = 0; unsigned flags = is_dir ? DO_MATCH_DIRECTORY : 0;
positive = do_match_pathspec(ps, name, namelen, positive = do_match_pathspec(ps, name, namelen,
prefix, seen, flags); prefix, seen, flags);
if (!(ps->magic & PATHSPEC_EXCLUDE) || !positive) if (!(ps->magic & PATHSPEC_EXCLUDE) || !positive)

10
dir.h
View File

@ -134,7 +134,7 @@ extern int no_wildcard(const char *string);
extern char *common_prefix(const struct pathspec *pathspec); extern char *common_prefix(const struct pathspec *pathspec);
extern int match_pathspec(const struct pathspec *pathspec, extern int match_pathspec(const struct pathspec *pathspec,
const char *name, int namelen, const char *name, int namelen,
int prefix, char *seen); int prefix, char *seen, int is_dir);
extern int within_depth(const char *name, int namelen, int depth, int max_depth); extern int within_depth(const char *name, int namelen, int depth, int max_depth);
extern int fill_directory(struct dir_struct *dir, const struct pathspec *pathspec); extern int fill_directory(struct dir_struct *dir, const struct pathspec *pathspec);
@ -209,14 +209,18 @@ static inline int ce_path_match(const struct cache_entry *ce,
const struct pathspec *pathspec, const struct pathspec *pathspec,
char *seen) char *seen)
{ {
return match_pathspec(pathspec, ce->name, ce_namelen(ce), 0, seen); return match_pathspec(pathspec, ce->name, ce_namelen(ce), 0, seen,
S_ISDIR(ce->ce_mode) || S_ISGITLINK(ce->ce_mode));
} }
static inline int dir_path_match(const struct dir_entry *ent, static inline int dir_path_match(const struct dir_entry *ent,
const struct pathspec *pathspec, const struct pathspec *pathspec,
int prefix, char *seen) int prefix, char *seen)
{ {
return match_pathspec(pathspec, ent->name, ent->len, prefix, seen); int has_trailing_dir = ent->len && ent->name[ent->len - 1] == '/';
int len = has_trailing_dir ? ent->len - 1 : ent->len;
return match_pathspec(pathspec, ent->name, len, prefix, seen,
has_trailing_dir);
} }
#endif #endif

View File

@ -673,7 +673,7 @@ int rerere_forget(struct pathspec *pathspec)
for (i = 0; i < conflict.nr; i++) { for (i = 0; i < conflict.nr; i++) {
struct string_list_item *it = &conflict.items[i]; struct string_list_item *it = &conflict.items[i];
if (!match_pathspec(pathspec, it->string, if (!match_pathspec(pathspec, it->string,
strlen(it->string), 0, NULL)) strlen(it->string), 0, NULL, 0))
continue; continue;
rerere_forget_one_path(it->string, &merge_rr); rerere_forget_one_path(it->string, &merge_rr);
} }

View File

@ -127,4 +127,10 @@ test_expect_success 'diff-tree ignores trailing slash on submodule path' '
test_cmp expect actual test_cmp expect actual
' '
test_expect_success 'diff-cache ignores trailing slash on submodule path' '
git diff --name-only HEAD^ submod >expect &&
git diff --name-only HEAD^ submod/ >actual &&
test_cmp expect actual
'
test_done test_done