зеркало из https://github.com/microsoft/git.git
Merge branch 'ap/status-ignored-in-ignored-directory' into maint
Output from "git status --ignored" did not work well when used with "--untracked". * ap/status-ignored-in-ignored-directory: status: always report ignored tracked directories git-status: Test --ignored behavior dir.c: Make git-status --ignored more consistent
This commit is contained in:
Коммит
85fd059a89
97
dir.c
97
dir.c
|
@ -732,7 +732,8 @@ static struct dir_entry *dir_entry_new(const char *pathname, int len)
|
||||||
|
|
||||||
static struct dir_entry *dir_add_name(struct dir_struct *dir, const char *pathname, int len)
|
static struct dir_entry *dir_add_name(struct dir_struct *dir, const char *pathname, int len)
|
||||||
{
|
{
|
||||||
if (cache_name_exists(pathname, len, ignore_case))
|
if (!(dir->flags & DIR_SHOW_IGNORED) &&
|
||||||
|
cache_name_exists(pathname, len, ignore_case))
|
||||||
return NULL;
|
return NULL;
|
||||||
|
|
||||||
ALLOC_GROW(dir->entries, dir->nr+1, dir->alloc);
|
ALLOC_GROW(dir->entries, dir->nr+1, dir->alloc);
|
||||||
|
@ -834,8 +835,9 @@ static enum exist_status directory_exists_in_index(const char *dirname, int len)
|
||||||
* traversal routine.
|
* traversal routine.
|
||||||
*
|
*
|
||||||
* Case 1: If we *already* have entries in the index under that
|
* Case 1: If we *already* have entries in the index under that
|
||||||
* directory name, we always recurse into the directory to see
|
* directory name, we recurse into the directory to see all the files,
|
||||||
* all the files.
|
* unless the directory is excluded and we want to show ignored
|
||||||
|
* directories
|
||||||
*
|
*
|
||||||
* Case 2: If we *already* have that directory name as a gitlink,
|
* Case 2: If we *already* have that directory name as a gitlink,
|
||||||
* we always continue to see it as a gitlink, regardless of whether
|
* we always continue to see it as a gitlink, regardless of whether
|
||||||
|
@ -849,6 +851,9 @@ static enum exist_status directory_exists_in_index(const char *dirname, int len)
|
||||||
* just a directory, unless "hide_empty_directories" is
|
* just a directory, unless "hide_empty_directories" is
|
||||||
* also true and the directory is empty, in which case
|
* also true and the directory is empty, in which case
|
||||||
* we just ignore it entirely.
|
* we just ignore it entirely.
|
||||||
|
* if we are looking for ignored directories, look if it
|
||||||
|
* contains only ignored files to decide if it must be shown as
|
||||||
|
* ignored or not.
|
||||||
* (b) if it looks like a git directory, and we don't have
|
* (b) if it looks like a git directory, and we don't have
|
||||||
* 'no_gitlinks' set we treat it as a gitlink, and show it
|
* 'no_gitlinks' set we treat it as a gitlink, and show it
|
||||||
* as a directory.
|
* as a directory.
|
||||||
|
@ -861,12 +866,15 @@ enum directory_treatment {
|
||||||
};
|
};
|
||||||
|
|
||||||
static enum directory_treatment treat_directory(struct dir_struct *dir,
|
static enum directory_treatment treat_directory(struct dir_struct *dir,
|
||||||
const char *dirname, int len,
|
const char *dirname, int len, int exclude,
|
||||||
const struct path_simplify *simplify)
|
const struct path_simplify *simplify)
|
||||||
{
|
{
|
||||||
/* The "len-1" is to strip the final '/' */
|
/* The "len-1" is to strip the final '/' */
|
||||||
switch (directory_exists_in_index(dirname, len-1)) {
|
switch (directory_exists_in_index(dirname, len-1)) {
|
||||||
case index_directory:
|
case index_directory:
|
||||||
|
if ((dir->flags & DIR_SHOW_OTHER_DIRECTORIES) && exclude)
|
||||||
|
break;
|
||||||
|
|
||||||
return recurse_into_directory;
|
return recurse_into_directory;
|
||||||
|
|
||||||
case index_gitdir:
|
case index_gitdir:
|
||||||
|
@ -886,13 +894,68 @@ static enum directory_treatment treat_directory(struct dir_struct *dir,
|
||||||
}
|
}
|
||||||
|
|
||||||
/* This is the "show_other_directories" case */
|
/* This is the "show_other_directories" case */
|
||||||
if (!(dir->flags & DIR_HIDE_EMPTY_DIRECTORIES))
|
|
||||||
|
/*
|
||||||
|
* We are looking for ignored files and our directory is not ignored,
|
||||||
|
* check if it contains only ignored files
|
||||||
|
*/
|
||||||
|
if ((dir->flags & DIR_SHOW_IGNORED) && !exclude) {
|
||||||
|
int ignored;
|
||||||
|
dir->flags &= ~DIR_SHOW_IGNORED;
|
||||||
|
dir->flags |= DIR_HIDE_EMPTY_DIRECTORIES;
|
||||||
|
ignored = read_directory_recursive(dir, dirname, len, 1, simplify);
|
||||||
|
dir->flags &= ~DIR_HIDE_EMPTY_DIRECTORIES;
|
||||||
|
dir->flags |= DIR_SHOW_IGNORED;
|
||||||
|
|
||||||
|
return ignored ? ignore_directory : show_directory;
|
||||||
|
}
|
||||||
|
if (!(dir->flags & DIR_SHOW_IGNORED) &&
|
||||||
|
!(dir->flags & DIR_HIDE_EMPTY_DIRECTORIES))
|
||||||
return show_directory;
|
return show_directory;
|
||||||
if (!read_directory_recursive(dir, dirname, len, 1, simplify))
|
if (!read_directory_recursive(dir, dirname, len, 1, simplify))
|
||||||
return ignore_directory;
|
return ignore_directory;
|
||||||
return show_directory;
|
return show_directory;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Decide what to do when we find a file while traversing the
|
||||||
|
* filesystem. Mostly two cases:
|
||||||
|
*
|
||||||
|
* 1. We are looking for ignored files
|
||||||
|
* (a) File is ignored, include it
|
||||||
|
* (b) File is in ignored path, include it
|
||||||
|
* (c) File is not ignored, exclude it
|
||||||
|
*
|
||||||
|
* 2. Other scenarios, include the file if not excluded
|
||||||
|
*
|
||||||
|
* Return 1 for exclude, 0 for include.
|
||||||
|
*/
|
||||||
|
static int treat_file(struct dir_struct *dir, struct strbuf *path, int exclude, int *dtype)
|
||||||
|
{
|
||||||
|
struct path_exclude_check check;
|
||||||
|
int exclude_file = 0;
|
||||||
|
|
||||||
|
if (exclude)
|
||||||
|
exclude_file = !(dir->flags & DIR_SHOW_IGNORED);
|
||||||
|
else if (dir->flags & DIR_SHOW_IGNORED) {
|
||||||
|
/* Always exclude indexed files */
|
||||||
|
struct cache_entry *ce = index_name_exists(&the_index,
|
||||||
|
path->buf, path->len, ignore_case);
|
||||||
|
|
||||||
|
if (ce)
|
||||||
|
return 1;
|
||||||
|
|
||||||
|
path_exclude_check_init(&check, dir);
|
||||||
|
|
||||||
|
if (!path_excluded(&check, path->buf, path->len, dtype))
|
||||||
|
exclude_file = 1;
|
||||||
|
|
||||||
|
path_exclude_check_clear(&check);
|
||||||
|
}
|
||||||
|
|
||||||
|
return exclude_file;
|
||||||
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* This is an inexact early pruning of any recursive directory
|
* This is an inexact early pruning of any recursive directory
|
||||||
* reading - if the path cannot possibly be in the pathspec,
|
* reading - if the path cannot possibly be in the pathspec,
|
||||||
|
@ -1031,27 +1094,14 @@ static enum path_treatment treat_one_path(struct dir_struct *dir,
|
||||||
if (dtype == DT_UNKNOWN)
|
if (dtype == DT_UNKNOWN)
|
||||||
dtype = get_dtype(de, path->buf, path->len);
|
dtype = get_dtype(de, path->buf, path->len);
|
||||||
|
|
||||||
/*
|
|
||||||
* Do we want to see just the ignored files?
|
|
||||||
* We still need to recurse into directories,
|
|
||||||
* even if we don't ignore them, since the
|
|
||||||
* directory may contain files that we do..
|
|
||||||
*/
|
|
||||||
if (!exclude && (dir->flags & DIR_SHOW_IGNORED)) {
|
|
||||||
if (dtype != DT_DIR)
|
|
||||||
return path_ignored;
|
|
||||||
}
|
|
||||||
|
|
||||||
switch (dtype) {
|
switch (dtype) {
|
||||||
default:
|
default:
|
||||||
return path_ignored;
|
return path_ignored;
|
||||||
case DT_DIR:
|
case DT_DIR:
|
||||||
strbuf_addch(path, '/');
|
strbuf_addch(path, '/');
|
||||||
switch (treat_directory(dir, path->buf, path->len, simplify)) {
|
|
||||||
|
switch (treat_directory(dir, path->buf, path->len, exclude, simplify)) {
|
||||||
case show_directory:
|
case show_directory:
|
||||||
if (exclude != !!(dir->flags
|
|
||||||
& DIR_SHOW_IGNORED))
|
|
||||||
return path_ignored;
|
|
||||||
break;
|
break;
|
||||||
case recurse_into_directory:
|
case recurse_into_directory:
|
||||||
return path_recurse;
|
return path_recurse;
|
||||||
|
@ -1061,7 +1111,12 @@ static enum path_treatment treat_one_path(struct dir_struct *dir,
|
||||||
break;
|
break;
|
||||||
case DT_REG:
|
case DT_REG:
|
||||||
case DT_LNK:
|
case DT_LNK:
|
||||||
break;
|
switch (treat_file(dir, path, exclude, &dtype)) {
|
||||||
|
case 1:
|
||||||
|
return path_ignored;
|
||||||
|
default:
|
||||||
|
break;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
return path_handled;
|
return path_handled;
|
||||||
}
|
}
|
||||||
|
|
|
@ -0,0 +1,146 @@
|
||||||
|
#!/bin/sh
|
||||||
|
|
||||||
|
test_description='git-status ignored files'
|
||||||
|
|
||||||
|
. ./test-lib.sh
|
||||||
|
|
||||||
|
cat >expected <<\EOF
|
||||||
|
?? .gitignore
|
||||||
|
?? actual
|
||||||
|
?? expected
|
||||||
|
?? untracked/
|
||||||
|
EOF
|
||||||
|
|
||||||
|
test_expect_success 'status untracked directory with --ignored' '
|
||||||
|
echo "ignored" >.gitignore &&
|
||||||
|
mkdir untracked &&
|
||||||
|
: >untracked/ignored &&
|
||||||
|
: >untracked/uncommitted &&
|
||||||
|
git status --porcelain --ignored >actual &&
|
||||||
|
test_cmp expected actual
|
||||||
|
'
|
||||||
|
|
||||||
|
cat >expected <<\EOF
|
||||||
|
?? .gitignore
|
||||||
|
?? actual
|
||||||
|
?? expected
|
||||||
|
?? untracked/uncommitted
|
||||||
|
!! untracked/ignored
|
||||||
|
EOF
|
||||||
|
|
||||||
|
test_expect_success 'status untracked directory with --ignored -u' '
|
||||||
|
git status --porcelain --ignored -u >actual &&
|
||||||
|
test_cmp expected actual
|
||||||
|
'
|
||||||
|
|
||||||
|
cat >expected <<\EOF
|
||||||
|
?? .gitignore
|
||||||
|
?? actual
|
||||||
|
?? expected
|
||||||
|
!! ignored/
|
||||||
|
EOF
|
||||||
|
|
||||||
|
test_expect_success 'status ignored directory with --ignore' '
|
||||||
|
rm -rf untracked &&
|
||||||
|
mkdir ignored &&
|
||||||
|
: >ignored/uncommitted &&
|
||||||
|
git status --porcelain --ignored >actual &&
|
||||||
|
test_cmp expected actual
|
||||||
|
'
|
||||||
|
|
||||||
|
cat >expected <<\EOF
|
||||||
|
?? .gitignore
|
||||||
|
?? actual
|
||||||
|
?? expected
|
||||||
|
!! ignored/uncommitted
|
||||||
|
EOF
|
||||||
|
|
||||||
|
test_expect_success 'status ignored directory with --ignore -u' '
|
||||||
|
git status --porcelain --ignored -u >actual &&
|
||||||
|
test_cmp expected actual
|
||||||
|
'
|
||||||
|
|
||||||
|
cat >expected <<\EOF
|
||||||
|
?? .gitignore
|
||||||
|
?? actual
|
||||||
|
?? expected
|
||||||
|
!! untracked-ignored/
|
||||||
|
EOF
|
||||||
|
|
||||||
|
test_expect_success 'status untracked directory with ignored files with --ignore' '
|
||||||
|
rm -rf ignored &&
|
||||||
|
mkdir untracked-ignored &&
|
||||||
|
mkdir untracked-ignored/test &&
|
||||||
|
: >untracked-ignored/ignored &&
|
||||||
|
: >untracked-ignored/test/ignored &&
|
||||||
|
git status --porcelain --ignored >actual &&
|
||||||
|
test_cmp expected actual
|
||||||
|
'
|
||||||
|
|
||||||
|
cat >expected <<\EOF
|
||||||
|
?? .gitignore
|
||||||
|
?? actual
|
||||||
|
?? expected
|
||||||
|
!! untracked-ignored/ignored
|
||||||
|
!! untracked-ignored/test/ignored
|
||||||
|
EOF
|
||||||
|
|
||||||
|
test_expect_success 'status untracked directory with ignored files with --ignore -u' '
|
||||||
|
git status --porcelain --ignored -u >actual &&
|
||||||
|
test_cmp expected actual
|
||||||
|
'
|
||||||
|
|
||||||
|
cat >expected <<\EOF
|
||||||
|
?? .gitignore
|
||||||
|
?? actual
|
||||||
|
?? expected
|
||||||
|
EOF
|
||||||
|
|
||||||
|
test_expect_success 'status ignored tracked directory with --ignore' '
|
||||||
|
rm -rf untracked-ignored &&
|
||||||
|
mkdir tracked &&
|
||||||
|
: >tracked/committed &&
|
||||||
|
git add tracked/committed &&
|
||||||
|
git commit -m. &&
|
||||||
|
echo "tracked" >.gitignore &&
|
||||||
|
git status --porcelain --ignored >actual &&
|
||||||
|
test_cmp expected actual
|
||||||
|
'
|
||||||
|
|
||||||
|
cat >expected <<\EOF
|
||||||
|
?? .gitignore
|
||||||
|
?? actual
|
||||||
|
?? expected
|
||||||
|
EOF
|
||||||
|
|
||||||
|
test_expect_success 'status ignored tracked directory with --ignore -u' '
|
||||||
|
git status --porcelain --ignored -u >actual &&
|
||||||
|
test_cmp expected actual
|
||||||
|
'
|
||||||
|
|
||||||
|
cat >expected <<\EOF
|
||||||
|
?? .gitignore
|
||||||
|
?? actual
|
||||||
|
?? expected
|
||||||
|
!! tracked/
|
||||||
|
EOF
|
||||||
|
|
||||||
|
test_expect_success 'status ignored tracked directory and uncommitted file with --ignore' '
|
||||||
|
: >tracked/uncommitted &&
|
||||||
|
git status --porcelain --ignored >actual &&
|
||||||
|
test_cmp expected actual
|
||||||
|
'
|
||||||
|
|
||||||
|
cat >expected <<\EOF
|
||||||
|
?? .gitignore
|
||||||
|
?? actual
|
||||||
|
?? expected
|
||||||
|
!! tracked/uncommitted
|
||||||
|
EOF
|
||||||
|
|
||||||
|
test_expect_success 'status ignored tracked directory and uncommitted file with --ignore -u' '
|
||||||
|
git status --porcelain --ignored -u >actual &&
|
||||||
|
test_cmp expected actual
|
||||||
|
'
|
||||||
|
|
||||||
|
test_done
|
|
@ -516,7 +516,9 @@ static void wt_status_collect_untracked(struct wt_status *s)
|
||||||
|
|
||||||
if (s->show_ignored_files) {
|
if (s->show_ignored_files) {
|
||||||
dir.nr = 0;
|
dir.nr = 0;
|
||||||
dir.flags = DIR_SHOW_IGNORED | DIR_SHOW_OTHER_DIRECTORIES;
|
dir.flags = DIR_SHOW_IGNORED;
|
||||||
|
if (s->show_untracked_files != SHOW_ALL_UNTRACKED_FILES)
|
||||||
|
dir.flags |= DIR_SHOW_OTHER_DIRECTORIES;
|
||||||
fill_directory(&dir, s->pathspec);
|
fill_directory(&dir, s->pathspec);
|
||||||
for (i = 0; i < dir.nr; i++) {
|
for (i = 0; i < dir.nr; i++) {
|
||||||
struct dir_entry *ent = dir.entries[i];
|
struct dir_entry *ent = dir.entries[i];
|
||||||
|
|
Загрузка…
Ссылка в новой задаче