Teach Status options around showing ignored files
cover Teach Status options around showing ignored files
From: Jameson Miller <[email protected]>
This patch series is the second part of [1], which was split into 2 parts. The first part, added an optimization in the directory listing logic to not scan the contents of ignored directories and was merged to master with commit 5aaa7fd3. This patch series includes the second part to expose additional arguments to the --ignored option on the status command.
This patch series teaches the status command more options to control which ignored files are reported independently of the which untracked files are reported by allowing the --ignored option to take additional arguments. Currently, the shown ignored files are linked to how untracked files are reported. Both ignored and untracked files are controlled by arguments to --untracked-files option. This makes it impossible to show all untracked files individually, but show ignored "files and directories" (that is, ignored directories are shown as 1 entry, instead of having all contents shown).
Our application (Visual Studio) has a specific set of requirements about how it wants untracked / ignored files reported by git status. It requires all untracked files listed individually. It would like ignored files and directories that explicity match an exclude pattern listed. If an ignored directory matches an exclude pattern, then the path of the directory should be returned. If a directory does not match an exclude pattern, but all of its contents are ignored, then we want the contained files reported instead of the directory.
The reason for controlling these behaviors separately is that there can be a significant performance impact to scanning the contents of excluded directories. Additionally, knowing whether a directory explicitly matches an exclude pattern can help the application make decisions about how to handle the directory. If an ignored directory itself matches an exclude pattern, then the application will know that any files underneath the directory must be ignored as well.
As a more concrete example, on Windows, Visual Studio creates a bin/ and obj/ directory inside of the project where it writes all .obj and binary build output files. Normal usage is to explicitly ignore these 2 directory names in the .gitignore file (rather than or in addition to *.obj). We just want to see the "bin/" and "obj/" paths regardless of which "--untracked-files" flag is passed in. Additionally, if we know the bin/ and obj/ directories are ignored, then we can ignore any files changes we notice underneath these paths, as we know they do not affect the output of stats.
[PATCH v1 0/1] Teach status to show ignored directories
[1] https://public-inbox.org/git/[email protected]/
Jameson Miller (6):
Teach status options around showing ignored files Update documentation for new directory and status logic Add tests for git status --ignored=matching Expand support for ignored arguments on status Add tests around status handling of ignored arguments Handle unsupported combination status arguments
Documentation/git-status.txt | 22 ++- Documentation/technical/api-directory-listing.txt | 28 +++- builtin/commit.c | 32 +++- dir.c | 44 ++++- dir.h | 3 +- t/t7519-ignored-mode.sh | 195 ++++++++++++++++++++++ wt-status.c | 11 +- wt-status.h | 8 +- 8 files changed, 325 insertions(+), 18 deletions(-) create mode 100755 t/t7519-ignored-mode.sh
Signature · 1 line
2.13.6
PATCH 1/6 Teach status options around showing ignored files
From: Jameson Miller <[email protected]>
This change teaches the status command more options to control which ignored files are reported independently of the which untracked files are reported by allowing the --ignored option to take additional arguments. Currently, the shown ignored files are linked to how untracked files are reported. Both ignored and untracked files are controlled by arguments to --untracked-files option. This makes it impossible to show all untracked files individually, but show ignored "files and directories" (that is, ignored directories are shown as 1 entry, instead of having all contents shown).
Our application (Visual Studio) has a specific set of requirements about how it wants untracked / ignored files reported by git status. It requires all untracked files listed individually. It would like ignored files and directories that explicity match an exclude pattern listed. If an ignored directory matches an exclude pattern, then the path of the directory should be returned. If a directory does not match an exclude pattern, but all of its contents are ignored, then we want the contained files reported instead of the directory.
The reason for controlling these behaviors separately is that there can be a significant performance impact to scanning the contents of excluded directories. Additionally, knowing whether a directory explicitly matches an exclude pattern can help the application make decisions about how to handle the directory. If an ignored directory itself matches an exclude pattern, then the application will know that any files underneath the directory must be ignored as well.
As a more concrete example, on Windows, Visual Studio creates a bin/ and obj/ directory inside of the project where it writes all .obj and binary build output files. Normal usage is to explicitly ignore these 2 directory names in the .gitignore file (rather than or in addition to *.obj). We just want to see the "bin/" and "obj/" paths regardless of which "--untracked-files" flag is passed in. Additionally, if we know the bin/ and obj/ directories are ignored, then we can ignore any files changes we notice underneath these paths, as we know they do not affect the output of stats.
--- builtin/commit.c | 27 +++++++++++++++++++++------ dir.c | 24 ++++++++++++++++++++++++ dir.h | 3 ++- wt-status.c | 11 ++++++++--- wt-status.h | 8 +++++++- 5 files changed, 62 insertions(+), 11 deletions(-)
builtin/commit.c +21 -6
@@ -118,7 +118,7 @@ static int edit_flag = -1; /* unspecified */static int quiet, verbose, no_verify, allow_empty, dry_run, renew_authorship;static int config_commit_verbose =-1 ;/* unspecified */ static int no_post_rewrite, allow_empty_message; -static char *untracked_files_arg, *force_date, *ignore_submodule_arg; +static char *untracked_files_arg, *force_date, *ignore_submodule_arg, *ignored_arg;static char *sign_commit;/*
@@ -139,7 +139,7 @@ static const char *cleanup_arg;static enum commit_whence whence;static int sequencer_in_use;static int use_editor =1 , include_status =1 ; -static int show_ignored_in_status, have_option_m; +static int have_option_m;static struct strbuf message =STRBUF_INIT ;static enum wt_status_format status_format =STATUS_FORMAT_UNSPECIFIED ;
@@ -1075,6 +1075,19 @@ static const char *find_author_by_nickname(const char *name)die (_ ("--author '%s' is not 'Name <email>' and matches no existing author" ), name); } +static void handle_ignored_arg (struct wt_status *s) +{ +if (!ignored_arg) + ;/* default already initialized */ +else if (!strcmp (ignored_arg,"traditional" )) + s->show_ignored_mode =SHOW_TRADITIONAL_IGNORED ; +else if (!strcmp (ignored_arg,"no" )) + s->show_ignored_mode =SHOW_NO_IGNORED ; +else if (!strcmp (ignored_arg,"matching" )) + s->show_ignored_mode =SHOW_MATCHING_IGNORED ; +else +die (_ ("Invalid ignored mode '%s'" ), ignored_arg); +}static void handle_untracked_files_arg (struct wt_status *s) {
@@ -1363,8 +1376,10 @@ int cmd_status(int argc, const char **argv, const char *prefix)N_ ("mode" ),N_ ("show untracked files, optional modes: all, normal, no. (Default: all)" ), PARSE_OPT_OPTARG, NULL, (intptr_t)"all" }, -OPT_BOOL (0 ,"ignored" , &show_ignored_in_status, -N_ ("show ignored files" )), + { OPTION_STRING, 0, "ignored", &ignored_arg, +N_ ("mode" ), +N_ ("show ignored files, optional modes: traditional, matching, no. (Default: traditional)" ), + PARSE_OPT_OPTARG, NULL, (intptr_t)"traditional" }, { OPTION_STRING, 0, "ignore-submodules", &ignore_submodule_arg, N_("when"),N_ ("ignore changes to submodules, optional when: all, dirty, untracked. (Default: all)" ), PARSE_OPT_OPTARG, NULL, (intptr_t)"all" },
@@ -1383,8 +1398,8 @@ int cmd_status(int argc, const char **argv, const char *prefix)finalize_deferred_config (&s);handle_untracked_files_arg (&s); -if (show_ignored_in_status) - s.show_ignored_files =1 ; +handle_ignored_arg (&s); +parse_pathspec (&s.pathspec,0 ,PATHSPEC_PREFER_FULL , prefix, argv);
dir.c +24 -0
@@ -1389,6 +1389,30 @@ static enum path_treatment treat_directory(struct dir_struct *dir,case index_nonexistent:if (dir->flags &DIR_SHOW_OTHER_DIRECTORIES )break ; +if (exclude && + (dir->flags &DIR_SHOW_IGNORED_TOO ) && + (dir->flags &DIR_SHOW_IGNORED_TOO_MODE_MATCHING )) { + +/* +* This is an excluded directory and we are +* showing ignored paths that match an exclude +* pattern. (e.g. show directory as ignored +* only if it matches an exclude pattern). +* This path will either be 'path_excluded` +* (if we are showing empty directories or if +* the directory is not empty), or will be +* 'path_none' (empty directory, and we are +* not showing empty directories). +*/ +if (!(dir->flags &DIR_HIDE_EMPTY_DIRECTORIES )) +return path_excluded; + +if (read_directory_recursive (dir, istate, dirname, len, + untracked,1 ,1 , pathspec) == path_excluded) +return path_excluded; + +return path_none; + }if (!(dir->flags &DIR_NO_GITLINKS )) {unsigned char sha1[20 ];if (resolve_gitlink_ref (dirname,"HEAD" , sha1) ==0 )
dir.h +2 -1
@@ -152,7 +152,8 @@ struct dir_struct {DIR_COLLECT_IGNORED =1 <<4 ,DIR_SHOW_IGNORED_TOO =1 <<5 ,DIR_COLLECT_KILLED_ONLY =1 <<6 , - DIR_KEEP_UNTRACKED_CONTENTS = 1<<7 +DIR_KEEP_UNTRACKED_CONTENTS =1 <<7 , + DIR_SHOW_IGNORED_TOO_MODE_MATCHING = 1<<8 } flags;struct dir_entry **entries;struct dir_entry **ignored;
wt-status.c +8 -3
@@ -660,10 +660,15 @@ static void wt_status_collect_untracked(struct wt_status *s)if (s->show_untracked_files !=SHOW_ALL_UNTRACKED_FILES ) dir.flags |=DIR_SHOW_OTHER_DIRECTORIES |DIR_HIDE_EMPTY_DIRECTORIES ; -if (s->show_ignored_files) +if (s->show_ignored_mode) { dir.flags |=DIR_SHOW_IGNORED_TOO ; -else + +if (s->show_ignored_mode ==SHOW_MATCHING_IGNORED ) + dir.flags |=DIR_SHOW_IGNORED_TOO_MODE_MATCHING ; + }else { dir.untracked = the_index.untracked; + } +setup_standard_excludes (&dir);fill_directory (&dir, &the_index, &s->pathspec);
@@ -1621,7 +1626,7 @@ static void wt_longstatus_print(struct wt_status *s) }if (s->show_untracked_files) {wt_longstatus_print_other (s, &s->untracked,_ ("Untracked files" ),"add" ); -if (s->show_ignored_files) +if (s->show_ignored_mode)wt_longstatus_print_other (s, &s->ignored,_ ("Ignored files" ),"add -f" );if (advice_status_u_option &&2000 < s->untracked_in_ms) {status_printf_ln (s,GIT_COLOR_NORMAL ,"%s" ,"" );
wt-status.h +7 -1
@@ -27,6 +27,12 @@ enum untracked_status_type {SHOW_ALL_UNTRACKED_FILES }; +enum show_ignored_type { +SHOW_NO_IGNORED , +SHOW_TRADITIONAL_IGNORED , +SHOW_MATCHING_IGNORED , +}; +/* from where does this commit originate */ enum commit_whence {FROM_COMMIT ,/* normal */
@@ -70,7 +76,7 @@ struct wt_status {int display_comment_prefix;int relative_paths;int submodule_summary; -int show_ignored_files; +enum show_ignored_type show_ignored_mode;enum untracked_status_type show_untracked_files;const char *ignore_submodule_arg;char color_palette[WT_STATUS_MAXSLOT ][COLOR_MAXLEN ];
Signature · 1 line
2.13.6
PATCH 2/6 Update documentation for new directory and status logic
In reply to [email protected]From: Jameson Miller <[email protected]>
--- Documentation/git-status.txt | 22 +++++++++++++++++- Documentation/technical/api-directory-listing.txt | 28 +++++++++++++++++++---- 2 files changed, 45 insertions(+), 5 deletions(-)
Documentation/git-status.txt +21 -1
@@ -97,8 +97,28 @@ configuration variable documented in linkgit:git-config[1]. (and suppresses the output of submodule summaries when the config option `status.submoduleSummary` is set). ---ignored:: +--ignored[=<mode>]:: Show ignored files as well. ++ +The mode parameter is used to specify the handling of ignored files. +It is optional: it defaults to 'default', and if specified, it must be +stuck to the option (e.g. '--ignored=default`, but not `--ignored default`). ++ +The possible options are: ++ + - 'traditional' - Shows ignored files and directories, unless + --untracked-files=all is specifed, in which case + individual files in ignored directories are + displayed. + - 'no' - Show no ignored files. + - 'matching' - Shows ignored files and directories matching an + ignore pattern. ++ +When 'matching' mode is specified, paths that explicity match an +ignored pattern are shown. If a directory matches an ignore pattern, +then it is shown, but not paths contained in the ignored directory. If +a directory does not match an ignore pattern, but all contents are +ignored, then the directory is not shown, but all contents are shown. -z:: Terminate entries with NUL, instead of LF. This implies
Documentation/technical/api-directory-listing.txt +24 -4
@@ -22,16 +22,20 @@ The notable options are: `flags`:: - A bit-field of options (the `*IGNORED*` flags are mutually exclusive): + A bit-field of options: `DIR_SHOW_IGNORED`::: - Return just ignored files in `entries[]`, not untracked files. + Return just ignored files in `entries[]`, not untracked + files. This is flag is mutually exclusive with + `DIR_SHOW_IGNORED_TOO`. `DIR_SHOW_IGNORED_TOO`::: - Similar to `DIR_SHOW_IGNORED`, but return ignored files in `ignored[]` - in addition to untracked files in `entries[]`. + Similar to `DIR_SHOW_IGNORED`, but return ignored files in + `ignored[]` in addition to untracked files in + `entries[]`. This flag is mutually exclusive with + `DIR_SHOW_IGNORED`. `DIR_KEEP_UNTRACKED_CONTENTS`:::
@@ -39,6 +43,22 @@ The notable options are: untracked contents of untracked directories are also returned in `entries[]`. +`DIR_SHOW_IGNORED_TOO_MODE_MATCHING`::: + + Only has meaning if `DIR_SHOW_IGNORED_TOO` is also set; if + this is set, returns ignored files and directories that match + an exclude pattern. If a directory matches an exclude pattern, + then the directory is returned and the contained paths are + not. A directory that does not match an exclude pattern will + not be returned even if all of its contents are ignored. In + this case, the contents are returned as individual entries. + +If this is set, files and directories + that explicity match an ignore pattern are reported. Implicity + ignored directories (directories that do not match an ignore + pattern, but whose contents are all ignored) are not reported, + instead all of the contents are reported. + `DIR_COLLECT_IGNORED`::: Special mode for git-add. Return ignored files in `ignored[]` and
Signature · 1 line
2.13.6
Re: [PATCH 2/6] Update documentation for new directory and status logic
Quoted 13 lines · On Thu, Oct 5, 2017 at 1:54 PM, <[email protected]> wrote:
From: Jameson Miller <[email protected]>
Signed-off-by Jameson Miller <[email protected]>--- Documentation/git-status.txt | 22 +++++++++++++++++- Documentation/technical/api-directory-listing.txt | 28 +++++++++++++++++++---- 2 files changed, 45 insertions(+), 5 deletions(-)Documentation/git-status.txt +0
-0
Documentation/git-status.txt configuration variable documented in linkgit:git-config[1]. · line 105
Quoted 10 lines
Documentation/git-status.txt +5
-1@@ -97,8 +97,28 @@ configuration variable documented in linkgit:git-config[1]. (and suppresses the output of submodule summaries when the config option `status.submoduleSummary` is set). ---ignored:: +--ignored[=<mode>]:: Show ignored files as well. ++ +The mode parameter is used to specify the handling of ignored files. +It is optional: it defaults to 'default', and if specified, it must be +stuck to the option (e.g. '--ignored=default`, but not `--ignored default`).
Is there a rationale for not accepting --ignored default? (It's just the way OPTION_STRING inputs seem to work,
but in other cases [c.f. man git gc, search "--prune=" ] this is just implied). Or rather: no need to spell this out explicitly IMHO, as that draws the users attention to it, which might be confusing.
Quoted 25 lines
Documentation/git-status.txt +16
-0++ +The possible options are: ++ + - 'traditional' - Shows ignored files and directories, unless + --untracked-files=all is specifed, in which case + individual files in ignored directories are + displayed. + - 'no' - Show no ignored files. + - 'matching' - Shows ignored files and directories matching an + ignore pattern. ++ +When 'matching' mode is specified, paths that explicity match an +ignored pattern are shown. If a directory matches an ignore pattern, +then it is shown, but not paths contained in the ignored directory. If +a directory does not match an ignore pattern, but all contents are +ignored, then the directory is not shown, but all contents are shown. -z:: Terminate entries with NUL, instead of LF. This impliesDocumentation/technical/api-directory-listing.txt +0
-0@@ -22,16 +22,20 @@ The notable options are:
Documentation/technical/api-directory-listing.txt The notable options are: · line 30
Quoted 10 lines
Documentation/technical/api-directory-listing.txt +3
-2`flags`:: - A bit-field of options (the `*IGNORED*` flags are mutually exclusive): + A bit-field of options: `DIR_SHOW_IGNORED`::: - Return just ignored files in `entries[]`, not untracked files. + Return just ignored files in `entries[]`, not untracked + files. This is flag is mutually exclusive with
"is flag is" ?
Quoted 17 lines
Documentation/technical/api-directory-listing.txt +5
-2+ `DIR_SHOW_IGNORED_TOO`. `DIR_SHOW_IGNORED_TOO`::: - Similar to `DIR_SHOW_IGNORED`, but return ignored files in `ignored[]` - in addition to untracked files in `entries[]`. + Similar to `DIR_SHOW_IGNORED`, but return ignored files in + `ignored[]` in addition to untracked files in + `entries[]`. This flag is mutually exclusive with + `DIR_SHOW_IGNORED`. `DIR_KEEP_UNTRACKED_CONTENTS`:::@@ -39,6 +43,22 @@ The notable options are: untracked contents of untracked directories are also returned in `entries[]`.
Documentation/technical/api-directory-listing.txt The notable options are: · line 55
Quoted 10 lines
Documentation/technical/api-directory-listing.txt +10
-0+`DIR_SHOW_IGNORED_TOO_MODE_MATCHING`::: + + Only has meaning if `DIR_SHOW_IGNORED_TOO` is also set; if + this is set, returns ignored files and directories that match + an exclude pattern. If a directory matches an exclude pattern, + then the directory is returned and the contained paths are + not. A directory that does not match an exclude pattern will + not be returned even if all of its contents are ignored. In + this case, the contents are returned as individual entries. +
I think to make the asciidoc happy, you'd put a '+ LF' as paragraph delimiter and the subsequent paragraphs are not indented. C.f. Documentation/git-gc.txt "--auto".
Oh, screw that. It turns out, this place is the only place in our docs where we use triple colons. So I don't know what I am talking about.
Quoted 12 lines
Documentation/technical/api-directory-listing.txt +6
-1+If this is set, files and directories + that explicity match an ignore pattern are reported. Implicity + ignored directories (directories that do not match an ignore + pattern, but whose contents are all ignored) are not reported, + instead all of the contents are reported. + `DIR_COLLECT_IGNORED`::: Special mode for git-add. Return ignored files in `ignored[]` and --2.13.6
PATCH 3/6 Add tests for git status `--ignored=matching`
In reply to [email protected]From: Jameson Miller <[email protected]>
Add tests for new ignored mode (matching) when showing all untracked files.
--- t/t7519-ignored-mode.sh | 132 ++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 132 insertions(+) create mode 100755 t/t7519-ignored-mode.sh
t/t7519-ignored-mode.sh new file +132 -0
@@ -0,0 +1,132 @@ +#!/bin/sh + +test_description='git status collapse ignored' + +. ./test-lib.sh + +# commit initial ignore file +test_expect_success 'setup initial commit and ignore file' ' + cat >.gitignore <<-\EOF && + *.ign + ignored_dir/ + !*.unignore + EOF + git add . && + test_tick && + git commit -m "Initial commit" +' + +# Test status behavior on folder with ignored files +test_expect_success 'Verify behavior of status on folders with ignored files' ' + test_when_finished "git clean -fdx" && + cat >expect <<-\EOF && + ? expect + ? output + ! dir/ignored/ignored_1.ign + ! dir/ignored/ignored_2.ign + ! ignored/ignored_1.ign + ! ignored/ignored_2.ign + EOF + + mkdir -p ignored dir/ignored && + touch ignored/ignored_1.ign ignored/ignored_2.ign \ + dir/ignored/ignored_1.ign dir/ignored/ignored_2.ign && + + git status --porcelain=v2 --ignored=matching --untracked-files=all >output && + test_i18ncmp expect output +' + +# Test status behavior on folder with tracked and ignored files +test_expect_success 'Verify status on folder with tracked & ignored files' ' + test_when_finished "git clean -fdx && git reset HEAD~1 --hard" && + cat >expect <<-\EOF && + ? expect + ? output + ! dir/tracked_ignored/ignored_1.ign + ! dir/tracked_ignored/ignored_2.ign + ! tracked_ignored/ignored_1.ign + ! tracked_ignored/ignored_2.ign + EOF + + mkdir -p tracked_ignored dir/tracked_ignored && + touch tracked_ignored/tracked_1 tracked_ignored/tracked_2 \ + tracked_ignored/ignored_1.ign tracked_ignored/ignored_2.ign \ + dir/tracked_ignored/tracked_1 dir/tracked_ignored/tracked_2 \ + dir/tracked_ignored/ignored_1.ign dir/tracked_ignored/ignored_2.ign && + + git add tracked_ignored/tracked_1 tracked_ignored/tracked_2 \ + dir/tracked_ignored/tracked_1 dir/tracked_ignored/tracked_2 && + test_tick && + git commit -m "commit tracked files" && + + git status --porcelain=v2 --ignored=matching --untracked-files=all >output && + test_i18ncmp expect output +' + +# Test status behavior on folder with untracked and ignored files +test_expect_success 'Verify status matching ignored files on folder with tracked & ignored files' ' + test_when_finished "git clean -fdx" && + cat >expect <<-\EOF && + ? dir/untracked_ignored/untracked_1 + ? dir/untracked_ignored/untracked_2 + ? expect + ? output + ? untracked_ignored/untracked_1 + ? untracked_ignored/untracked_2 + ! dir/untracked_ignored/ignored_1.ign + ! dir/untracked_ignored/ignored_2.ign + ! untracked_ignored/ignored_1.ign + ! untracked_ignored/ignored_2.ign + EOF + + mkdir -p untracked_ignored dir/untracked_ignored && + touch untracked_ignored/untracked_1 untracked_ignored/untracked_2 \ + untracked_ignored/ignored_1.ign untracked_ignored/ignored_2.ign \ + dir/untracked_ignored/untracked_1 dir/untracked_ignored/untracked_2 \ + dir/untracked_ignored/ignored_1.ign dir/untracked_ignored/ignored_2.ign && + + git status --porcelain=v2 --ignored=matching --untracked-files=all >output && + test_i18ncmp expect output +' + +# Test status behavior on ignored folder +test_expect_success 'Verify status matching ignored files on ignored folder' ' + test_when_finished "git clean -fdx" && + cat >expect <<-\EOF && + ? expect + ? output + ! ignored_dir/ + EOF + + mkdir ignored_dir && + touch ignored_dir/ignored_1 ignored_dir/ignored_2 \ + ignored_dir/ignored_1.ign ignored_dir/ignored_2.ign && + + git status --porcelain=v2 --ignored=matching --untracked-files=all >output && + test_i18ncmp expect output +' + +# Test status behavior on ignored folder with tracked file +test_expect_success 'Verify status behavior on ignored folder containing tracked file' ' + test_when_finished "git clean -fdx && git reset HEAD~1 --hard" && + cat >expect <<-\EOF && + ? expect + ? output + ! ignored_dir/ignored_1 + ! ignored_dir/ignored_1.ign + ! ignored_dir/ignored_2 + ! ignored_dir/ignored_2.ign + EOF + + mkdir ignored_dir && + touch ignored_dir/ignored_1 ignored_dir/ignored_2 \ + ignored_dir/ignored_1.ign ignored_dir/ignored_2.ign \ + ignored_dir/tracked && + git add -f ignored_dir/tracked && + test_tick && + git commit -m "Force add file in ignored directory" && + git status --porcelain=v2 --ignored=matching --untracked-files=all >output && + test_i18ncmp expect output +' + +test_done
Signature · 1 line
2.13.6
Re: [PATCH 3/6] Add tests for git status `--ignored=matching`
Quoted 17 lines · On Thu, Oct 5, 2017 at 1:54 PM, <[email protected]> wrote:
From: Jameson Miller <[email protected]>
Add tests for new ignored mode (matching) when showing all untracked files.
Signed-off-by Jameson Miller <[email protected]>--- t/t7519-ignored-mode.sh | 132 ++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 132 insertions(+) create mode 100755 t/t7519-ignored-mode.sht/t7519-ignored-mode.sh new file +0
-0
t/t7519-ignored-mode.sh line 8
Quoted 8 lines
t/t7519-ignored-mode.sh new file +8
-0@@ -0,0 +1,132 @@ +#!/bin/sh + +test_description='git status collapse ignored' + +. ./test-lib.sh + +# commit initial ignore file +test_expect_success 'setup initial commit and ignore file' '
Here and in the following tests, I have the impression that the leading comment says the same as the test title, so you could omit the comments, putting all effort into a well word smithed test title.
t/t7519-ignored-mode.sh line 15
Quoted 7 lines
t/t7519-ignored-mode.sh new file +7
-0+ cat >.gitignore <<-\EOF && + *.ign + ignored_dir/ + !*.unignore + EOF + git add . && + test_tick &&
How is timing relevant to these test?
Thanks,
Stefan
PATCH 4/6 Expand support for ignored arguments on status
In reply to [email protected]From: Jameson Miller <[email protected]>
Teach status command to handle matching ignored mode when showing untracked files with the normal option.
--- dir.c | 20 ++++++++++++++++++-- 1 file changed, 18 insertions(+), 2 deletions(-)
dir.c +18 -2
@@ -1585,6 +1585,7 @@ static enum path_treatment treat_one_path(struct dir_struct *dir, {int exclude;int has_path_in_index = !!index_file_exists (istate, path->buf, path->len, ignore_case); +enum path_treatment path_treatment;if (dtype ==DT_UNKNOWN ) dtype =get_dtype (de, istate, path->buf, path->len);
@@ -1631,8 +1632,23 @@ static enum path_treatment treat_one_path(struct dir_struct *dir,return path_none;case DT_DIR :strbuf_addch (path,'/' ); -return treat_directory (dir, istate, untracked, path->buf, path->len, - baselen, exclude, pathspec); + path_treatment =treat_directory (dir, istate, untracked, + path->buf, path->len, + baselen, exclude, pathspec); +/* +* If we are only want to return directories that +* match an exclude pattern, and this directories does +* not match an exclude pattern but all contents are +* excluded, then indicate that we should recurse into +* this directory (instead of marking the directory +* itself as an ignored path) +*/ +if (!exclude && + path_treatment == path_excluded && + (dir->flags &DIR_SHOW_IGNORED_TOO ) && + (dir->flags &DIR_SHOW_IGNORED_TOO_MODE_MATCHING )) +return path_recurse; +return path_treatment;case DT_REG :case DT_LNK :return exclude ? path_excluded : path_untracked;
Signature · 1 line
2.13.6
PATCH 5/6 Add tests around status handling of ignored arguments
In reply to [email protected]From: Jameson Miller <[email protected]>
Add tests for status handling of '--ignored=matching and --untracked-files=normal`.
--- t/t7519-ignored-mode.sh | 63 +++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 63 insertions(+)
t/t7519-ignored-mode.sh +63 -0
@@ -129,4 +129,67 @@ test_expect_success 'Verify status behavior on ignored folder containing tracked test_i18ncmp expect output ' +# Test ignored matching behavior with --untracked=normal +test_expect_success 'Verify matching ignored files with --untracked-files=normal' ' + test_when_finished "git clean -fdx" && + cat >expect <<-\EOF && + ? expect + ? output + ? untracked_dir/ + ! ignored_dir/ + ! ignored_files/ignored_1.ign + ! ignored_files/ignored_2.ign + EOF + + mkdir ignored_dir ignored_files untracked_dir && + touch ignored_dir/ignored_1 ignored_dir/ignored_2 \ + ignored_files/ignored_1.ign ignored_files/ignored_2.ign \ + untracked_dir/untracked && + git status --porcelain=v2 --ignored=matching --untracked-files=normal >output && + test_i18ncmp expect output +' + +# Test ignored matching behavior with --untracked=normal +test_expect_success 'Verify matching ignored files with --untracked-files=normal' ' + test_when_finished "git clean -fdx" && + cat >expect <<-\EOF && + ? expect + ? output + ? untracked_dir/ + ! ignored_dir/ + ! ignored_files/ignored_1.ign + ! ignored_files/ignored_2.ign + EOF + + mkdir ignored_dir ignored_files untracked_dir && + touch ignored_dir/ignored_1 ignored_dir/ignored_2 \ + ignored_files/ignored_1.ign ignored_files/ignored_2.ign \ + untracked_dir/untracked && + git status --porcelain=v2 --ignored=matching --untracked-files=normal >output && + test_i18ncmp expect output +' + +# Test status behavior on ignored folder with tracked file +test_expect_success 'Verify status behavior on ignored folder containing tracked file' ' + test_when_finished "git clean -fdx && git reset HEAD~1 --hard" && + cat >expect <<-\EOF && + ? expect + ? output + ! ignored_dir/ignored_1 + ! ignored_dir/ignored_1.ign + ! ignored_dir/ignored_2 + ! ignored_dir/ignored_2.ign + EOF + + mkdir ignored_dir && + touch ignored_dir/ignored_1 ignored_dir/ignored_2 \ + ignored_dir/ignored_1.ign ignored_dir/ignored_2.ign \ + ignored_dir/tracked && + git add -f ignored_dir/tracked && + test_tick && + git commit -m "Force add file in ignored directory" && + git status --porcelain=v2 --ignored=matching --untracked-files=normal >output && + test_i18ncmp expect output +' + test_done
Signature · 1 line
2.13.6
PATCH 6/6 Handle unsupported combination status arguments
In reply to [email protected]From: Jameson Miller <[email protected]>
It is not clear what the correct behavior should be when you ask for specific ignored behavior without reporting untracked files. For now, report this as an unsupported combination of input arguments, so it can be modified in the future without back compat concerns.
--- builtin/commit.c | 5 +++++ 1 file changed, 5 insertions(+)
builtin/commit.c +5 -0
@@ -1400,6 +1400,11 @@ int cmd_status(int argc, const char **argv, const char *prefix)handle_untracked_files_arg (&s);handle_ignored_arg (&s); +/* Check for unsupported combination of args */ +if (s.show_ignored_mode ==SHOW_MATCHING_IGNORED && + s.show_untracked_files ==SHOW_NO_UNTRACKED_FILES ) +die (_ ("Unsupported combination of ignored and untracked-files arguments" )); +parse_pathspec (&s.pathspec,0 ,PATHSPEC_PREFER_FULL , prefix, argv);
Signature · 1 line
2.13.6
Re: [PATCH 6/6] Handle unsupported combination status arguments
Quoted 6 lines · On Thu, Oct 5, 2017 at 1:54 PM, <[email protected]> wrote:
From: Jameson Miller <[email protected]>
It is not clear what the correct behavior should be when you ask for specific ignored behavior without reporting untracked files. For now, report this as an unsupported combination of input arguments, so it can be modified in the future without back compat concerns.
Is there a rationale to put this as an extra commit at the end, or could this be squashed into the first commit as well?
Quoted 11 lines
Signed-off-by Jameson Miller <[email protected]>--- builtin/commit.c | 5 +++++ 1 file changed, 5 insertions(+)builtin/commit.c +0
-0
builtin/commit.c int cmd_status(int argc, const char **argv, const char *prefix) · line 1403
Quoted 4 lines
builtin/commit.c +1
-0@@ -1400,6 +1400,11 @@ int cmd_status(int argc, const char **argv, const char *prefix)handle_untracked_files_arg (&s);handle_ignored_arg (&s); +/* Check for unsupported combination of args */
Oh, this is the first check that we add here for unsupported combinations. How much value does this comment bring to the future reader?
builtin/commit.c int cmd_status(int argc, const char **argv, const char *prefix) · line 1406
Quoted 3 lines
builtin/commit.c +3
-0+if (s.show_ignored_mode ==SHOW_MATCHING_IGNORED && + s.show_untracked_files ==SHOW_NO_UNTRACKED_FILES ) +die (_ ("Unsupported combination of ignored and untracked-files arguments" ));
Thanks for taking care of the corner case!
Stefan
Hi,
Quoted 6 lines · [email protected] wrote:
This patch series is the second part of [1], which was split into 2 parts. The first part, added an optimization in the directory listing logic to not scan the contents of ignored directories and was merged to master with commit
5aaa7fd3. This patch series includes the second part to expose additional arguments to the --ignored option on the status command.
Thanks.
Quoted 2 lines
This patch series teaches the status command more options to control which ignored files are reported independently of the which untracked
[...]
Quoted 2 lines
Our application (Visual Studio) has a specific set of requirements about how it wants untracked / ignored files reported by git status.
[...]
Quoted 2 lines
The reason for controlling these behaviors separately is that there can be a significant performance impact to scanning the contents of
[....]
Quoted 2 lines
As a more concrete example, on Windows, Visual Studio creates a bin/ and obj/ directory inside of the project where it writes all .obj and
[...]
I see this information is also in patch 1/6. That's a very good thing, since that makes performance numbers involved more concrete about which patch brings them about and it becomes part of permanent history that way --- thanks.
But it took me a while to notice, and before then, I was trying to read through the cover letter to get an overview of which patches I am supposed to look at. For next time, could the cover letter say something like "See patches 1 and 2 for more details about the motivation" instead of repeating the commit message content? That would save reviewers some time.
Thanks,
Jonathan
Quoted 30 lines · Jonathan Nieder
Hi,
Quoted 6 lines · [email protected] wrote:
This patch series is the second part of [1], which was split into 2 parts. The first part, added an optimization in the directory listing logic to not scan the contents of ignored directories and was merged to master with commit
5aaa7fd3. This patch series includes the second part to expose additional arguments to the --ignored option on the status command.Thanks.
Quoted 2 lines
This patch series teaches the status command more options to control which ignored files are reported independently of the which untracked
[...]
Quoted 2 lines
Our application (Visual Studio) has a specific set of requirements about how it wants untracked / ignored files reported by git status.
[...]
Quoted 2 lines
The reason for controlling these behaviors separately is that there can be a significant performance impact to scanning the contents of
[....]
Quoted 2 lines
As a more concrete example, on Windows, Visual Studio creates a bin/ and obj/ directory inside of the project where it writes all .obj and
[...]
I see this information is also in patch 1/6. That's a very good thing, since that makes performance numbers involved more concrete about which patch brings them about and it becomes part of permanent history that way --- thanks.
Quoted 6 lines
But it took me a while to notice, and before then, I was trying to read through the cover letter to get an overview of which patches I am supposed to look at. For next time, could the cover letter say something like "See patches 1 and 2 for more details about the motivation" instead of repeating the commit message content? That would save reviewers some time.
Will do - thank you for the feedback!
Quoted 3 lines
Thanks,
Jonathan
v2 cover Teach Status options around showing ignored files
In reply to [email protected]Changes in v2:
Addressed review comments from the original series:
* Made fixes / simplifications suggested for documentation
* Removed test_tick from test scripts
* Merged 2 commits (as suggested)
Jameson Miller (5):
Teach status options around showing ignored files Update documentation for new directory and status logic Add tests for git status --ignored=matching Expand support for ignored arguments on status Add tests around status handling of ignored arguments
Documentation/git-status.txt | 21 ++- Documentation/technical/api-directory-listing.txt | 27 +++- builtin/commit.c | 31 +++- dir.c | 44 +++++- dir.h | 3 +- t/t7519-ignored-mode.sh | 183 ++++++++++++++++++++++ wt-status.c | 11 +- wt-status.h | 8 +- 8 files changed, 310 insertions(+), 18 deletions(-) create mode 100755 t/t7519-ignored-mode.sh
Signature · 1 line
2.13.6
PATCH v2 1/5 Teach status options around showing ignored files
This change teaches the status command more options to control which ignored files are reported independently of the which untracked files are reported by allowing the --ignored option to take additional arguments. Currently, the shown ignored files are linked to how untracked files are reported. Both ignored and untracked files are controlled by arguments to --untracked-files option. This makes it impossible to show all untracked files individually, but show ignored "files and directories" (that is, ignored directories are shown as 1 entry, instead of having all contents shown).
Our application (Visual Studio) has a specific set of requirements about how it wants untracked / ignored files reported by git status. It requires all untracked files listed individually. It would like ignored files and directories that explicity match an exclude pattern listed. If an ignored directory matches an exclude pattern, then the path of the directory should be returned. If a directory does not match an exclude pattern, but all of its contents are ignored, then we want the contained files reported instead of the directory.
The reason for controlling these behaviors separately is that there can be a significant performance impact to scanning the contents of excluded directories. Additionally, knowing whether a directory explicitly matches an exclude pattern can help the application make decisions about how to handle the directory. If an ignored directory itself matches an exclude pattern, then the application will know that any files underneath the directory must be ignored as well.
As a more concrete example, on Windows, Visual Studio creates a bin/ and obj/ directory inside of the project where it writes all .obj and binary build output files. Normal usage is to explicitly ignore these 2 directory names in the .gitignore file (rather than or in addition to *.obj). We just want to see the "bin/" and "obj/" paths regardless of which "--untracked-files" flag is passed in. Additionally, if we know the bin/ and obj/ directories are ignored, then we can ignore any files changes we notice underneath these paths, as we know they do not affect the output of stats.
--- builtin/commit.c | 31 +++++++++++++++++++++++++------ dir.c | 24 ++++++++++++++++++++++++ dir.h | 3 ++- wt-status.c | 11 ++++++++--- wt-status.h | 8 +++++++- 5 files changed, 66 insertions(+), 11 deletions(-)
builtin/commit.c +25 -6
@@ -118,7 +118,7 @@ static int edit_flag = -1; /* unspecified */static int quiet, verbose, no_verify, allow_empty, dry_run, renew_authorship;static int config_commit_verbose =-1 ;/* unspecified */ static int no_post_rewrite, allow_empty_message; -static char *untracked_files_arg, *force_date, *ignore_submodule_arg; +static char *untracked_files_arg, *force_date, *ignore_submodule_arg, *ignored_arg;static char *sign_commit;/*
@@ -139,7 +139,7 @@ static const char *cleanup_arg;static enum commit_whence whence;static int sequencer_in_use;static int use_editor =1 , include_status =1 ; -static int show_ignored_in_status, have_option_m; +static int have_option_m;static struct strbuf message =STRBUF_INIT ;static enum wt_status_format status_format =STATUS_FORMAT_UNSPECIFIED ;
@@ -1075,6 +1075,19 @@ static const char *find_author_by_nickname(const char *name)die (_ ("--author '%s' is not 'Name <email>' and matches no existing author" ), name); } +static void handle_ignored_arg (struct wt_status *s) +{ +if (!ignored_arg) + ;/* default already initialized */ +else if (!strcmp (ignored_arg,"traditional" )) + s->show_ignored_mode =SHOW_TRADITIONAL_IGNORED ; +else if (!strcmp (ignored_arg,"no" )) + s->show_ignored_mode =SHOW_NO_IGNORED ; +else if (!strcmp (ignored_arg,"matching" )) + s->show_ignored_mode =SHOW_MATCHING_IGNORED ; +else +die (_ ("Invalid ignored mode '%s'" ), ignored_arg); +}static void handle_untracked_files_arg (struct wt_status *s) {
@@ -1363,8 +1376,10 @@ int cmd_status(int argc, const char **argv, const char *prefix)N_ ("mode" ),N_ ("show untracked files, optional modes: all, normal, no. (Default: all)" ), PARSE_OPT_OPTARG, NULL, (intptr_t)"all" }, -OPT_BOOL (0 ,"ignored" , &show_ignored_in_status, -N_ ("show ignored files" )), + { OPTION_STRING, 0, "ignored", &ignored_arg, +N_ ("mode" ), +N_ ("show ignored files, optional modes: traditional, matching, no. (Default: traditional)" ), + PARSE_OPT_OPTARG, NULL, (intptr_t)"traditional" }, { OPTION_STRING, 0, "ignore-submodules", &ignore_submodule_arg, N_("when"),N_ ("ignore changes to submodules, optional when: all, dirty, untracked. (Default: all)" ), PARSE_OPT_OPTARG, NULL, (intptr_t)"all" },
@@ -1383,8 +1398,12 @@ int cmd_status(int argc, const char **argv, const char *prefix)finalize_deferred_config (&s);handle_untracked_files_arg (&s); -if (show_ignored_in_status) - s.show_ignored_files =1 ; +handle_ignored_arg (&s); + +if (s.show_ignored_mode ==SHOW_MATCHING_IGNORED && + s.show_untracked_files ==SHOW_NO_UNTRACKED_FILES ) +die (_ ("Unsupported combination of ignored and untracked-files arguments" )); +parse_pathspec (&s.pathspec,0 ,PATHSPEC_PREFER_FULL , prefix, argv);
dir.c +24 -0
@@ -1389,6 +1389,30 @@ static enum path_treatment treat_directory(struct dir_struct *dir,case index_nonexistent:if (dir->flags &DIR_SHOW_OTHER_DIRECTORIES )break ; +if (exclude && + (dir->flags &DIR_SHOW_IGNORED_TOO ) && + (dir->flags &DIR_SHOW_IGNORED_TOO_MODE_MATCHING )) { + +/* +* This is an excluded directory and we are +* showing ignored paths that match an exclude +* pattern. (e.g. show directory as ignored +* only if it matches an exclude pattern). +* This path will either be 'path_excluded` +* (if we are showing empty directories or if +* the directory is not empty), or will be +* 'path_none' (empty directory, and we are +* not showing empty directories). +*/ +if (!(dir->flags &DIR_HIDE_EMPTY_DIRECTORIES )) +return path_excluded; + +if (read_directory_recursive (dir, istate, dirname, len, + untracked,1 ,1 , pathspec) == path_excluded) +return path_excluded; + +return path_none; + }if (!(dir->flags &DIR_NO_GITLINKS )) {unsigned char sha1[20 ];if (resolve_gitlink_ref (dirname,"HEAD" , sha1) ==0 )
dir.h +2 -1
@@ -152,7 +152,8 @@ struct dir_struct {DIR_COLLECT_IGNORED =1 <<4 ,DIR_SHOW_IGNORED_TOO =1 <<5 ,DIR_COLLECT_KILLED_ONLY =1 <<6 , - DIR_KEEP_UNTRACKED_CONTENTS = 1<<7 +DIR_KEEP_UNTRACKED_CONTENTS =1 <<7 , + DIR_SHOW_IGNORED_TOO_MODE_MATCHING = 1<<8 } flags;struct dir_entry **entries;struct dir_entry **ignored;
wt-status.c +8 -3
@@ -660,10 +660,15 @@ static void wt_status_collect_untracked(struct wt_status *s)if (s->show_untracked_files !=SHOW_ALL_UNTRACKED_FILES ) dir.flags |=DIR_SHOW_OTHER_DIRECTORIES |DIR_HIDE_EMPTY_DIRECTORIES ; -if (s->show_ignored_files) +if (s->show_ignored_mode) { dir.flags |=DIR_SHOW_IGNORED_TOO ; -else + +if (s->show_ignored_mode ==SHOW_MATCHING_IGNORED ) + dir.flags |=DIR_SHOW_IGNORED_TOO_MODE_MATCHING ; + }else { dir.untracked = the_index.untracked; + } +setup_standard_excludes (&dir);fill_directory (&dir, &the_index, &s->pathspec);
@@ -1621,7 +1626,7 @@ static void wt_longstatus_print(struct wt_status *s) }if (s->show_untracked_files) {wt_longstatus_print_other (s, &s->untracked,_ ("Untracked files" ),"add" ); -if (s->show_ignored_files) +if (s->show_ignored_mode)wt_longstatus_print_other (s, &s->ignored,_ ("Ignored files" ),"add -f" );if (advice_status_u_option &&2000 < s->untracked_in_ms) {status_printf_ln (s,GIT_COLOR_NORMAL ,"%s" ,"" );
wt-status.h +7 -1
@@ -27,6 +27,12 @@ enum untracked_status_type {SHOW_ALL_UNTRACKED_FILES }; +enum show_ignored_type { +SHOW_NO_IGNORED , +SHOW_TRADITIONAL_IGNORED , +SHOW_MATCHING_IGNORED , +}; +/* from where does this commit originate */ enum commit_whence {FROM_COMMIT ,/* normal */
@@ -70,7 +76,7 @@ struct wt_status {int display_comment_prefix;int relative_paths;int submodule_summary; -int show_ignored_files; +enum show_ignored_type show_ignored_mode;enum untracked_status_type show_untracked_files;const char *ignore_submodule_arg;char color_palette[WT_STATUS_MAXSLOT ][COLOR_MAXLEN ];
Signature · 1 line
2.13.6
Re: [PATCH v2 1/5] Teach status options around showing ignored files
Quoted 9 lines · Jameson Miller
This change teaches the status command more options to control which ignored files are reported independently of the which untracked files are reported by allowing the
--ignoredoption to take additional arguments. Currently, the shown ignored files are linked to how untracked files are reported. Both ignored and untracked files are controlled by arguments to--untracked-filesoption. This makes it impossible to show all untracked files individually, but show ignored "files and directories" (that is, ignored directories are shown as 1 entry, instead of having all contents shown).
The description makes sense. And it makes sense to show a directory known to contain only ignored paths as just one entry, instead of exploding that to individual files.
Quoted 2 lines
Our application (Visual Studio) has a specific set of requirements about how it wants untracked / ignored files reported by git status.
This sentence does not read well. VS has no obligation to read from "git status", so there is no "specific set of requirements" that make us care. If the output from "status" is insufficient you could be reading from "ls-files --ignored", for example, if you want more details than "git status" gives you.
The sentence, and the paragraph that immediately follows it, need a serious attitude adjustment ;-), even though it is good as read as an explanation of what the proposed output wants to show.
Quoted 7 lines
The reason for controlling these behaviors separately is that there can be a significant performance impact to scanning the contents of excluded directories. Additionally, knowing whether a directory explicitly matches an exclude pattern can help the application make decisions about how to handle the directory. If an ignored directory itself matches an exclude pattern, then the application will know that any files underneath the directory must be ignored as well.
While the above description taken standalone makes sense, doesn't the "we want all paths listed, without abbreviated to the directory and requiring the reader to infer from the fact that aidrectory is shown that everything in it are ignored" the log message stated earlier contradict another change you earlier sent, that avoids scanning a directory that is known to be completely untracked (i.e. no path under it in the index) and return early once an untracked file is found in it?
Quoted 185 lines
Signed-off-by Jameson Miller <[email protected]>--- builtin/commit.c | 31 +++++++++++++++++++++++++------ dir.c | 24 ++++++++++++++++++++++++ dir.h | 3 ++- wt-status.c | 11 ++++++++--- wt-status.h | 8 +++++++- 5 files changed, 66 insertions(+), 11 deletions(-)builtin/commit.c +25
-6@@ -118,7 +118,7 @@ static int edit_flag = -1; /* unspecified */static int quiet, verbose, no_verify, allow_empty, dry_run, renew_authorship;static int config_commit_verbose =-1 ;/* unspecified */ static int no_post_rewrite, allow_empty_message; -static char *untracked_files_arg, *force_date, *ignore_submodule_arg; +static char *untracked_files_arg, *force_date, *ignore_submodule_arg, *ignored_arg;static char *sign_commit;/* @@ -139,7 +139,7 @@ static const char *cleanup_arg;static enum commit_whence whence;static int sequencer_in_use;static int use_editor =1 , include_status =1 ; -static int show_ignored_in_status, have_option_m; +static int have_option_m;static struct strbuf message =STRBUF_INIT ;static enum wt_status_format status_format =STATUS_FORMAT_UNSPECIFIED ;@@ -1075,6 +1075,19 @@ static const char *find_author_by_nickname(const char *name)die (_ ("--author '%s' is not 'Name <email>' and matches no existing author" ), name); } +static void handle_ignored_arg (struct wt_status *s) +{ +if (!ignored_arg) + ;/* default already initialized */ +else if (!strcmp (ignored_arg,"traditional" )) + s->show_ignored_mode =SHOW_TRADITIONAL_IGNORED ; +else if (!strcmp (ignored_arg,"no" )) + s->show_ignored_mode =SHOW_NO_IGNORED ; +else if (!strcmp (ignored_arg,"matching" )) + s->show_ignored_mode =SHOW_MATCHING_IGNORED ; +else +die (_ ("Invalid ignored mode '%s'" ), ignored_arg); +}static void handle_untracked_files_arg (struct wt_status *s) {@@ -1363,8 +1376,10 @@ int cmd_status(int argc, const char **argv, const char *prefix)N_ ("mode" ),N_ ("show untracked files, optional modes: all, normal, no. (Default: all)" ), PARSE_OPT_OPTARG, NULL, (intptr_t)"all" }, -OPT_BOOL (0 ,"ignored" , &show_ignored_in_status, -N_ ("show ignored files" )), + { OPTION_STRING, 0, "ignored", &ignored_arg, +N_ ("mode" ), +N_ ("show ignored files, optional modes: traditional, matching, no. (Default: traditional)" ), + PARSE_OPT_OPTARG, NULL, (intptr_t)"traditional" }, { OPTION_STRING, 0, "ignore-submodules", &ignore_submodule_arg, N_("when"),N_ ("ignore changes to submodules, optional when: all, dirty, untracked. (Default: all)" ), PARSE_OPT_OPTARG, NULL, (intptr_t)"all" },@@ -1383,8 +1398,12 @@ int cmd_status(int argc, const char **argv, const char *prefix)finalize_deferred_config (&s);handle_untracked_files_arg (&s); -if (show_ignored_in_status) - s.show_ignored_files =1 ; +handle_ignored_arg (&s); + +if (s.show_ignored_mode ==SHOW_MATCHING_IGNORED && + s.show_untracked_files ==SHOW_NO_UNTRACKED_FILES ) +die (_ ("Unsupported combination of ignored and untracked-files arguments" )); +parse_pathspec (&s.pathspec,0 ,PATHSPEC_PREFER_FULL , prefix, argv);dir.c +24
-0@@ -1389,6 +1389,30 @@ static enum path_treatment treat_directory(struct dir_struct *dir,case index_nonexistent:if (dir->flags &DIR_SHOW_OTHER_DIRECTORIES )break ; +if (exclude && + (dir->flags &DIR_SHOW_IGNORED_TOO ) && + (dir->flags &DIR_SHOW_IGNORED_TOO_MODE_MATCHING )) { + +/* +* This is an excluded directory and we are +* showing ignored paths that match an exclude +* pattern. (e.g. show directory as ignored +* only if it matches an exclude pattern). +* This path will either be 'path_excluded` +* (if we are showing empty directories or if +* the directory is not empty), or will be +* 'path_none' (empty directory, and we are +* not showing empty directories). +*/ +if (!(dir->flags &DIR_HIDE_EMPTY_DIRECTORIES )) +return path_excluded; + +if (read_directory_recursive (dir, istate, dirname, len, + untracked,1 ,1 , pathspec) == path_excluded) +return path_excluded; + +return path_none; + }if (!(dir->flags &DIR_NO_GITLINKS )) {unsigned char sha1[20 ];if (resolve_gitlink_ref (dirname,"HEAD" , sha1) ==0 )dir.h +2
-1@@ -152,7 +152,8 @@ struct dir_struct {DIR_COLLECT_IGNORED =1 <<4 ,DIR_SHOW_IGNORED_TOO =1 <<5 ,DIR_COLLECT_KILLED_ONLY =1 <<6 , - DIR_KEEP_UNTRACKED_CONTENTS = 1<<7 +DIR_KEEP_UNTRACKED_CONTENTS =1 <<7 , + DIR_SHOW_IGNORED_TOO_MODE_MATCHING = 1<<8 } flags;struct dir_entry **entries;struct dir_entry **ignored;wt-status.c +8
-3@@ -660,10 +660,15 @@ static void wt_status_collect_untracked(struct wt_status *s)if (s->show_untracked_files !=SHOW_ALL_UNTRACKED_FILES ) dir.flags |=DIR_SHOW_OTHER_DIRECTORIES |DIR_HIDE_EMPTY_DIRECTORIES ; -if (s->show_ignored_files) +if (s->show_ignored_mode) { dir.flags |=DIR_SHOW_IGNORED_TOO ; -else + +if (s->show_ignored_mode ==SHOW_MATCHING_IGNORED ) + dir.flags |=DIR_SHOW_IGNORED_TOO_MODE_MATCHING ; + }else { dir.untracked = the_index.untracked; + } +setup_standard_excludes (&dir);fill_directory (&dir, &the_index, &s->pathspec);@@ -1621,7 +1626,7 @@ static void wt_longstatus_print(struct wt_status *s) }if (s->show_untracked_files) {wt_longstatus_print_other (s, &s->untracked,_ ("Untracked files" ),"add" ); -if (s->show_ignored_files) +if (s->show_ignored_mode)wt_longstatus_print_other (s, &s->ignored,_ ("Ignored files" ),"add -f" );if (advice_status_u_option &&2000 < s->untracked_in_ms) {status_printf_ln (s,GIT_COLOR_NORMAL ,"%s" ,"" );wt-status.h +7
-1@@ -27,6 +27,12 @@ enum untracked_status_type {SHOW_ALL_UNTRACKED_FILES }; +enum show_ignored_type { +SHOW_NO_IGNORED , +SHOW_TRADITIONAL_IGNORED , +SHOW_MATCHING_IGNORED , +}; +/* from where does this commit originate */ enum commit_whence {FROM_COMMIT ,/* normal */ @@ -70,7 +76,7 @@ struct wt_status {int display_comment_prefix;int relative_paths;int submodule_summary; -int show_ignored_files; +enum show_ignored_type show_ignored_mode;enum untracked_status_type show_untracked_files;const char *ignore_submodule_arg;char color_palette[WT_STATUS_MAXSLOT ][COLOR_MAXLEN ];
Re: [PATCH v2 1/5] Teach status options around showing ignored files
Quoted 23 lines · Junio C Hamano
Quoted 9 lines · Jameson Miller
This change teaches the status command more options to control which ignored files are reported independently of the which untracked files are reported by allowing the
--ignoredoption to take additional arguments. Currently, the shown ignored files are linked to how untracked files are reported. Both ignored and untracked files are controlled by arguments to--untracked-filesoption. This makes it impossible to show all untracked files individually, but show ignored "files and directories" (that is, ignored directories are shown as 1 entry, instead of having all contents shown).The description makes sense. And it makes sense to show a directory known to contain only ignored paths as just one entry, instead of exploding that to individual files.
Quoted 2 lines
Our application (Visual Studio) has a specific set of requirements about how it wants untracked / ignored files reported by git status.
This sentence does not read well. VS has no obligation to read from "git status", so there is no "specific set of requirements" that make us care. If the output from "status" is insufficient you could be reading from "ls-files --ignored", for example, if you want more details than "git status" gives you.
Quoted 3 lines
The sentence, and the paragraph that immediately follows it, need a serious attitude adjustment ;-), even though it is good as read as an explanation of what the proposed output wants to show.
It was not my intention to have this paragraph come across this way. I meant to express the ideal format of data that our application would like (from whatever source) as motivation for why we are proposing these changes. I will reword this paragraph to remove any unintended implication otherwise.
Quoted 7 lines
Quoted 7 lines
The reason for controlling these behaviors separately is that there can be a significant performance impact to scanning the contents of excluded directories. Additionally, knowing whether a directory explicitly matches an exclude pattern can help the application make decisions about how to handle the directory. If an ignored directory itself matches an exclude pattern, then the application will know that any files underneath the directory must be ignored as well.
Quoted 8 lines
While the above description taken standalone makes sense, doesn't the "we want all paths listed, without abbreviated to the directory and requiring the reader to infer from the fact that aidrectory is shown that everything in it are ignored" the log message stated earlier contradict another change you earlier sent, that avoids scanning a directory that is known to be completely untracked (i.e. no path under it in the index) and return early once an untracked file is found in it?
My first set of changes introduced a perf optimization without any functional changes. The perf optimization was to avoid scanning a directory that is known to be ignored (i.e no path under it in the index and the directory matches an exclude pattern). It returns early once any file is found in it. Any file found must be ignored, as it is contained in an ignored directory.
This second set of changes is to allow optional decoupling of how ignored and untracked items are reported.
Quoted 186 lines
Quoted 186 lines
Signed-off-by Jameson Miller <[email protected]>--- builtin/commit.c | 31 +++++++++++++++++++++++++------ dir.c | 24 ++++++++++++++++++++++++ dir.h | 3 ++- wt-status.c | 11 ++++++++--- wt-status.h | 8 +++++++- 5 files changed, 66 insertions(+), 11 deletions(-)builtin/commit.c +25
-6@@ -118,7 +118,7 @@ static int edit_flag = -1; /* unspecified */static int quiet, verbose, no_verify, allow_empty, dry_run, renew_authorship;static int config_commit_verbose =-1 ;/* unspecified */ static int no_post_rewrite, allow_empty_message; -static char *untracked_files_arg, *force_date, *ignore_submodule_arg; +static char *untracked_files_arg, *force_date, *ignore_submodule_arg, *ignored_arg;static char *sign_commit;/* @@ -139,7 +139,7 @@ static const char *cleanup_arg;static enum commit_whence whence;static int sequencer_in_use;static int use_editor =1 , include_status =1 ; -static int show_ignored_in_status, have_option_m; +static int have_option_m;static struct strbuf message =STRBUF_INIT ;static enum wt_status_format status_format =STATUS_FORMAT_UNSPECIFIED ;@@ -1075,6 +1075,19 @@ static const char *find_author_by_nickname(const char *name)die (_ ("--author '%s' is not 'Name <email>' and matches no existing author" ), name); } +static void handle_ignored_arg (struct wt_status *s) +{ +if (!ignored_arg) + ;/* default already initialized */ +else if (!strcmp (ignored_arg,"traditional" )) + s->show_ignored_mode =SHOW_TRADITIONAL_IGNORED ; +else if (!strcmp (ignored_arg,"no" )) + s->show_ignored_mode =SHOW_NO_IGNORED ; +else if (!strcmp (ignored_arg,"matching" )) + s->show_ignored_mode =SHOW_MATCHING_IGNORED ; +else +die (_ ("Invalid ignored mode '%s'" ), ignored_arg); +}static void handle_untracked_files_arg (struct wt_status *s) {@@ -1363,8 +1376,10 @@ int cmd_status(int argc, const char **argv, const char *prefix)N_ ("mode" ),N_ ("show untracked files, optional modes: all, normal, no. (Default: all)" ), PARSE_OPT_OPTARG, NULL, (intptr_t)"all" }, -OPT_BOOL (0 ,"ignored" , &show_ignored_in_status, -N_ ("show ignored files" )), + { OPTION_STRING, 0, "ignored", &ignored_arg, +N_ ("mode" ), +N_ ("show ignored files, optional modes: traditional, matching, no. (Default: traditional)" ), + PARSE_OPT_OPTARG, NULL, (intptr_t)"traditional" }, { OPTION_STRING, 0, "ignore-submodules", &ignore_submodule_arg, N_("when"),N_ ("ignore changes to submodules, optional when: all, dirty, untracked. (Default: all)" ), PARSE_OPT_OPTARG, NULL, (intptr_t)"all" },@@ -1383,8 +1398,12 @@ int cmd_status(int argc, const char **argv, const char *prefix)finalize_deferred_config (&s);handle_untracked_files_arg (&s); -if (show_ignored_in_status) - s.show_ignored_files =1 ; +handle_ignored_arg (&s); + +if (s.show_ignored_mode ==SHOW_MATCHING_IGNORED && + s.show_untracked_files ==SHOW_NO_UNTRACKED_FILES ) +die (_ ("Unsupported combination of ignored and untracked-files arguments" )); +parse_pathspec (&s.pathspec,0 ,PATHSPEC_PREFER_FULL , prefix, argv);dir.c +24
-0@@ -1389,6 +1389,30 @@ static enum path_treatment treat_directory(struct dir_struct *dir,case index_nonexistent:if (dir->flags &DIR_SHOW_OTHER_DIRECTORIES )break ; +if (exclude && + (dir->flags &DIR_SHOW_IGNORED_TOO ) && + (dir->flags &DIR_SHOW_IGNORED_TOO_MODE_MATCHING )) { + +/* +* This is an excluded directory and we are +* showing ignored paths that match an exclude +* pattern. (e.g. show directory as ignored +* only if it matches an exclude pattern). +* This path will either be 'path_excluded` +* (if we are showing empty directories or if +* the directory is not empty), or will be +* 'path_none' (empty directory, and we are +* not showing empty directories). +*/ +if (!(dir->flags &DIR_HIDE_EMPTY_DIRECTORIES )) +return path_excluded; + +if (read_directory_recursive (dir, istate, dirname, len, + untracked,1 ,1 , pathspec) == path_excluded) +return path_excluded; + +return path_none; + }if (!(dir->flags &DIR_NO_GITLINKS )) {unsigned char sha1[20 ];if (resolve_gitlink_ref (dirname,"HEAD" , sha1) ==0 )dir.h +2
-1@@ -152,7 +152,8 @@ struct dir_struct {DIR_COLLECT_IGNORED =1 <<4 ,DIR_SHOW_IGNORED_TOO =1 <<5 ,DIR_COLLECT_KILLED_ONLY =1 <<6 , - DIR_KEEP_UNTRACKED_CONTENTS = 1<<7 +DIR_KEEP_UNTRACKED_CONTENTS =1 <<7 , + DIR_SHOW_IGNORED_TOO_MODE_MATCHING = 1<<8 } flags;struct dir_entry **entries;struct dir_entry **ignored;wt-status.c +8
-3@@ -660,10 +660,15 @@ static void wt_status_collect_untracked(struct wt_status *s)if (s->show_untracked_files !=SHOW_ALL_UNTRACKED_FILES ) dir.flags |=DIR_SHOW_OTHER_DIRECTORIES |DIR_HIDE_EMPTY_DIRECTORIES ; -if (s->show_ignored_files) +if (s->show_ignored_mode) { dir.flags |=DIR_SHOW_IGNORED_TOO ; -else + +if (s->show_ignored_mode ==SHOW_MATCHING_IGNORED ) + dir.flags |=DIR_SHOW_IGNORED_TOO_MODE_MATCHING ; + }else { dir.untracked = the_index.untracked; + } +setup_standard_excludes (&dir);fill_directory (&dir, &the_index, &s->pathspec);@@ -1621,7 +1626,7 @@ static void wt_longstatus_print(struct wt_status *s) }if (s->show_untracked_files) {wt_longstatus_print_other (s, &s->untracked,_ ("Untracked files" ),"add" ); -if (s->show_ignored_files) +if (s->show_ignored_mode)wt_longstatus_print_other (s, &s->ignored,_ ("Ignored files" ),"add -f" );if (advice_status_u_option &&2000 < s->untracked_in_ms) {status_printf_ln (s,GIT_COLOR_NORMAL ,"%s" ,"" );wt-status.h +7
-1@@ -27,6 +27,12 @@ enum untracked_status_type {SHOW_ALL_UNTRACKED_FILES }; +enum show_ignored_type { +SHOW_NO_IGNORED , +SHOW_TRADITIONAL_IGNORED , +SHOW_MATCHING_IGNORED , +}; +/* from where does this commit originate */ enum commit_whence {FROM_COMMIT ,/* normal */ @@ -70,7 +76,7 @@ struct wt_status {int display_comment_prefix;int relative_paths;int submodule_summary; -int show_ignored_files; +enum show_ignored_type show_ignored_mode;enum untracked_status_type show_untracked_files;const char *ignore_submodule_arg;char color_palette[WT_STATUS_MAXSLOT ][COLOR_MAXLEN ];
PATCH v2 2/5 Update documentation for new directory and status logic
In reply to Jameson Miller--- Documentation/git-status.txt | 21 +++++++++++++++++- Documentation/technical/api-directory-listing.txt | 27 +++++++++++++++++++---- 2 files changed, 43 insertions(+), 5 deletions(-)
Documentation/git-status.txt +20 -1
@@ -97,8 +97,27 @@ configuration variable documented in linkgit:git-config[1]. (and suppresses the output of submodule summaries when the config option `status.submoduleSummary` is set). ---ignored:: +--ignored[=<mode>]:: Show ignored files as well. ++ +The mode parameter is used to specify the handling of ignored files. +It is optional: it defaults to 'traditional'. ++ +The possible options are: ++ + - 'traditional' - Shows ignored files and directories, unless + --untracked-files=all is specifed, in which case + individual files in ignored directories are + displayed. + - 'no' - Show no ignored files. + - 'matching' - Shows ignored files and directories matching an + ignore pattern. ++ +When 'matching' mode is specified, paths that explicity match an +ignored pattern are shown. If a directory matches an ignore pattern, +then it is shown, but not paths contained in the ignored directory. If +a directory does not match an ignore pattern, but all contents are +ignored, then the directory is not shown, but all contents are shown. -z:: Terminate entries with NUL, instead of LF. This implies
Documentation/technical/api-directory-listing.txt +23 -4
@@ -22,16 +22,20 @@ The notable options are: `flags`:: - A bit-field of options (the `*IGNORED*` flags are mutually exclusive): + A bit-field of options: `DIR_SHOW_IGNORED`::: - Return just ignored files in `entries[]`, not untracked files. + Return just ignored files in `entries[]`, not untracked + files. This flag is mutually exclusive with + `DIR_SHOW_IGNORED_TOO`. `DIR_SHOW_IGNORED_TOO`::: - Similar to `DIR_SHOW_IGNORED`, but return ignored files in `ignored[]` - in addition to untracked files in `entries[]`. + Similar to `DIR_SHOW_IGNORED`, but return ignored files in + `ignored[]` in addition to untracked files in + `entries[]`. This flag is mutually exclusive with + `DIR_SHOW_IGNORED`. `DIR_KEEP_UNTRACKED_CONTENTS`:::
@@ -39,6 +43,21 @@ The notable options are: untracked contents of untracked directories are also returned in `entries[]`. +`DIR_SHOW_IGNORED_TOO_MODE_MATCHING`::: + + Only has meaning if `DIR_SHOW_IGNORED_TOO` is also set; if + this is set, returns ignored files and directories that match + an exclude pattern. If a directory matches an exclude pattern, + then the directory is returned and the contained paths are + not. A directory that does not match an exclude pattern will + not be returned even if all of its contents are ignored. In + this case, the contents are returned as individual entries. ++ +If this is set, files and directories that explicity match an ignore +pattern are reported. Implicity ignored directories (directories that +do not match an ignore pattern, but whose contents are all ignored) +are not reported, instead all of the contents are reported. + `DIR_COLLECT_IGNORED`::: Special mode for git-add. Return ignored files in `ignored[]` and
Signature · 1 line
2.13.6
Re: [PATCH v2 2/5] Update documentation for new directory and status logic
Quoted 26 lines · Jameson Miller
Signed-off-by Jameson Miller <[email protected]>--- Documentation/git-status.txt | 21 +++++++++++++++++- Documentation/technical/api-directory-listing.txt | 27 +++++++++++++++++++---- 2 files changed, 43 insertions(+), 5 deletions(-)Documentation/git-status.txt +10
-1@@ -97,8 +97,27 @@ configuration variable documented in linkgit:git-config[1]. (and suppresses the output of submodule summaries when the config option `status.submoduleSummary` is set). ---ignored:: +--ignored[=<mode>]:: Show ignored files as well. ++ +The mode parameter is used to specify the handling of ignored files. +It is optional: it defaults to 'traditional'. ++ +The possible options are: ++ + - 'traditional' - Shows ignored files and directories, unless + --untracked-files=all is specifed, in which case + individual files in ignored directories are
Documentation/git-status.txt configuration variable documented in linkgit:git-config[1]. · line 120
Quoted 10 lines
Documentation/git-status.txt +10
-0+ displayed. + - 'no' - Show no ignored files. + - 'matching' - Shows ignored files and directories matching an + ignore pattern. ++ +When 'matching' mode is specified, paths that explicity match an +ignored pattern are shown. If a directory matches an ignore pattern, +then it is shown, but not paths contained in the ignored directory. If +a directory does not match an ignore pattern, but all contents are +ignored, then the directory is not shown, but all contents are shown.
Well explained.
Quoted 37 lines
Documentation/technical/api-directory-listing.txt +12
-4@@ -22,16 +22,20 @@ The notable options are: `flags`:: - A bit-field of options (the `*IGNORED*` flags are mutually exclusive): + A bit-field of options: `DIR_SHOW_IGNORED`::: - Return just ignored files in `entries[]`, not untracked files. + Return just ignored files in `entries[]`, not untracked + files. This flag is mutually exclusive with + `DIR_SHOW_IGNORED_TOO`. `DIR_SHOW_IGNORED_TOO`::: - Similar to `DIR_SHOW_IGNORED`, but return ignored files in `ignored[]` - in addition to untracked files in `entries[]`. + Similar to `DIR_SHOW_IGNORED`, but return ignored files in + `ignored[]` in addition to untracked files in + `entries[]`. This flag is mutually exclusive with + `DIR_SHOW_IGNORED`. `DIR_KEEP_UNTRACKED_CONTENTS`:::@@ -39,6 +43,21 @@ The notable options are: untracked contents of untracked directories are also returned in `entries[]`. +`DIR_SHOW_IGNORED_TOO_MODE_MATCHING`::: + + Only has meaning if `DIR_SHOW_IGNORED_TOO` is also set; if + this is set, returns ignored files and directories that match
Documentation/technical/api-directory-listing.txt The notable options are: · line 59
Quoted 10 lines
Documentation/technical/api-directory-listing.txt +10
-0+ an exclude pattern. If a directory matches an exclude pattern, + then the directory is returned and the contained paths are + not. A directory that does not match an exclude pattern will + not be returned even if all of its contents are ignored. In + this case, the contents are returned as individual entries. ++ +If this is set, files and directories that explicity match an ignore +pattern are reported. Implicity ignored directories (directories that +do not match an ignore pattern, but whose contents are all ignored) +are not reported, instead all of the contents are reported.
Makes me wonder if DIR_SHOW_IGNORED* should be splt out into a short enum. We have:
- Do not show ignored ones (0)
- Collect ignored ones (DIR_SHOW_IGNORED)
- Collect ignored and untracked ones separately (DIR_SHOW_IGNORED_TOO)
- Collect ignored and duntracked ones separately, but limit them to those mach exclude patterns explicitly (DIR_SHOW_IGNORED_TOO|...MODE_MATCHING)
so we need two bits to fit a 4-possiblity enum.
Then we do not have to worry about saying quirky things like A and B are incompatible, and C makes sense only when B is set, etc.
Quoted 3 lines
Documentation/technical/api-directory-listing.txt +0
-0`DIR_COLLECT_IGNORED`::: Special mode for git-add. Return ignored files in `ignored[]` and
Re: [PATCH v2 2/5] Update documentation for new directory and status logic
Quoted 96 lines · Junio C Hamano
Quoted 26 lines · Jameson Miller
Signed-off-by Jameson Miller <[email protected]>--- Documentation/git-status.txt | 21 +++++++++++++++++- Documentation/technical/api-directory-listing.txt | 27 +++++++++++++++++++---- 2 files changed, 43 insertions(+), 5 deletions(-)Documentation/git-status.txt +10
-1@@ -97,8 +97,27 @@ configuration variable documented in linkgit:git-config[1]. (and suppresses the output of submodule summaries when the config option `status.submoduleSummary` is set). ---ignored:: +--ignored[=<mode>]:: Show ignored files as well. ++ +The mode parameter is used to specify the handling of ignored files. +It is optional: it defaults to 'traditional'. ++ +The possible options are: ++ + - 'traditional' - Shows ignored files and directories, unless + --untracked-files=all is specifed, in which case + individual files in ignored directories areDocumentation/git-status.txt configuration variable documented in linkgit:git-config[1]. · line 120
Quoted 10 lines
Documentation/git-status.txt +10
-0+ displayed. + - 'no' - Show no ignored files. + - 'matching' - Shows ignored files and directories matching an + ignore pattern. ++ +When 'matching' mode is specified, paths that explicity match an +ignored pattern are shown. If a directory matches an ignore pattern, +then it is shown, but not paths contained in the ignored directory. If +a directory does not match an ignore pattern, but all contents are +ignored, then the directory is not shown, but all contents are shown.Well explained.
Quoted 37 lines
Documentation/technical/api-directory-listing.txt +12
-4@@ -22,16 +22,20 @@ The notable options are: `flags`:: - A bit-field of options (the `*IGNORED*` flags are mutually exclusive): + A bit-field of options: `DIR_SHOW_IGNORED`::: - Return just ignored files in `entries[]`, not untracked files. + Return just ignored files in `entries[]`, not untracked + files. This flag is mutually exclusive with + `DIR_SHOW_IGNORED_TOO`. `DIR_SHOW_IGNORED_TOO`::: - Similar to `DIR_SHOW_IGNORED`, but return ignored files in `ignored[]` - in addition to untracked files in `entries[]`. + Similar to `DIR_SHOW_IGNORED`, but return ignored files in + `ignored[]` in addition to untracked files in + `entries[]`. This flag is mutually exclusive with + `DIR_SHOW_IGNORED`. `DIR_KEEP_UNTRACKED_CONTENTS`:::@@ -39,6 +43,21 @@ The notable options are: untracked contents of untracked directories are also returned in `entries[]`. +`DIR_SHOW_IGNORED_TOO_MODE_MATCHING`::: + + Only has meaning if `DIR_SHOW_IGNORED_TOO` is also set; if + this is set, returns ignored files and directories that matchDocumentation/technical/api-directory-listing.txt The notable options are: · line 59
Quoted 10 lines
Documentation/technical/api-directory-listing.txt +10
-0+ an exclude pattern. If a directory matches an exclude pattern, + then the directory is returned and the contained paths are + not. A directory that does not match an exclude pattern will + not be returned even if all of its contents are ignored. In + this case, the contents are returned as individual entries. ++ +If this is set, files and directories that explicity match an ignore +pattern are reported. Implicity ignored directories (directories that +do not match an ignore pattern, but whose contents are all ignored) +are not reported, instead all of the contents are reported.Makes me wonder if DIR_SHOW_IGNORED* should be splt out into a short enum. We have:
- Do not show ignored ones (0)
- Collect ignored ones (
DIR_SHOW_IGNORED)- Collect ignored and untracked ones separately (
DIR_SHOW_IGNORED_TOO)
Quoted 7 lines
- Collect ignored and duntracked ones separately, but limit them to those mach exclude patterns explicitly (DIR_SHOW_IGNORED_TOO|...MODE_MATCHING)
so we need two bits to fit a 4-possiblity enum.
Then we do not have to worry about saying quirky things like A and B are incompatible, and C makes sense only when B is set, etc.
I could see a potential for other values for the "show ignored mode" flags - for example: "NORMAL", "MATCHING", "ALL"... Instead of making more change at this point in time, how would you feel about waiting until the next change in this area.
If you would prefer for me to change these enums now, I can do that.
Quoted 4 lines
Quoted 4 lines
Documentation/technical/api-directory-listing.txt +0
-0`DIR_COLLECT_IGNORED`::: Special mode for git-add. Return ignored files in `ignored[]` and
Re: [PATCH v2 2/5] Update documentation for new directory and status logic
Quoted 20 lines · Jameson Miller
Quoted 13 lines
Documentation/technical/api-directory-listing.txt The notable options are: · line 59
Quoted 4 lines
Documentation/technical/api-directory-listing.txt +4
-0+If this is set, files and directories that explicity match an ignore +pattern are reported. Implicity ignored directories (directories that +do not match an ignore pattern, but whose contents are all ignored) +are not reported, instead all of the contents are reported.Makes me wonder if DIR_SHOW_IGNORED* should be splt out into a short enum. We have:
- Do not show ignored ones (0)
- Collect ignored ones (
DIR_SHOW_IGNORED)- Collect ignored and untracked ones separately (
DIR_SHOW_IGNORED_TOO)Quoted 7 lines
- Collect ignored and duntracked ones separately, but limit them to those mach exclude patterns explicitly (DIR_SHOW_IGNORED_TOO|...MODE_MATCHING)
so we need two bits to fit a 4-possiblity enum.
Then we do not have to worry about saying quirky things like A and B are incompatible, and C makes sense only when B is set, etc.
Quoted 7 lines
I could see a potential for other values for the "show ignored mode" flags - for example: "NORMAL", "MATCHING", "ALL"... Instead of making more change at this point in time, how would you feel about waiting until the next change in this area.
If you would prefer for me to change these enums now, I can do that.
"Makes me wonder" was just that. I was made to wonder. I did not have strong opinions either way. You thought about the area of this code longer than I did, so I do not mind you picking the course of action that is best for the project, and if you think it is better to wait until we know more about the vocabulary we want to support before we restructure these flags, that is fine by me.
Thanks.
PATCH v2 3/5 Add tests for git status `--ignored=matching`
In reply to Jameson MillerAdd tests for new ignored mode (matching) when showing all untracked files.
--- t/t7519-ignored-mode.sh | 125 ++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 125 insertions(+) create mode 100755 t/t7519-ignored-mode.sh
t/t7519-ignored-mode.sh new file +125 -0
@@ -0,0 +1,125 @@ +#!/bin/sh + +test_description='git status collapse ignored' + +. ./test-lib.sh + +# commit initial ignore file +test_expect_success 'setup initial commit and ignore file' ' + cat >.gitignore <<-\EOF && + *.ign + ignored_dir/ + !*.unignore + EOF + git add . && + git commit -m "Initial commit" +' + +test_expect_success 'Verify behavior of status on folders with ignored files' ' + test_when_finished "git clean -fdx" && + cat >expect <<-\EOF && + ? expect + ? output + ! dir/ignored/ignored_1.ign + ! dir/ignored/ignored_2.ign + ! ignored/ignored_1.ign + ! ignored/ignored_2.ign + EOF + + mkdir -p ignored dir/ignored && + touch ignored/ignored_1.ign ignored/ignored_2.ign \ + dir/ignored/ignored_1.ign dir/ignored/ignored_2.ign && + + git status --porcelain=v2 --ignored=matching --untracked-files=all >output && + test_i18ncmp expect output +' + +test_expect_success 'Verify status behavior on folder with tracked & ignored files' ' + test_when_finished "git clean -fdx && git reset HEAD~1 --hard" && + cat >expect <<-\EOF && + ? expect + ? output + ! dir/tracked_ignored/ignored_1.ign + ! dir/tracked_ignored/ignored_2.ign + ! tracked_ignored/ignored_1.ign + ! tracked_ignored/ignored_2.ign + EOF + + mkdir -p tracked_ignored dir/tracked_ignored && + touch tracked_ignored/tracked_1 tracked_ignored/tracked_2 \ + tracked_ignored/ignored_1.ign tracked_ignored/ignored_2.ign \ + dir/tracked_ignored/tracked_1 dir/tracked_ignored/tracked_2 \ + dir/tracked_ignored/ignored_1.ign dir/tracked_ignored/ignored_2.ign && + + git add tracked_ignored/tracked_1 tracked_ignored/tracked_2 \ + dir/tracked_ignored/tracked_1 dir/tracked_ignored/tracked_2 && + git commit -m "commit tracked files" && + + git status --porcelain=v2 --ignored=matching --untracked-files=all >output && + test_i18ncmp expect output +' + +test_expect_success 'Verify status behavior on folder with untracked and ignored files' ' + test_when_finished "git clean -fdx" && + cat >expect <<-\EOF && + ? dir/untracked_ignored/untracked_1 + ? dir/untracked_ignored/untracked_2 + ? expect + ? output + ? untracked_ignored/untracked_1 + ? untracked_ignored/untracked_2 + ! dir/untracked_ignored/ignored_1.ign + ! dir/untracked_ignored/ignored_2.ign + ! untracked_ignored/ignored_1.ign + ! untracked_ignored/ignored_2.ign + EOF + + mkdir -p untracked_ignored dir/untracked_ignored && + touch untracked_ignored/untracked_1 untracked_ignored/untracked_2 \ + untracked_ignored/ignored_1.ign untracked_ignored/ignored_2.ign \ + dir/untracked_ignored/untracked_1 dir/untracked_ignored/untracked_2 \ + dir/untracked_ignored/ignored_1.ign dir/untracked_ignored/ignored_2.ign && + + git status --porcelain=v2 --ignored=matching --untracked-files=all >output && + test_i18ncmp expect output +' + +test_expect_success 'Verify status matching ignored files on ignored folder' ' + test_when_finished "git clean -fdx" && + cat >expect <<-\EOF && + ? expect + ? output + ! ignored_dir/ + EOF + + mkdir ignored_dir && + touch ignored_dir/ignored_1 ignored_dir/ignored_2 \ + ignored_dir/ignored_1.ign ignored_dir/ignored_2.ign && + + git status --porcelain=v2 --ignored=matching --untracked-files=all >output && + test_i18ncmp expect output +' + +test_expect_success 'Verify status behavior on ignored folder containing tracked file' ' + test_when_finished "git clean -fdx && git reset HEAD~1 --hard" && + cat >expect <<-\EOF && + ? expect + ? output + ! ignored_dir/ignored_1 + ! ignored_dir/ignored_1.ign + ! ignored_dir/ignored_2 + ! ignored_dir/ignored_2.ign + EOF + + mkdir ignored_dir && + touch ignored_dir/ignored_1 ignored_dir/ignored_2 \ + ignored_dir/ignored_1.ign ignored_dir/ignored_2.ign \ + ignored_dir/tracked && + git add -f ignored_dir/tracked && + test_tick && + git commit -m "Force add file in ignored directory" && + git status --porcelain=v2 --ignored=matching --untracked-files=all >output && + test_i18ncmp expect output +' + +test_done
Signature · 1 line
2.13.6
PATCH v2 4/5 Expand support for ignored arguments on status
In reply to Jameson MillerTeach status command to handle matching ignored mode when showing untracked files with the normal option.
--- dir.c | 20 ++++++++++++++++++-- 1 file changed, 18 insertions(+), 2 deletions(-)
dir.c +18 -2
@@ -1585,6 +1585,7 @@ static enum path_treatment treat_one_path(struct dir_struct *dir, {int exclude;int has_path_in_index = !!index_file_exists (istate, path->buf, path->len, ignore_case); +enum path_treatment path_treatment;if (dtype ==DT_UNKNOWN ) dtype =get_dtype (de, istate, path->buf, path->len);
@@ -1631,8 +1632,23 @@ static enum path_treatment treat_one_path(struct dir_struct *dir,return path_none;case DT_DIR :strbuf_addch (path,'/' ); -return treat_directory (dir, istate, untracked, path->buf, path->len, - baselen, exclude, pathspec); + path_treatment =treat_directory (dir, istate, untracked, + path->buf, path->len, + baselen, exclude, pathspec); +/* +* If we are only want to return directories that +* match an exclude pattern, and this directories does +* not match an exclude pattern but all contents are +* excluded, then indicate that we should recurse into +* this directory (instead of marking the directory +* itself as an ignored path) +*/ +if (!exclude && + path_treatment == path_excluded && + (dir->flags &DIR_SHOW_IGNORED_TOO ) && + (dir->flags &DIR_SHOW_IGNORED_TOO_MODE_MATCHING )) +return path_recurse; +return path_treatment;case DT_REG :case DT_LNK :return exclude ? path_excluded : path_untracked;
Signature · 1 line
2.13.6
Re: [PATCH v2 4/5] Expand support for ignored arguments on status
Quoted 22 lines · Jameson Miller
Teach status command to handle matching ignored mode when showing untracked files with the normal option.
Signed-off-by Jameson Miller <[email protected]>--- dir.c | 20 ++++++++++++++++++-- 1 file changed, 18 insertions(+), 2 deletions(-)dir.c +1
-0@@ -1585,6 +1585,7 @@ static enum path_treatment treat_one_path(struct dir_struct *dir, {int exclude;int has_path_in_index = !!index_file_exists (istate, path->buf, path->len, ignore_case); +enum path_treatment path_treatment;if (dtype ==DT_UNKNOWN ) dtype =get_dtype (de, istate, path->buf, path->len);@@ -1631,8 +1632,23 @@ static enum path_treatment treat_one_path(struct dir_struct *dir,return path_none;
dir.c static enum path_treatment treat_one_path(struct dir_struct *dir, · line 1640
Quoted 10 lines
dir.c +6
-2case DT_DIR :strbuf_addch (path,'/' ); -return treat_directory (dir, istate, untracked, path->buf, path->len, - baselen, exclude, pathspec); + path_treatment =treat_directory (dir, istate, untracked, + path->buf, path->len, + baselen, exclude, pathspec); +/* +* If we are only want to return directories that +* match an exclude pattern, and this directories does
s/are //; s/directories/directory/
dir.c static enum path_treatment treat_one_path(struct dir_struct *dir, · line 1651
Quoted 11 lines
dir.c +11
-0+* not match an exclude pattern but all contents are +* excluded, then indicate that we should recurse into +* this directory (instead of marking the directory +* itself as an ignored path) +*/ +if (!exclude && + path_treatment == path_excluded && + (dir->flags &DIR_SHOW_IGNORED_TOO ) && + (dir->flags &DIR_SHOW_IGNORED_TOO_MODE_MATCHING )) +return path_recurse; +return path_treatment;
The required change to the code is surprisingly small ;-) and it is well explained in the comment. Good job.
Quoted 3 lines
dir.c +0
-0case DT_REG :case DT_LNK :return exclude ? path_excluded : path_untracked;
PATCH v2 5/5 Add tests around status handling of ignored arguments
In reply to Jameson MillerAdd tests for status handling of '--ignored=matching and --untracked-files=normal`.
--- t/t7519-ignored-mode.sh | 60 ++++++++++++++++++++++++++++++++++++++++++++++++- 1 file changed, 59 insertions(+), 1 deletion(-)
t/t7519-ignored-mode.sh +59 -1
@@ -116,10 +116,68 @@ test_expect_success 'Verify status behavior on ignored folder containing tracked ignored_dir/ignored_1.ign ignored_dir/ignored_2.ign \ ignored_dir/tracked && git add -f ignored_dir/tracked && - test_tick && git commit -m "Force add file in ignored directory" && git status --porcelain=v2 --ignored=matching --untracked-files=all >output && test_i18ncmp expect output ' +test_expect_success 'Verify matching ignored files with --untracked-files=normal' ' + test_when_finished "git clean -fdx" && + cat >expect <<-\EOF && + ? expect + ? output + ? untracked_dir/ + ! ignored_dir/ + ! ignored_files/ignored_1.ign + ! ignored_files/ignored_2.ign + EOF + + mkdir ignored_dir ignored_files untracked_dir && + touch ignored_dir/ignored_1 ignored_dir/ignored_2 \ + ignored_files/ignored_1.ign ignored_files/ignored_2.ign \ + untracked_dir/untracked && + git status --porcelain=v2 --ignored=matching --untracked-files=normal >output && + test_i18ncmp expect output +' + +test_expect_success 'Verify matching ignored files with --untracked-files=normal' ' + test_when_finished "git clean -fdx" && + cat >expect <<-\EOF && + ? expect + ? output + ? untracked_dir/ + ! ignored_dir/ + ! ignored_files/ignored_1.ign + ! ignored_files/ignored_2.ign + EOF + + mkdir ignored_dir ignored_files untracked_dir && + touch ignored_dir/ignored_1 ignored_dir/ignored_2 \ + ignored_files/ignored_1.ign ignored_files/ignored_2.ign \ + untracked_dir/untracked && + git status --porcelain=v2 --ignored=matching --untracked-files=normal >output && + test_i18ncmp expect output +' + +test_expect_success 'Verify status behavior on ignored folder containing tracked file' ' + test_when_finished "git clean -fdx && git reset HEAD~1 --hard" && + cat >expect <<-\EOF && + ? expect + ? output + ! ignored_dir/ignored_1 + ! ignored_dir/ignored_1.ign + ! ignored_dir/ignored_2 + ! ignored_dir/ignored_2.ign + EOF + + mkdir ignored_dir && + touch ignored_dir/ignored_1 ignored_dir/ignored_2 \ + ignored_dir/ignored_1.ign ignored_dir/ignored_2.ign \ + ignored_dir/tracked && + git add -f ignored_dir/tracked && + git commit -m "Force add file in ignored directory" && + git status --porcelain=v2 --ignored=matching --untracked-files=normal >output && + test_i18ncmp expect output +' + test_done
Signature · 1 line
2.13.6
Re: [PATCH v2 5/5] Add tests around status handling of ignored arguments
Quoted 5 lines · Jameson Miller
Add tests for status handling of '--ignored=matching
and--untracked-files=normal`.Signed-off-by Jameson Miller <[email protected]>---
Hmph, having some tests in 3/5, changes in 4/5 and even more tests in 5/5 makes me as a reader a bit confused, as the description for these two test patches does not make it clear how they are related and how they are different. Is it that changes in 1/5 alone does not fulfill the promise made by documentation added at 2/5 so 3/5 only has tests for behaviour that works with 1/5 alone but is broken with respect to what 2/5 claims until 4/5 is applied, and these "not working with 1/5 alone, but works after 4/5" are added in this step?
Quoted 77 lines
t/t7519-ignored-mode.sh | 60 ++++++++++++++++++++++++++++++++++++++++++++++++- 1 file changed, 59 insertions(+), 1 deletion(-)t/t7519-ignored-mode.sh +59
-1@@ -116,10 +116,68 @@ test_expect_success 'Verify status behavior on ignored folder containing tracked ignored_dir/ignored_1.ign ignored_dir/ignored_2.ign \ ignored_dir/tracked && git add -f ignored_dir/tracked && - test_tick && git commit -m "Force add file in ignored directory" && git status --porcelain=v2 --ignored=matching --untracked-files=all >output && test_i18ncmp expect output ' +test_expect_success 'Verify matching ignored files with --untracked-files=normal' ' + test_when_finished "git clean -fdx" && + cat >expect <<-\EOF && + ? expect + ? output + ? untracked_dir/ + ! ignored_dir/ + ! ignored_files/ignored_1.ign + ! ignored_files/ignored_2.ign + EOF + + mkdir ignored_dir ignored_files untracked_dir && + touch ignored_dir/ignored_1 ignored_dir/ignored_2 \ + ignored_files/ignored_1.ign ignored_files/ignored_2.ign \ + untracked_dir/untracked && + git status --porcelain=v2 --ignored=matching --untracked-files=normal >output && + test_i18ncmp expect output +' + +test_expect_success 'Verify matching ignored files with --untracked-files=normal' ' + test_when_finished "git clean -fdx" && + cat >expect <<-\EOF && + ? expect + ? output + ? untracked_dir/ + ! ignored_dir/ + ! ignored_files/ignored_1.ign + ! ignored_files/ignored_2.ign + EOF + + mkdir ignored_dir ignored_files untracked_dir && + touch ignored_dir/ignored_1 ignored_dir/ignored_2 \ + ignored_files/ignored_1.ign ignored_files/ignored_2.ign \ + untracked_dir/untracked && + git status --porcelain=v2 --ignored=matching --untracked-files=normal >output && + test_i18ncmp expect output +' + +test_expect_success 'Verify status behavior on ignored folder containing tracked file' ' + test_when_finished "git clean -fdx && git reset HEAD~1 --hard" && + cat >expect <<-\EOF && + ? expect + ? output + ! ignored_dir/ignored_1 + ! ignored_dir/ignored_1.ign + ! ignored_dir/ignored_2 + ! ignored_dir/ignored_2.ign + EOF + + mkdir ignored_dir && + touch ignored_dir/ignored_1 ignored_dir/ignored_2 \ + ignored_dir/ignored_1.ign ignored_dir/ignored_2.ign \ + ignored_dir/tracked && + git add -f ignored_dir/tracked && + git commit -m "Force add file in ignored directory" && + git status --porcelain=v2 --ignored=matching --untracked-files=normal >output && + test_i18ncmp expect output +' + test_done
Re: [PATCH v2 5/5] Add tests around status handling of ignored arguments
Quoted 7 lines · Junio C Hamano
Quoted 5 lines · Jameson Miller
Add tests for status handling of '--ignored=matching
and--untracked-files=normal`.Signed-off-by Jameson Miller <[email protected]>---
Quoted 8 lines
Hmph, having some tests in 3/5, changes in 4/5 and even more tests in 5/5 makes me as a reader a bit confused, as the description for these two test patches does not make it clear how they are related and how they are different. Is it that changes in 1/5 alone does not fulfill the promise made by documentation added at 2/5 so 3/5 only has tests for behaviour that works with 1/5 alone but is broken with respect to what 2/5 claims until 4/5 is applied, and these "not working with 1/5 alone, but works after 4/5" are added in this step?
Correct. The changes in 1/5 are to implement "--ignored=matching" with "--untracked-files=all" with corresponding tests in 3/5. The changes in 4/5 are to implement "--ignored=matching" with "--untracked-files=normal" and the corresponding tests are in 5/5.
Do you have a preference on how I organized this work? I see several possible ways to split up this work. Maybe it would be less confusing to have the implementation in the first two commits, then 1 commit with all the tests, and then a commit with the documentation? I think it makes sense to have the logic for the different flag combinations split into their own commits, but I am open to any suggestions.
Quoted 78 lines
Quoted 78 lines
t/t7519-ignored-mode.sh | 60 ++++++++++++++++++++++++++++++++++++++++++++++++- 1 file changed, 59 insertions(+), 1 deletion(-)t/t7519-ignored-mode.sh +59
-1@@ -116,10 +116,68 @@ test_expect_success 'Verify status behavior on ignored folder containing tracked ignored_dir/ignored_1.ign ignored_dir/ignored_2.ign \ ignored_dir/tracked && git add -f ignored_dir/tracked && - test_tick && git commit -m "Force add file in ignored directory" && git status --porcelain=v2 --ignored=matching --untracked-files=all >output && test_i18ncmp expect output ' +test_expect_success 'Verify matching ignored files with --untracked-files=normal' ' + test_when_finished "git clean -fdx" && + cat >expect <<-\EOF && + ? expect + ? output + ? untracked_dir/ + ! ignored_dir/ + ! ignored_files/ignored_1.ign + ! ignored_files/ignored_2.ign + EOF + + mkdir ignored_dir ignored_files untracked_dir && + touch ignored_dir/ignored_1 ignored_dir/ignored_2 \ + ignored_files/ignored_1.ign ignored_files/ignored_2.ign \ + untracked_dir/untracked && + git status --porcelain=v2 --ignored=matching --untracked-files=normal >output && + test_i18ncmp expect output +' + +test_expect_success 'Verify matching ignored files with --untracked-files=normal' ' + test_when_finished "git clean -fdx" && + cat >expect <<-\EOF && + ? expect + ? output + ? untracked_dir/ + ! ignored_dir/ + ! ignored_files/ignored_1.ign + ! ignored_files/ignored_2.ign + EOF + + mkdir ignored_dir ignored_files untracked_dir && + touch ignored_dir/ignored_1 ignored_dir/ignored_2 \ + ignored_files/ignored_1.ign ignored_files/ignored_2.ign \ + untracked_dir/untracked && + git status --porcelain=v2 --ignored=matching --untracked-files=normal >output && + test_i18ncmp expect output +' + +test_expect_success 'Verify status behavior on ignored folder containing tracked file' ' + test_when_finished "git clean -fdx && git reset HEAD~1 --hard" && + cat >expect <<-\EOF && + ? expect + ? output + ! ignored_dir/ignored_1 + ! ignored_dir/ignored_1.ign + ! ignored_dir/ignored_2 + ! ignored_dir/ignored_2.ign + EOF + + mkdir ignored_dir && + touch ignored_dir/ignored_1 ignored_dir/ignored_2 \ + ignored_dir/ignored_1.ign ignored_dir/ignored_2.ign \ + ignored_dir/tracked && + git add -f ignored_dir/tracked && + git commit -m "Force add file in ignored directory" && + git status --porcelain=v2 --ignored=matching --untracked-files=normal >output && + test_i18ncmp expect output +' + test_done
Re: [PATCH v2 5/5] Add tests around status handling of ignored arguments
Quoted 15 lines · Jameson Miller
Quoted 8 lines
Hmph, having some tests in 3/5, changes in 4/5 and even more tests in 5/5 makes me as a reader a bit confused, as the description for these two test patches does not make it clear how they are related and how they are different. Is it that changes in 1/5 alone does not fulfill the promise made by documentation added at 2/5 so 3/5 only has tests for behaviour that works with 1/5 alone but is broken with respect to what 2/5 claims until 4/5 is applied, and these "not working with 1/5 alone, but works after 4/5" are added in this step?
Correct. The changes in 1/5 are to implement "--ignored=matching" with "--untracked-files=all" with corresponding tests in 3/5. The changes in 4/5 are to implement "--ignored=matching" with "--untracked-files=normal" and the corresponding tests are in 5/5.
Quoted 7 lines
Do you have a preference on how I organized this work? I see several possible ways to split up this work. Maybe it would be less confusing to have the implementation in the first two commits, then 1 commit with all the tests, and then a commit with the documentation? I think it makes sense to have the logic for the different flag combinations split into their own commits, but I am open to any suggestions.
Yeah, there are some alternatives, all valid.
Support matching/all combination in 1/5, document that in 2/5, test that in 3/5 and then do the same 3-patch series to support matching/normal combination in 4/5, 5/5 and 6/5 would be one. Doing code, doc and test for matching/all in one patch and doing code, doc and test for matching/normal in another patch, resulting in a two-patch series may be another. Or your "code for matching/all in 1/5, code for matching/normal in 2/5, doc and test for both in subsequent steps" is fine, too. All of these would not leave things in inconsistent state when we interrupt the series in the middle, which is a desirable property for those who want to understand the topic.
Quoted 8 lines · Jameson Miller
Changes in v2:
Addressed review comments from the original series:
* Made fixes / simplifications suggested for documentation
* Removed
test_tickfrom test scripts
Quoted 8 lines
* Merged 2 commits (as suggested)
Jameson Miller (5):
Teach status options around showing ignored files Update documentation for new directory and status logic Add tests for git status--ignored=matchingExpand support for ignored arguments on status Add tests around status handling of ignored arguments
Please make sure these titles mix well when they appear together with changes from other people that are completely unrelated to them. Keep in mind that your "git status" is *not* the most important thing in the world (of course, it is no less important than others, either). Perhaps
status: add new options to show ignored files differently
status: document logic to show new directory
status: test --ignored=matching
etc. Rules of thumb:
(1) choose "<area>: " prefix appropriately
(2) keep them short and to the point
(3) word that follow "<area>: " prefix is not capitalized
(4) no need for full-stop at the end of the title
Quoted 24 lines · Junio C Hamano
Quoted 8 lines · Jameson Miller
Changes in v2:
Addressed review comments from the original series:
* Made fixes / simplifications suggested for documentation
* Removed
test_tickfrom test scriptsQuoted 8 lines
* Merged 2 commits (as suggested)
Jameson Miller (5):
Teach status options around showing ignored files Update documentation for new directory and status logic Add tests for git status--ignored=matchingExpand support for ignored arguments on status Add tests around status handling of ignored argumentsPlease make sure these titles mix well when they appear together with changes from other people that are completely unrelated to them. Keep in mind that your "git status" is *not* the most important thing in the world (of course, it is no less important than others, either). Perhaps
Quoted 3 lines
status: add new options to show ignored files differently
status: document logic to show new directory
status: test --ignored=matching
Thank you for the suggestions - I will update the commit titles in my next round.
Quoted 9 lines
etc. Rules of thumb:
(1) choose "<area>: " prefix appropriately
(2) keep them short and to the point
(3) word that follow "<area>: " prefix is not capitalized
(4) no need for full-stop at the end of the title
v3 cover status: add option to show ignored files differently
In reply to [email protected]The previous iteration can be found here:
https://public-inbox.org/git/[email protected]/
The main difference is to address feedback around commit organization and wording.
Jameson Miller (4):
status: add option to show ignored files differently
status: report matching ignored and normal untracked
status: document options to show matching ignored files
status: test --ignored=matching
Documentation/git-status.txt | 21 ++- Documentation/technical/api-directory-listing.txt | 27 +++- builtin/commit.c | 31 +++- dir.c | 44 +++++- dir.h | 3 +- t/t7519-ignored-mode.sh | 183 ++++++++++++++++++++++ wt-status.c | 11 +- wt-status.h | 8 +- 8 files changed, 310 insertions(+), 18 deletions(-) create mode 100755 t/t7519-ignored-mode.sh
Signature · 1 line
2.13.6
PATCH v3 1/4 status: add option to show ignored files differently
Teach the status command more flexibility in how ignored files are reported. Currently, the reporting of ignored files and untracked files are linked. You cannot control how ignored files are reported independently of how untracked files are reported (i.e. all vs normal). This makes it impossible to show untracked files with the all option, but show ignored files with the normal option.
This work 1) adds the ability to control the reporting of ignored files independently of untracked files and 2) introduces the concept of status reporting ignored paths that explicitly match an ignored pattern. There are 2 benefits to these changes: 1) if a consumer needs all untracked files but not all ignored files, there is a performance benefit to not scanning all contents of an ignored directory and 2) returning ignored files that explicitly match a path allow a consumer to make more informed decisions about when a status result might be stale.
This commit implements --ignored=matching with --untracked-files=all. The following commit will implement --ignored=matching with --untracked=files=normal.
As an example of where this flexibility could be useful is that our application (Visual Studio) runs the status command and presents the output. It shows all untracked files individually (e.g. using the '--untracked-files==all' option), and would like to know about which paths are ignored. It uses information about ignored paths to make decisions about when the status result might have changed. Additionally, many projects place build output into directories inside a repository's working directory (e.g. in "bin/" and "obj/" directories). Normal usage is to explicitly ignore these 2 directory names in the .gitignore file (rather than or in addition to the *.obj pattern).If an application could know that these directories are explicitly ignored, it could infer that all contents are ignored as well and make better informed decisions about files in these directories. It could infer that any changes under these paths would not affect the output of status. Additionally, there can be a significant performance benefit by avoiding scanning through ignored directories.
When status is set to report matching ignored files, it has the following behavior. Ignored files and directories that explicitly match an exclude pattern are reported. If an ignored directory matches an exclude pattern, then the path of the directory is returned. If a directory does not match an exclude pattern, but all of its contents are ignored, then the contained files are reported instead of the directory.
--- builtin/commit.c | 31 +++++++++++++++++++++++++------ dir.c | 24 ++++++++++++++++++++++++ dir.h | 3 ++- wt-status.c | 11 ++++++++--- wt-status.h | 8 +++++++- 5 files changed, 66 insertions(+), 11 deletions(-)
builtin/commit.c +25 -6
@@ -118,7 +118,7 @@ static int edit_flag = -1; /* unspecified */static int quiet, verbose, no_verify, allow_empty, dry_run, renew_authorship;static int config_commit_verbose =-1 ;/* unspecified */ static int no_post_rewrite, allow_empty_message; -static char *untracked_files_arg, *force_date, *ignore_submodule_arg; +static char *untracked_files_arg, *force_date, *ignore_submodule_arg, *ignored_arg;static char *sign_commit;/*
@@ -139,7 +139,7 @@ static const char *cleanup_arg;static enum commit_whence whence;static int sequencer_in_use;static int use_editor =1 , include_status =1 ; -static int show_ignored_in_status, have_option_m; +static int have_option_m;static struct strbuf message =STRBUF_INIT ;static enum wt_status_format status_format =STATUS_FORMAT_UNSPECIFIED ;
@@ -1075,6 +1075,19 @@ static const char *find_author_by_nickname(const char *name)die (_ ("--author '%s' is not 'Name <email>' and matches no existing author" ), name); } +static void handle_ignored_arg (struct wt_status *s) +{ +if (!ignored_arg) + ;/* default already initialized */ +else if (!strcmp (ignored_arg,"traditional" )) + s->show_ignored_mode =SHOW_TRADITIONAL_IGNORED ; +else if (!strcmp (ignored_arg,"no" )) + s->show_ignored_mode =SHOW_NO_IGNORED ; +else if (!strcmp (ignored_arg,"matching" )) + s->show_ignored_mode =SHOW_MATCHING_IGNORED ; +else +die (_ ("Invalid ignored mode '%s'" ), ignored_arg); +}static void handle_untracked_files_arg (struct wt_status *s) {
@@ -1363,8 +1376,10 @@ int cmd_status(int argc, const char **argv, const char *prefix)N_ ("mode" ),N_ ("show untracked files, optional modes: all, normal, no. (Default: all)" ), PARSE_OPT_OPTARG, NULL, (intptr_t)"all" }, -OPT_BOOL (0 ,"ignored" , &show_ignored_in_status, -N_ ("show ignored files" )), + { OPTION_STRING, 0, "ignored", &ignored_arg, +N_ ("mode" ), +N_ ("show ignored files, optional modes: traditional, matching, no. (Default: traditional)" ), + PARSE_OPT_OPTARG, NULL, (intptr_t)"traditional" }, { OPTION_STRING, 0, "ignore-submodules", &ignore_submodule_arg, N_("when"),N_ ("ignore changes to submodules, optional when: all, dirty, untracked. (Default: all)" ), PARSE_OPT_OPTARG, NULL, (intptr_t)"all" },
@@ -1383,8 +1398,12 @@ int cmd_status(int argc, const char **argv, const char *prefix)finalize_deferred_config (&s);handle_untracked_files_arg (&s); -if (show_ignored_in_status) - s.show_ignored_files =1 ; +handle_ignored_arg (&s); + +if (s.show_ignored_mode ==SHOW_MATCHING_IGNORED && + s.show_untracked_files ==SHOW_NO_UNTRACKED_FILES ) +die (_ ("Unsupported combination of ignored and untracked-files arguments" )); +parse_pathspec (&s.pathspec,0 ,PATHSPEC_PREFER_FULL , prefix, argv);
dir.c +24 -0
@@ -1389,6 +1389,30 @@ static enum path_treatment treat_directory(struct dir_struct *dir,case index_nonexistent:if (dir->flags &DIR_SHOW_OTHER_DIRECTORIES )break ; +if (exclude && + (dir->flags &DIR_SHOW_IGNORED_TOO ) && + (dir->flags &DIR_SHOW_IGNORED_TOO_MODE_MATCHING )) { + +/* +* This is an excluded directory and we are +* showing ignored paths that match an exclude +* pattern. (e.g. show directory as ignored +* only if it matches an exclude pattern). +* This path will either be 'path_excluded` +* (if we are showing empty directories or if +* the directory is not empty), or will be +* 'path_none' (empty directory, and we are +* not showing empty directories). +*/ +if (!(dir->flags &DIR_HIDE_EMPTY_DIRECTORIES )) +return path_excluded; + +if (read_directory_recursive (dir, istate, dirname, len, + untracked,1 ,1 , pathspec) == path_excluded) +return path_excluded; + +return path_none; + }if (!(dir->flags &DIR_NO_GITLINKS )) {unsigned char sha1[20 ];if (resolve_gitlink_ref (dirname,"HEAD" , sha1) ==0 )
dir.h +2 -1
@@ -152,7 +152,8 @@ struct dir_struct {DIR_COLLECT_IGNORED =1 <<4 ,DIR_SHOW_IGNORED_TOO =1 <<5 ,DIR_COLLECT_KILLED_ONLY =1 <<6 , - DIR_KEEP_UNTRACKED_CONTENTS = 1<<7 +DIR_KEEP_UNTRACKED_CONTENTS =1 <<7 , + DIR_SHOW_IGNORED_TOO_MODE_MATCHING = 1<<8 } flags;struct dir_entry **entries;struct dir_entry **ignored;
wt-status.c +8 -3
@@ -660,10 +660,15 @@ static void wt_status_collect_untracked(struct wt_status *s)if (s->show_untracked_files !=SHOW_ALL_UNTRACKED_FILES ) dir.flags |=DIR_SHOW_OTHER_DIRECTORIES |DIR_HIDE_EMPTY_DIRECTORIES ; -if (s->show_ignored_files) +if (s->show_ignored_mode) { dir.flags |=DIR_SHOW_IGNORED_TOO ; -else + +if (s->show_ignored_mode ==SHOW_MATCHING_IGNORED ) + dir.flags |=DIR_SHOW_IGNORED_TOO_MODE_MATCHING ; + }else { dir.untracked = the_index.untracked; + } +setup_standard_excludes (&dir);fill_directory (&dir, &the_index, &s->pathspec);
@@ -1621,7 +1626,7 @@ static void wt_longstatus_print(struct wt_status *s) }if (s->show_untracked_files) {wt_longstatus_print_other (s, &s->untracked,_ ("Untracked files" ),"add" ); -if (s->show_ignored_files) +if (s->show_ignored_mode)wt_longstatus_print_other (s, &s->ignored,_ ("Ignored files" ),"add -f" );if (advice_status_u_option &&2000 < s->untracked_in_ms) {status_printf_ln (s,GIT_COLOR_NORMAL ,"%s" ,"" );
wt-status.h +7 -1
@@ -27,6 +27,12 @@ enum untracked_status_type {SHOW_ALL_UNTRACKED_FILES }; +enum show_ignored_type { +SHOW_NO_IGNORED , +SHOW_TRADITIONAL_IGNORED , +SHOW_MATCHING_IGNORED , +}; +/* from where does this commit originate */ enum commit_whence {FROM_COMMIT ,/* normal */
@@ -70,7 +76,7 @@ struct wt_status {int display_comment_prefix;int relative_paths;int submodule_summary; -int show_ignored_files; +enum show_ignored_type show_ignored_mode;enum untracked_status_type show_untracked_files;const char *ignore_submodule_arg;char color_palette[WT_STATUS_MAXSLOT ][COLOR_MAXLEN ];
Signature · 1 line
2.13.6
Re: [PATCH v3 1/4] status: add option to show ignored files differently
Quoted 12 lines · Jameson Miller
Teach the status command more flexibility in how ignored files are reported. Currently, the reporting of ignored files and untracked files are linked. You cannot control how ignored files are reported independently of how untracked files are reported (i.e.
allvsnormal). This makes it impossible to show untracked files with thealloption, but show ignored files with thenormaloption.This work 1) adds the ability to control the reporting of ignored files independently of untracked files and 2) introduces the concept of status reporting ignored paths that explicitly match an ignored pattern. ...
Quoted 7 lines
When status is set to report matching ignored files, it has the following behavior. Ignored files and directories that explicitly match an exclude pattern are reported. If an ignored directory matches an exclude pattern, then the path of the directory is returned. If a directory does not match an exclude pattern, but all of its contents are ignored, then the contained files are reported instead of the directory.
Thanks for an updated log message. Very nicely explained.
Quoted 17 lines
builtin/commit.c +13
-0+static void handle_ignored_arg (struct wt_status *s) +{ +if (!ignored_arg) + ;/* default already initialized */ +else if (!strcmp (ignored_arg,"traditional" )) + s->show_ignored_mode =SHOW_TRADITIONAL_IGNORED ; +else if (!strcmp (ignored_arg,"no" )) + s->show_ignored_mode =SHOW_NO_IGNORED ; +else if (!strcmp (ignored_arg,"matching" )) + s->show_ignored_mode =SHOW_MATCHING_IGNORED ; +else +die (_ ("Invalid ignored mode '%s'" ), ignored_arg); +}static void handle_untracked_files_arg (struct wt_status *s) {
builtin/commit.c int cmd_status(int argc, const char **argv, const char *prefix) · line 1382
Quoted 9 lines
builtin/commit.c +4
-2@@ -1363,8 +1376,10 @@ int cmd_status(int argc, const char **argv, const char *prefix)N_ ("mode" ),N_ ("show untracked files, optional modes: all, normal, no. (Default: all)" ), PARSE_OPT_OPTARG, NULL, (intptr_t)"all" }, -OPT_BOOL (0 ,"ignored" , &show_ignored_in_status, - N_("show ignored files")), + { OPTION_STRING, 0, "ignored", &ignored_arg, +N_ ("mode" ), +N_ ("show ignored files, optional modes: traditional, matching, no. (Default: traditional)" ), + PARSE_OPT_OPTARG, NULL, (intptr_t)"traditional" },
We used to use "show_ignored_in_status" variable that can be either 0 (when no --ignored is given, or an explicit --no-ignored is given, on the command line) or 1 (when --ignored is given on the command line).
We still allow "--ignored" without value for backward compatibility, but
$ git status -uall --ignored \*.c
may trigger die() from handle_ignored_arg(). I wonder if this is something we care about.
... goes and digs ...
OK, because of PARSE_OPT_OPTARG, the above is safe; "*.c" is not mistaken as the value given to the --ignored option. It also means that
$ git status -uno --ignored matching
would not mean what a naïve reader may expect and does not error out, even though
$ git status -uno --ignored=matching
would. Which is something we eventually might care about, but that is how parse-options PARSE_OPT_OPTARG works, and I consider "fixing" it is totally out of the scope of this series (e.g. the next option "--ignore-submodules" below shares exactly the same issue).
Quoted 9 lines
builtin/commit.c +0
-0{OPTION_STRING ,0 ,"ignore-submodules" , &ignore_submodule_arg,N_ ("when" ),N_ ("ignore changes to submodules, optional when: all, dirty, untracked. (Default: all)" ), PARSE_OPT_OPTARG, NULL, (intptr_t)"all" },wt-status.c +0
-0
wt-status.c static void wt_status_collect_untracked(struct wt_status *s) · line 663
Quoted 5 lines
wt-status.c +1
-1@@ -660,10 +660,15 @@ static void wt_status_collect_untracked(struct wt_status *s)if (s->show_untracked_files !=SHOW_ALL_UNTRACKED_FILES ) dir.flags |=DIR_SHOW_OTHER_DIRECTORIES |DIR_HIDE_EMPTY_DIRECTORIES ; -if (s->show_ignored_files) +if (s->show_ignored_mode) {
Now we no longer use show_ignored_files that was a boolean yes/no, and instead use an enum show_ignored_mode, we'd better spell this out like so:
if (s->show_ignored_mode == SHOW_NO_IGNORED) {wt-status.c static void wt_status_collect_untracked(struct wt_status *s) · line 667
Quoted 5 lines
wt-status.c +3
-1dir.flags |=DIR_SHOW_IGNORED_TOO ; - else + +if (s->show_ignored_mode ==SHOW_MATCHING_IGNORED ) + dir.flags |=DIR_SHOW_IGNORED_TOO_MODE_MATCHING ;
Mental note: the old "show_ignored_files is true" case is now split into two, i.e. traditional vs matching. When matching is used, dir.flags gets a new bit, i.e. DIR_SHOW_IGNORED_TOO_MODE_MATCHING. Lack of that bit means dir.c helpers should behave as before.
wt-status.c static void wt_longstatus_print(struct wt_status *s) · line 1629
Quoted 13 lines
wt-status.c +4
-1+ }else { dir.untracked = the_index.untracked; + } +setup_standard_excludes (&dir);fill_directory (&dir, &the_index, &s->pathspec);@@ -1621,7 +1626,7 @@ static void wt_longstatus_print(struct wt_status *s) }if (s->show_untracked_files) {wt_longstatus_print_other (s, &s->untracked,_ ("Untracked files" ),"add" ); -if (s->show_ignored_files) +if (s->show_ignored_mode)
Likewise, i.e.
if (s->show_ignored_mode == SHOW_NO_IGNORED)
Quoted 9 lines
wt-status.c +0
-0wt_longstatus_print_other (s, &s->ignored,_ ("Ignored files" ),"add -f" );if (advice_status_u_option &&2000 < s->untracked_in_ms) {status_printf_ln (s,GIT_COLOR_NORMAL ,"%s" ,"" );dir.c +0
-0
dir.c static enum path_treatment treat_directory(struct dir_struct *dir, · line 1394
Quoted 6 lines
dir.c +3
-0@@ -1389,6 +1389,30 @@ static enum path_treatment treat_directory(struct dir_struct *dir,case index_nonexistent:if (dir->flags &DIR_SHOW_OTHER_DIRECTORIES )break ; +if (exclude && + (dir->flags &DIR_SHOW_IGNORED_TOO ) && + (dir->flags &DIR_SHOW_IGNORED_TOO_MODE_MATCHING )) {
It somehow feels superfluous to check both TOO and TOO_MODE_MATCHING here (IOW, wouldn't the latter be superset of the former? Is there a valid case where the latter is set but not the former?), but it is perhaps OK as belt-and-suspenders sanity.
dir.c static enum path_treatment treat_directory(struct dir_struct *dir, · line 1406
Quoted 11 lines
dir.c +11
-0+/* +* This is an excluded directory and we are +* showing ignored paths that match an exclude +* pattern. (e.g. show directory as ignored +* only if it matches an exclude pattern). +* This path will either be 'path_excluded` +* (if we are showing empty directories or if +* the directory is not empty), or will be +* 'path_none' (empty directory, and we are +* not showing empty directories). +*/
The only caller of treat_directory() calls us when the path we are seeing (sans trailing '/' that was added immediately before we were called) passed "is_excluded()" check in the caller, so at this point, the directory in question is being excluded because it matched an exclude pattern. IOW, if we are a/b/c, a pattern such as "a/b/*" may have said we are excluded and made the call to this function. Do we need to ensure that a pattern like "a/*" is not what excluded us? Or IGNORED_TOO_MODE_MATCHING also should show "a/b/c" when a pattern "a/*" matched it as "ignored because it matched an exclude pattern"?
dir.c static enum path_treatment treat_directory(struct dir_struct *dir, · line 1415
Quoted 9 lines
dir.c +9
-0+if (!(dir->flags &DIR_HIDE_EMPTY_DIRECTORIES )) +return path_excluded; + +if (read_directory_recursive (dir, istate, dirname, len, + untracked,1 ,1 , pathspec) == path_excluded) +return path_excluded; + +return path_none; + }
... I guess we won't get into such a situation because this codepath will return only _excluded or _none when we are handing "a/b" which is already excluded "a/*", and does not cause the caller to recurse into "a/b/c" in the first place. So the updated code looks fine.
Quoted 17 lines
dir.c +0
-0if (!(dir->flags &DIR_NO_GITLINKS )) {unsigned char sha1[20 ];if (resolve_gitlink_ref (dirname,"HEAD" , sha1) ==0 )dir.h +2
-1@@ -152,7 +152,8 @@ struct dir_struct {DIR_COLLECT_IGNORED =1 <<4 ,DIR_SHOW_IGNORED_TOO =1 <<5 ,DIR_COLLECT_KILLED_ONLY =1 <<6 , - DIR_KEEP_UNTRACKED_CONTENTS = 1<<7 +DIR_KEEP_UNTRACKED_CONTENTS =1 <<7 , + DIR_SHOW_IGNORED_TOO_MODE_MATCHING = 1<<8 } flags;struct dir_entry **entries;struct dir_entry **ignored;
PATCH v3 2/4 status: report matching ignored and normal untracked
In reply to Jameson MillerTeach status command to handle --ignored=matching with --untracked-files=normal
--- dir.c | 20 ++++++++++++++++++-- 1 file changed, 18 insertions(+), 2 deletions(-)
dir.c +18 -2
@@ -1585,6 +1585,7 @@ static enum path_treatment treat_one_path(struct dir_struct *dir, {int exclude;int has_path_in_index = !!index_file_exists (istate, path->buf, path->len, ignore_case); +enum path_treatment path_treatment;if (dtype ==DT_UNKNOWN ) dtype =get_dtype (de, istate, path->buf, path->len);
@@ -1631,8 +1632,23 @@ static enum path_treatment treat_one_path(struct dir_struct *dir,return path_none;case DT_DIR :strbuf_addch (path,'/' ); -return treat_directory (dir, istate, untracked, path->buf, path->len, - baselen, exclude, pathspec); + path_treatment =treat_directory (dir, istate, untracked, + path->buf, path->len, + baselen, exclude, pathspec); +/* +* If 1) we only want to return directories that +* match an exclude pattern and 2) this directory does +* not match an exclude pattern but all of its +* contents are excluded, then indicate that we should +* recurse into this directory (instead of marking the +* directory itself as an ignored path). +*/ +if (!exclude && + path_treatment == path_excluded && + (dir->flags &DIR_SHOW_IGNORED_TOO ) && + (dir->flags &DIR_SHOW_IGNORED_TOO_MODE_MATCHING )) +return path_recurse; +return path_treatment;case DT_REG :case DT_LNK :return exclude ? path_excluded : path_untracked;
Signature · 1 line
2.13.6
PATCH v3 3/4 status: document options to show matching ignored files
In reply to Jameson Miller--- Documentation/git-status.txt | 21 +++++++++++++++++- Documentation/technical/api-directory-listing.txt | 27 +++++++++++++++++++---- 2 files changed, 43 insertions(+), 5 deletions(-)
Documentation/git-status.txt +20 -1
@@ -97,8 +97,27 @@ configuration variable documented in linkgit:git-config[1]. (and suppresses the output of submodule summaries when the config option `status.submoduleSummary` is set). ---ignored:: +--ignored[=<mode>]:: Show ignored files as well. ++ +The mode parameter is used to specify the handling of ignored files. +It is optional: it defaults to 'traditional'. ++ +The possible options are: ++ + - 'traditional' - Shows ignored files and directories, unless + --untracked-files=all is specifed, in which case + individual files in ignored directories are + displayed. + - 'no' - Show no ignored files. + - 'matching' - Shows ignored files and directories matching an + ignore pattern. ++ +When 'matching' mode is specified, paths that explicity match an +ignored pattern are shown. If a directory matches an ignore pattern, +then it is shown, but not paths contained in the ignored directory. If +a directory does not match an ignore pattern, but all contents are +ignored, then the directory is not shown, but all contents are shown. -z:: Terminate entries with NUL, instead of LF. This implies
Documentation/technical/api-directory-listing.txt +23 -4
@@ -22,16 +22,20 @@ The notable options are: `flags`:: - A bit-field of options (the `*IGNORED*` flags are mutually exclusive): + A bit-field of options: `DIR_SHOW_IGNORED`::: - Return just ignored files in `entries[]`, not untracked files. + Return just ignored files in `entries[]`, not untracked + files. This flag is mutually exclusive with + `DIR_SHOW_IGNORED_TOO`. `DIR_SHOW_IGNORED_TOO`::: - Similar to `DIR_SHOW_IGNORED`, but return ignored files in `ignored[]` - in addition to untracked files in `entries[]`. + Similar to `DIR_SHOW_IGNORED`, but return ignored files in + `ignored[]` in addition to untracked files in + `entries[]`. This flag is mutually exclusive with + `DIR_SHOW_IGNORED`. `DIR_KEEP_UNTRACKED_CONTENTS`:::
@@ -39,6 +43,21 @@ The notable options are: untracked contents of untracked directories are also returned in `entries[]`. +`DIR_SHOW_IGNORED_TOO_MODE_MATCHING`::: + + Only has meaning if `DIR_SHOW_IGNORED_TOO` is also set; if + this is set, returns ignored files and directories that match + an exclude pattern. If a directory matches an exclude pattern, + then the directory is returned and the contained paths are + not. A directory that does not match an exclude pattern will + not be returned even if all of its contents are ignored. In + this case, the contents are returned as individual entries. ++ +If this is set, files and directories that explicity match an ignore +pattern are reported. Implicity ignored directories (directories that +do not match an ignore pattern, but whose contents are all ignored) +are not reported, instead all of the contents are reported. + `DIR_COLLECT_IGNORED`::: Special mode for git-add. Return ignored files in `ignored[]` and
Signature · 1 line
2.13.6
PATCH v3 4/4 status: test --ignored=matching
In reply to Jameson MillerAdd tests around status reporting ignord files that match an exclude pattern for both --untracked-files=normal and --untracked-files=all.
--- t/t7519-ignored-mode.sh | 183 ++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 183 insertions(+) create mode 100755 t/t7519-ignored-mode.sh
t/t7519-ignored-mode.sh new file +183 -0
@@ -0,0 +1,183 @@ +#!/bin/sh + +test_description='git status collapse ignored' + +. ./test-lib.sh + +# commit initial ignore file +test_expect_success 'setup initial commit and ignore file' ' + cat >.gitignore <<-\EOF && + *.ign + ignored_dir/ + !*.unignore + EOF + git add . && + git commit -m "Initial commit" +' + +test_expect_success 'Verify behavior of status on folders with ignored files' ' + test_when_finished "git clean -fdx" && + cat >expect <<-\EOF && + ? expect + ? output + ! dir/ignored/ignored_1.ign + ! dir/ignored/ignored_2.ign + ! ignored/ignored_1.ign + ! ignored/ignored_2.ign + EOF + + mkdir -p ignored dir/ignored && + touch ignored/ignored_1.ign ignored/ignored_2.ign \ + dir/ignored/ignored_1.ign dir/ignored/ignored_2.ign && + + git status --porcelain=v2 --ignored=matching --untracked-files=all >output && + test_i18ncmp expect output +' + +test_expect_success 'Verify status behavior on folder with tracked & ignored files' ' + test_when_finished "git clean -fdx && git reset HEAD~1 --hard" && + cat >expect <<-\EOF && + ? expect + ? output + ! dir/tracked_ignored/ignored_1.ign + ! dir/tracked_ignored/ignored_2.ign + ! tracked_ignored/ignored_1.ign + ! tracked_ignored/ignored_2.ign + EOF + + mkdir -p tracked_ignored dir/tracked_ignored && + touch tracked_ignored/tracked_1 tracked_ignored/tracked_2 \ + tracked_ignored/ignored_1.ign tracked_ignored/ignored_2.ign \ + dir/tracked_ignored/tracked_1 dir/tracked_ignored/tracked_2 \ + dir/tracked_ignored/ignored_1.ign dir/tracked_ignored/ignored_2.ign && + + git add tracked_ignored/tracked_1 tracked_ignored/tracked_2 \ + dir/tracked_ignored/tracked_1 dir/tracked_ignored/tracked_2 && + git commit -m "commit tracked files" && + + git status --porcelain=v2 --ignored=matching --untracked-files=all >output && + test_i18ncmp expect output +' + +test_expect_success 'Verify status behavior on folder with untracked and ignored files' ' + test_when_finished "git clean -fdx" && + cat >expect <<-\EOF && + ? dir/untracked_ignored/untracked_1 + ? dir/untracked_ignored/untracked_2 + ? expect + ? output + ? untracked_ignored/untracked_1 + ? untracked_ignored/untracked_2 + ! dir/untracked_ignored/ignored_1.ign + ! dir/untracked_ignored/ignored_2.ign + ! untracked_ignored/ignored_1.ign + ! untracked_ignored/ignored_2.ign + EOF + + mkdir -p untracked_ignored dir/untracked_ignored && + touch untracked_ignored/untracked_1 untracked_ignored/untracked_2 \ + untracked_ignored/ignored_1.ign untracked_ignored/ignored_2.ign \ + dir/untracked_ignored/untracked_1 dir/untracked_ignored/untracked_2 \ + dir/untracked_ignored/ignored_1.ign dir/untracked_ignored/ignored_2.ign && + + git status --porcelain=v2 --ignored=matching --untracked-files=all >output && + test_i18ncmp expect output +' + +test_expect_success 'Verify status matching ignored files on ignored folder' ' + test_when_finished "git clean -fdx" && + cat >expect <<-\EOF && + ? expect + ? output + ! ignored_dir/ + EOF + + mkdir ignored_dir && + touch ignored_dir/ignored_1 ignored_dir/ignored_2 \ + ignored_dir/ignored_1.ign ignored_dir/ignored_2.ign && + + git status --porcelain=v2 --ignored=matching --untracked-files=all >output && + test_i18ncmp expect output +' + +test_expect_success 'Verify status behavior on ignored folder containing tracked file' ' + test_when_finished "git clean -fdx && git reset HEAD~1 --hard" && + cat >expect <<-\EOF && + ? expect + ? output + ! ignored_dir/ignored_1 + ! ignored_dir/ignored_1.ign + ! ignored_dir/ignored_2 + ! ignored_dir/ignored_2.ign + EOF + + mkdir ignored_dir && + touch ignored_dir/ignored_1 ignored_dir/ignored_2 \ + ignored_dir/ignored_1.ign ignored_dir/ignored_2.ign \ + ignored_dir/tracked && + git add -f ignored_dir/tracked && + git commit -m "Force add file in ignored directory" && + git status --porcelain=v2 --ignored=matching --untracked-files=all >output && + test_i18ncmp expect output +' + +test_expect_success 'Verify matching ignored files with --untracked-files=normal' ' + test_when_finished "git clean -fdx" && + cat >expect <<-\EOF && + ? expect + ? output + ? untracked_dir/ + ! ignored_dir/ + ! ignored_files/ignored_1.ign + ! ignored_files/ignored_2.ign + EOF + + mkdir ignored_dir ignored_files untracked_dir && + touch ignored_dir/ignored_1 ignored_dir/ignored_2 \ + ignored_files/ignored_1.ign ignored_files/ignored_2.ign \ + untracked_dir/untracked && + git status --porcelain=v2 --ignored=matching --untracked-files=normal >output && + test_i18ncmp expect output +' + +test_expect_success 'Verify matching ignored files with --untracked-files=normal' ' + test_when_finished "git clean -fdx" && + cat >expect <<-\EOF && + ? expect + ? output + ? untracked_dir/ + ! ignored_dir/ + ! ignored_files/ignored_1.ign + ! ignored_files/ignored_2.ign + EOF + + mkdir ignored_dir ignored_files untracked_dir && + touch ignored_dir/ignored_1 ignored_dir/ignored_2 \ + ignored_files/ignored_1.ign ignored_files/ignored_2.ign \ + untracked_dir/untracked && + git status --porcelain=v2 --ignored=matching --untracked-files=normal >output && + test_i18ncmp expect output +' + +test_expect_success 'Verify status behavior on ignored folder containing tracked file' ' + test_when_finished "git clean -fdx && git reset HEAD~1 --hard" && + cat >expect <<-\EOF && + ? expect + ? output + ! ignored_dir/ignored_1 + ! ignored_dir/ignored_1.ign + ! ignored_dir/ignored_2 + ! ignored_dir/ignored_2.ign + EOF + + mkdir ignored_dir && + touch ignored_dir/ignored_1 ignored_dir/ignored_2 \ + ignored_dir/ignored_1.ign ignored_dir/ignored_2.ign \ + ignored_dir/tracked && + git add -f ignored_dir/tracked && + git commit -m "Force add file in ignored directory" && + git status --porcelain=v2 --ignored=matching --untracked-files=normal >output && + test_i18ncmp expect output +' + +test_done
Signature · 1 line
2.13.6
Re: [PATCH v3 4/4] status: test --ignored=matching
Quoted 1 line · Jameson Miller
+test_expect_success 'Verify behavior of status on folders with ignored files' '
https://stackoverflow.com/questions/5078676/what-is-the-difference-between-a-directory-and-a-folder
We test directories here?
All tests are testing --ignored=matching, do we want to have at least one test of "no" and "traditional" as well? (Just to see if the parsing works; we can modify
an existing test for that?)
Re: [PATCH v3 4/4] status: test --ignored=matching
In reply to Jameson MillerQuoted 8 lines · Jameson Miller
Add tests around status reporting ignord files that match an exclude pattern for both --untracked-files=normal and --untracked-files=all.
Signed-off-by Jameson Miller <[email protected]>--- t/t7519-ignored-mode.sh | 183 ++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 183 insertions(+) create mode 100755 t/t7519-ignored-mode.sh
Ben's fsmonitor series already uses t7519, so please move this somewhere else. Perhaps
git diff --name-only --diff-filter=A master pu t/
would help you see what new tests that are missing from 'master' are added by topics in flight.
Re: [PATCH v3 0/4] status: add option to show ignored files differently
In reply to Jameson MillerQuoted 5 lines · Jameson Miller
Jameson Miller (4):
status: add option to show ignored files differently
status: report matching ignored and normal untracked
status: document options to show matching ignored files
status: test --ignored=matching
Thanks, queued.
v4 cover status: add option to show ignored files differently
In reply to [email protected]The previous iteration can be found here:
https://public-inbox.org/git/[email protected]/
Changes from V3 patch series:
- Added extra test for --ignored=no an --ignored=traditional
- Updated wording from "folders" -> "directories"
- Renamed test to a name not taken in by topics in flight
Jameson Miller (4):
status: add option to show ignored files differently
status: report matching ignored and normal untracked
status: document options to show matching ignored files
status: test ignored modes
Documentation/git-status.txt | 21 +- Documentation/technical/api-directory-listing.txt | 27 ++- builtin/commit.c | 31 ++- dir.c | 44 +++- dir.h | 3 +- t/t7521-ignored-mode.sh | 233 ++++++++++++++++++++++ wt-status.c | 11 +- wt-status.h | 8 +- 8 files changed, 360 insertions(+), 18 deletions(-) create mode 100755 t/t7521-ignored-mode.sh
Signature · 1 line
2.13.6
PATCH v4 1/4 status: add option to show ignored files differently
Teach the status command more flexibility in how ignored files are reported. Currently, the reporting of ignored files and untracked files are linked. You cannot control how ignored files are reported independently of how untracked files are reported (i.e. all vs normal). This makes it impossible to show untracked files with the all option, but show ignored files with the normal option.
This work 1) adds the ability to control the reporting of ignored files independently of untracked files and 2) introduces the concept of status reporting ignored paths that explicitly match an ignored pattern. There are 2 benefits to these changes: 1) if a consumer needs all untracked files but not all ignored files, there is a performance benefit to not scanning all contents of an ignored directory and 2) returning ignored files that explicitly match a path allow a consumer to make more informed decisions about when a status result might be stale.
This commit implements --ignored=matching with --untracked-files=all. The following commit will implement --ignored=matching with --untracked=files=normal.
As an example of where this flexibility could be useful is that our application (Visual Studio) runs the status command and presents the output. It shows all untracked files individually (e.g. using the '--untracked-files==all' option), and would like to know about which paths are ignored. It uses information about ignored paths to make decisions about when the status result might have changed. Additionally, many projects place build output into directories inside a repository's working directory (e.g. in "bin/" and "obj/" directories). Normal usage is to explicitly ignore these 2 directory names in the .gitignore file (rather than or in addition to the *.obj pattern).If an application could know that these directories are explicitly ignored, it could infer that all contents are ignored as well and make better informed decisions about files in these directories. It could infer that any changes under these paths would not affect the output of status. Additionally, there can be a significant performance benefit by avoiding scanning through ignored directories.
When status is set to report matching ignored files, it has the following behavior. Ignored files and directories that explicitly match an exclude pattern are reported. If an ignored directory matches an exclude pattern, then the path of the directory is returned. If a directory does not match an exclude pattern, but all of its contents are ignored, then the contained files are reported instead of the directory.
--- builtin/commit.c | 31 +++++++++++++++++++++++++------ dir.c | 24 ++++++++++++++++++++++++ dir.h | 3 ++- wt-status.c | 11 ++++++++--- wt-status.h | 8 +++++++- 5 files changed, 66 insertions(+), 11 deletions(-)
builtin/commit.c +25 -6
@@ -118,7 +118,7 @@ static int edit_flag = -1; /* unspecified */static int quiet, verbose, no_verify, allow_empty, dry_run, renew_authorship;static int config_commit_verbose =-1 ;/* unspecified */ static int no_post_rewrite, allow_empty_message; -static char *untracked_files_arg, *force_date, *ignore_submodule_arg; +static char *untracked_files_arg, *force_date, *ignore_submodule_arg, *ignored_arg;static char *sign_commit;/*
@@ -139,7 +139,7 @@ static const char *cleanup_arg;static enum commit_whence whence;static int sequencer_in_use;static int use_editor =1 , include_status =1 ; -static int show_ignored_in_status, have_option_m; +static int have_option_m;static struct strbuf message =STRBUF_INIT ;static enum wt_status_format status_format =STATUS_FORMAT_UNSPECIFIED ;
@@ -1075,6 +1075,19 @@ static const char *find_author_by_nickname(const char *name)die (_ ("--author '%s' is not 'Name <email>' and matches no existing author" ), name); } +static void handle_ignored_arg (struct wt_status *s) +{ +if (!ignored_arg) + ;/* default already initialized */ +else if (!strcmp (ignored_arg,"traditional" )) + s->show_ignored_mode =SHOW_TRADITIONAL_IGNORED ; +else if (!strcmp (ignored_arg,"no" )) + s->show_ignored_mode =SHOW_NO_IGNORED ; +else if (!strcmp (ignored_arg,"matching" )) + s->show_ignored_mode =SHOW_MATCHING_IGNORED ; +else +die (_ ("Invalid ignored mode '%s'" ), ignored_arg); +}static void handle_untracked_files_arg (struct wt_status *s) {
@@ -1363,8 +1376,10 @@ int cmd_status(int argc, const char **argv, const char *prefix)N_ ("mode" ),N_ ("show untracked files, optional modes: all, normal, no. (Default: all)" ), PARSE_OPT_OPTARG, NULL, (intptr_t)"all" }, -OPT_BOOL (0 ,"ignored" , &show_ignored_in_status, -N_ ("show ignored files" )), + { OPTION_STRING, 0, "ignored", &ignored_arg, +N_ ("mode" ), +N_ ("show ignored files, optional modes: traditional, matching, no. (Default: traditional)" ), + PARSE_OPT_OPTARG, NULL, (intptr_t)"traditional" }, { OPTION_STRING, 0, "ignore-submodules", &ignore_submodule_arg, N_("when"),N_ ("ignore changes to submodules, optional when: all, dirty, untracked. (Default: all)" ), PARSE_OPT_OPTARG, NULL, (intptr_t)"all" },
@@ -1383,8 +1398,12 @@ int cmd_status(int argc, const char **argv, const char *prefix)finalize_deferred_config (&s);handle_untracked_files_arg (&s); -if (show_ignored_in_status) - s.show_ignored_files =1 ; +handle_ignored_arg (&s); + +if (s.show_ignored_mode ==SHOW_MATCHING_IGNORED && + s.show_untracked_files ==SHOW_NO_UNTRACKED_FILES ) +die (_ ("Unsupported combination of ignored and untracked-files arguments" )); +parse_pathspec (&s.pathspec,0 ,PATHSPEC_PREFER_FULL , prefix, argv);
dir.c +24 -0
@@ -1389,6 +1389,30 @@ static enum path_treatment treat_directory(struct dir_struct *dir,case index_nonexistent:if (dir->flags &DIR_SHOW_OTHER_DIRECTORIES )break ; +if (exclude && + (dir->flags &DIR_SHOW_IGNORED_TOO ) && + (dir->flags &DIR_SHOW_IGNORED_TOO_MODE_MATCHING )) { + +/* +* This is an excluded directory and we are +* showing ignored paths that match an exclude +* pattern. (e.g. show directory as ignored +* only if it matches an exclude pattern). +* This path will either be 'path_excluded` +* (if we are showing empty directories or if +* the directory is not empty), or will be +* 'path_none' (empty directory, and we are +* not showing empty directories). +*/ +if (!(dir->flags &DIR_HIDE_EMPTY_DIRECTORIES )) +return path_excluded; + +if (read_directory_recursive (dir, istate, dirname, len, + untracked,1 ,1 , pathspec) == path_excluded) +return path_excluded; + +return path_none; + }if (!(dir->flags &DIR_NO_GITLINKS )) {unsigned char sha1[20 ];if (resolve_gitlink_ref (dirname,"HEAD" , sha1) ==0 )
dir.h +2 -1
@@ -152,7 +152,8 @@ struct dir_struct {DIR_COLLECT_IGNORED =1 <<4 ,DIR_SHOW_IGNORED_TOO =1 <<5 ,DIR_COLLECT_KILLED_ONLY =1 <<6 , - DIR_KEEP_UNTRACKED_CONTENTS = 1<<7 +DIR_KEEP_UNTRACKED_CONTENTS =1 <<7 , + DIR_SHOW_IGNORED_TOO_MODE_MATCHING = 1<<8 } flags;struct dir_entry **entries;struct dir_entry **ignored;
wt-status.c +8 -3
@@ -658,10 +658,15 @@ static void wt_status_collect_untracked(struct wt_status *s)if (s->show_untracked_files !=SHOW_ALL_UNTRACKED_FILES ) dir.flags |=DIR_SHOW_OTHER_DIRECTORIES |DIR_HIDE_EMPTY_DIRECTORIES ; -if (s->show_ignored_files) +if (s->show_ignored_mode) { dir.flags |=DIR_SHOW_IGNORED_TOO ; -else + +if (s->show_ignored_mode ==SHOW_MATCHING_IGNORED ) + dir.flags |=DIR_SHOW_IGNORED_TOO_MODE_MATCHING ; + }else { dir.untracked = the_index.untracked; + } +setup_standard_excludes (&dir);fill_directory (&dir, &the_index, &s->pathspec);
@@ -1619,7 +1624,7 @@ static void wt_longstatus_print(struct wt_status *s) }if (s->show_untracked_files) {wt_longstatus_print_other (s, &s->untracked,_ ("Untracked files" ),"add" ); -if (s->show_ignored_files) +if (s->show_ignored_mode)wt_longstatus_print_other (s, &s->ignored,_ ("Ignored files" ),"add -f" );if (advice_status_u_option &&2000 < s->untracked_in_ms) {status_printf_ln (s,GIT_COLOR_NORMAL ,"%s" ,"" );
wt-status.h +7 -1
@@ -27,6 +27,12 @@ enum untracked_status_type {SHOW_ALL_UNTRACKED_FILES }; +enum show_ignored_type { +SHOW_NO_IGNORED , +SHOW_TRADITIONAL_IGNORED , +SHOW_MATCHING_IGNORED , +}; +/* from where does this commit originate */ enum commit_whence {FROM_COMMIT ,/* normal */
@@ -70,7 +76,7 @@ struct wt_status {int display_comment_prefix;int relative_paths;int submodule_summary; -int show_ignored_files; +enum show_ignored_type show_ignored_mode;enum untracked_status_type show_untracked_files;const char *ignore_submodule_arg;char color_palette[WT_STATUS_MAXSLOT ][COLOR_MAXLEN ];
Signature · 1 line
2.13.6
PATCH v4 2/4 status: report matching ignored and normal untracked
In reply to Jameson MillerTeach status command to handle --ignored=matching with --untracked-files=normal
--- dir.c | 20 ++++++++++++++++++-- 1 file changed, 18 insertions(+), 2 deletions(-)
dir.c +18 -2
@@ -1585,6 +1585,7 @@ static enum path_treatment treat_one_path(struct dir_struct *dir, {int exclude;int has_path_in_index = !!index_file_exists (istate, path->buf, path->len, ignore_case); +enum path_treatment path_treatment;if (dtype ==DT_UNKNOWN ) dtype =get_dtype (de, istate, path->buf, path->len);
@@ -1631,8 +1632,23 @@ static enum path_treatment treat_one_path(struct dir_struct *dir,return path_none;case DT_DIR :strbuf_addch (path,'/' ); -return treat_directory (dir, istate, untracked, path->buf, path->len, - baselen, exclude, pathspec); + path_treatment =treat_directory (dir, istate, untracked, + path->buf, path->len, + baselen, exclude, pathspec); +/* +* If 1) we only want to return directories that +* match an exclude pattern and 2) this directory does +* not match an exclude pattern but all of its +* contents are excluded, then indicate that we should +* recurse into this directory (instead of marking the +* directory itself as an ignored path). +*/ +if (!exclude && + path_treatment == path_excluded && + (dir->flags &DIR_SHOW_IGNORED_TOO ) && + (dir->flags &DIR_SHOW_IGNORED_TOO_MODE_MATCHING )) +return path_recurse; +return path_treatment;case DT_REG :case DT_LNK :return exclude ? path_excluded : path_untracked;
Signature · 1 line
2.13.6
PATCH v4 3/4 status: document options to show matching ignored files
In reply to Jameson Miller--- Documentation/git-status.txt | 21 +++++++++++++++++- Documentation/technical/api-directory-listing.txt | 27 +++++++++++++++++++---- 2 files changed, 43 insertions(+), 5 deletions(-)
Documentation/git-status.txt +20 -1
@@ -97,8 +97,27 @@ configuration variable documented in linkgit:git-config[1]. (and suppresses the output of submodule summaries when the config option `status.submoduleSummary` is set). ---ignored:: +--ignored[=<mode>]:: Show ignored files as well. ++ +The mode parameter is used to specify the handling of ignored files. +It is optional: it defaults to 'traditional'. ++ +The possible options are: ++ + - 'traditional' - Shows ignored files and directories, unless + --untracked-files=all is specifed, in which case + individual files in ignored directories are + displayed. + - 'no' - Show no ignored files. + - 'matching' - Shows ignored files and directories matching an + ignore pattern. ++ +When 'matching' mode is specified, paths that explicity match an +ignored pattern are shown. If a directory matches an ignore pattern, +then it is shown, but not paths contained in the ignored directory. If +a directory does not match an ignore pattern, but all contents are +ignored, then the directory is not shown, but all contents are shown. -z:: Terminate entries with NUL, instead of LF. This implies
Documentation/technical/api-directory-listing.txt +23 -4
@@ -22,16 +22,20 @@ The notable options are: `flags`:: - A bit-field of options (the `*IGNORED*` flags are mutually exclusive): + A bit-field of options: `DIR_SHOW_IGNORED`::: - Return just ignored files in `entries[]`, not untracked files. + Return just ignored files in `entries[]`, not untracked + files. This flag is mutually exclusive with + `DIR_SHOW_IGNORED_TOO`. `DIR_SHOW_IGNORED_TOO`::: - Similar to `DIR_SHOW_IGNORED`, but return ignored files in `ignored[]` - in addition to untracked files in `entries[]`. + Similar to `DIR_SHOW_IGNORED`, but return ignored files in + `ignored[]` in addition to untracked files in + `entries[]`. This flag is mutually exclusive with + `DIR_SHOW_IGNORED`. `DIR_KEEP_UNTRACKED_CONTENTS`:::
@@ -39,6 +43,21 @@ The notable options are: untracked contents of untracked directories are also returned in `entries[]`. +`DIR_SHOW_IGNORED_TOO_MODE_MATCHING`::: + + Only has meaning if `DIR_SHOW_IGNORED_TOO` is also set; if + this is set, returns ignored files and directories that match + an exclude pattern. If a directory matches an exclude pattern, + then the directory is returned and the contained paths are + not. A directory that does not match an exclude pattern will + not be returned even if all of its contents are ignored. In + this case, the contents are returned as individual entries. ++ +If this is set, files and directories that explicity match an ignore +pattern are reported. Implicity ignored directories (directories that +do not match an ignore pattern, but whose contents are all ignored) +are not reported, instead all of the contents are reported. + `DIR_COLLECT_IGNORED`::: Special mode for git-add. Return ignored files in `ignored[]` and
Signature · 1 line
2.13.6
PATCH v4 4/4 status: test ignored modes
In reply to Jameson MillerAdd tests around status reporting ignord files that match an exclude pattern for both --untracked-files=normal and --untracked-files=all.
--- t/t7521-ignored-mode.sh | 233 ++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 233 insertions(+) create mode 100755 t/t7521-ignored-mode.sh
t/t7521-ignored-mode.sh new file +233 -0
@@ -0,0 +1,233 @@ +#!/bin/sh + +test_description='git status ignored modes' + +. ./test-lib.sh + +test_expect_success 'setup initial commit and ignore file' ' + cat >.gitignore <<-\EOF && + *.ign + ignored_dir/ + !*.unignore + EOF + git add . && + git commit -m "Initial commit" +' + +test_expect_success 'Verify behavior of status on directories with ignored files' ' + test_when_finished "git clean -fdx" && + cat >expect <<-\EOF && + ? expect + ? output + ! dir/ignored/ignored_1.ign + ! dir/ignored/ignored_2.ign + ! ignored/ignored_1.ign + ! ignored/ignored_2.ign + EOF + + mkdir -p ignored dir/ignored && + touch ignored/ignored_1.ign ignored/ignored_2.ign \ + dir/ignored/ignored_1.ign dir/ignored/ignored_2.ign && + + git status --porcelain=v2 --ignored=matching --untracked-files=all >output && + test_i18ncmp expect output +' + +test_expect_success 'Verify status behavior on directory with tracked & ignored files' ' + test_when_finished "git clean -fdx && git reset HEAD~1 --hard" && + cat >expect <<-\EOF && + ? expect + ? output + ! dir/tracked_ignored/ignored_1.ign + ! dir/tracked_ignored/ignored_2.ign + ! tracked_ignored/ignored_1.ign + ! tracked_ignored/ignored_2.ign + EOF + + mkdir -p tracked_ignored dir/tracked_ignored && + touch tracked_ignored/tracked_1 tracked_ignored/tracked_2 \ + tracked_ignored/ignored_1.ign tracked_ignored/ignored_2.ign \ + dir/tracked_ignored/tracked_1 dir/tracked_ignored/tracked_2 \ + dir/tracked_ignored/ignored_1.ign dir/tracked_ignored/ignored_2.ign && + + git add tracked_ignored/tracked_1 tracked_ignored/tracked_2 \ + dir/tracked_ignored/tracked_1 dir/tracked_ignored/tracked_2 && + git commit -m "commit tracked files" && + + git status --porcelain=v2 --ignored=matching --untracked-files=all >output && + test_i18ncmp expect output +' + +test_expect_success 'Verify status behavior on directory with untracked and ignored files' ' + test_when_finished "git clean -fdx" && + cat >expect <<-\EOF && + ? dir/untracked_ignored/untracked_1 + ? dir/untracked_ignored/untracked_2 + ? expect + ? output + ? untracked_ignored/untracked_1 + ? untracked_ignored/untracked_2 + ! dir/untracked_ignored/ignored_1.ign + ! dir/untracked_ignored/ignored_2.ign + ! untracked_ignored/ignored_1.ign + ! untracked_ignored/ignored_2.ign + EOF + + mkdir -p untracked_ignored dir/untracked_ignored && + touch untracked_ignored/untracked_1 untracked_ignored/untracked_2 \ + untracked_ignored/ignored_1.ign untracked_ignored/ignored_2.ign \ + dir/untracked_ignored/untracked_1 dir/untracked_ignored/untracked_2 \ + dir/untracked_ignored/ignored_1.ign dir/untracked_ignored/ignored_2.ign && + + git status --porcelain=v2 --ignored=matching --untracked-files=all >output && + test_i18ncmp expect output +' + +test_expect_success 'Verify status matching ignored files on ignored directory' ' + test_when_finished "git clean -fdx" && + cat >expect <<-\EOF && + ? expect + ? output + ! ignored_dir/ + EOF + + mkdir ignored_dir && + touch ignored_dir/ignored_1 ignored_dir/ignored_2 \ + ignored_dir/ignored_1.ign ignored_dir/ignored_2.ign && + + git status --porcelain=v2 --ignored=matching --untracked-files=all >output && + test_i18ncmp expect output +' + +test_expect_success 'Verify status behavior on ignored directory containing tracked file' ' + test_when_finished "git clean -fdx && git reset HEAD~1 --hard" && + cat >expect <<-\EOF && + ? expect + ? output + ! ignored_dir/ignored_1 + ! ignored_dir/ignored_1.ign + ! ignored_dir/ignored_2 + ! ignored_dir/ignored_2.ign + EOF + + mkdir ignored_dir && + touch ignored_dir/ignored_1 ignored_dir/ignored_2 \ + ignored_dir/ignored_1.ign ignored_dir/ignored_2.ign \ + ignored_dir/tracked && + git add -f ignored_dir/tracked && + git commit -m "Force add file in ignored directory" && + git status --porcelain=v2 --ignored=matching --untracked-files=all >output && + test_i18ncmp expect output +' + +test_expect_success 'Verify matching ignored files with --untracked-files=normal' ' + test_when_finished "git clean -fdx" && + cat >expect <<-\EOF && + ? expect + ? output + ? untracked_dir/ + ! ignored_dir/ + ! ignored_files/ignored_1.ign + ! ignored_files/ignored_2.ign + EOF + + mkdir ignored_dir ignored_files untracked_dir && + touch ignored_dir/ignored_1 ignored_dir/ignored_2 \ + ignored_files/ignored_1.ign ignored_files/ignored_2.ign \ + untracked_dir/untracked && + git status --porcelain=v2 --ignored=matching --untracked-files=normal >output && + test_i18ncmp expect output +' + +test_expect_success 'Verify matching ignored files with --untracked-files=normal' ' + test_when_finished "git clean -fdx" && + cat >expect <<-\EOF && + ? expect + ? output + ? untracked_dir/ + ! ignored_dir/ + ! ignored_files/ignored_1.ign + ! ignored_files/ignored_2.ign + EOF + + mkdir ignored_dir ignored_files untracked_dir && + touch ignored_dir/ignored_1 ignored_dir/ignored_2 \ + ignored_files/ignored_1.ign ignored_files/ignored_2.ign \ + untracked_dir/untracked && + git status --porcelain=v2 --ignored=matching --untracked-files=normal >output && + test_i18ncmp expect output +' + +test_expect_success 'Verify status behavior on ignored directory containing tracked file' ' + test_when_finished "git clean -fdx && git reset HEAD~1 --hard" && + cat >expect <<-\EOF && + ? expect + ? output + ! ignored_dir/ignored_1 + ! ignored_dir/ignored_1.ign + ! ignored_dir/ignored_2 + ! ignored_dir/ignored_2.ign + EOF + + mkdir ignored_dir && + touch ignored_dir/ignored_1 ignored_dir/ignored_2 \ + ignored_dir/ignored_1.ign ignored_dir/ignored_2.ign \ + ignored_dir/tracked && + git add -f ignored_dir/tracked && + git commit -m "Force add file in ignored directory" && + git status --porcelain=v2 --ignored=matching --untracked-files=normal >output && + test_i18ncmp expect output +' + +test_expect_success 'Verify behavior of status with --ignored=no' ' + test_when_finished "git clean -fdx" && + cat >expect <<-\EOF && + ? expect + ? output + EOF + + mkdir -p ignored dir/ignored && + touch ignored/ignored_1.ign ignored/ignored_2.ign \ + dir/ignored/ignored_1.ign dir/ignored/ignored_2.ign && + + git status --porcelain=v2 --ignored=no --untracked-files=all >output && + test_i18ncmp expect output +' + +test_expect_success 'Verify behavior of status with --ignored=traditional and --untracked-files=all' ' + test_when_finished "git clean -fdx" && + cat >expect <<-\EOF && + ? expect + ? output + ! dir/ignored/ignored_1.ign + ! dir/ignored/ignored_2.ign + ! ignored/ignored_1.ign + ! ignored/ignored_2.ign + EOF + + mkdir -p ignored dir/ignored && + touch ignored/ignored_1.ign ignored/ignored_2.ign \ + dir/ignored/ignored_1.ign dir/ignored/ignored_2.ign && + + git status --porcelain=v2 --ignored=traditional --untracked-files=all >output && + test_i18ncmp expect output +' + +test_expect_success 'Verify behavior of status with --ignored=traditional and --untracked-files=normal' ' + test_when_finished "git clean -fdx" && + cat >expect <<-\EOF && + ? expect + ? output + ! dir/ + ! ignored/ + EOF + + mkdir -p ignored dir/ignored && + touch ignored/ignored_1.ign ignored/ignored_2.ign \ + dir/ignored/ignored_1.ign dir/ignored/ignored_2.ign && + + git status --porcelain=v2 --ignored=traditional --untracked-files=normal >output && + test_i18ncmp expect output +' + +test_done
Signature · 1 line
2.13.6
v5 cover status: add option to show ignored files differently
In reply to [email protected]From: Jameson Miller <[email protected]>
Previous patch series can be found:
https://public-inbox.org/git/[email protected]/
Only difference from previous version is to update the commit author email to match corporate email address.
Jameson Miller (4):
status: add option to show ignored files differently
status: report matching ignored and normal untracked
status: document options to show matching ignored files
status: test ignored modes
Documentation/git-status.txt | 21 +- Documentation/technical/api-directory-listing.txt | 27 ++- builtin/commit.c | 31 ++- dir.c | 44 +++- dir.h | 3 +- t/t7521-ignored-mode.sh | 233 ++++++++++++++++++++++ wt-status.c | 11 +- wt-status.h | 8 +- 8 files changed, 360 insertions(+), 18 deletions(-) create mode 100755 t/t7521-ignored-mode.sh
Signature · 1 line
2.13.6
PATCH v5 1/4 status: add option to show ignored files differently
From: Jameson Miller <[email protected]>
Teach the status command more flexibility in how ignored files are reported. Currently, the reporting of ignored files and untracked files are linked. You cannot control how ignored files are reported independently of how untracked files are reported (i.e. all vs normal). This makes it impossible to show untracked files with the all option, but show ignored files with the normal option.
This work 1) adds the ability to control the reporting of ignored files independently of untracked files and 2) introduces the concept of status reporting ignored paths that explicitly match an ignored pattern. There are 2 benefits to these changes: 1) if a consumer needs all untracked files but not all ignored files, there is a performance benefit to not scanning all contents of an ignored directory and 2) returning ignored files that explicitly match a path allow a consumer to make more informed decisions about when a status result might be stale.
This commit implements --ignored=matching with --untracked-files=all. The following commit will implement --ignored=matching with --untracked=files=normal.
As an example of where this flexibility could be useful is that our application (Visual Studio) runs the status command and presents the output. It shows all untracked files individually (e.g. using the '--untracked-files==all' option), and would like to know about which paths are ignored. It uses information about ignored paths to make decisions about when the status result might have changed. Additionally, many projects place build output into directories inside a repository's working directory (e.g. in "bin/" and "obj/" directories). Normal usage is to explicitly ignore these 2 directory names in the .gitignore file (rather than or in addition to the *.obj pattern).If an application could know that these directories are explicitly ignored, it could infer that all contents are ignored as well and make better informed decisions about files in these directories. It could infer that any changes under these paths would not affect the output of status. Additionally, there can be a significant performance benefit by avoiding scanning through ignored directories.
When status is set to report matching ignored files, it has the following behavior. Ignored files and directories that explicitly match an exclude pattern are reported. If an ignored directory matches an exclude pattern, then the path of the directory is returned. If a directory does not match an exclude pattern, but all of its contents are ignored, then the contained files are reported instead of the directory.
--- builtin/commit.c | 31 +++++++++++++++++++++++++------ dir.c | 24 ++++++++++++++++++++++++ dir.h | 3 ++- wt-status.c | 11 ++++++++--- wt-status.h | 8 +++++++- 5 files changed, 66 insertions(+), 11 deletions(-)
builtin/commit.c +25 -6
@@ -118,7 +118,7 @@ static int edit_flag = -1; /* unspecified */static int quiet, verbose, no_verify, allow_empty, dry_run, renew_authorship;static int config_commit_verbose =-1 ;/* unspecified */ static int no_post_rewrite, allow_empty_message; -static char *untracked_files_arg, *force_date, *ignore_submodule_arg; +static char *untracked_files_arg, *force_date, *ignore_submodule_arg, *ignored_arg;static char *sign_commit;/*
@@ -139,7 +139,7 @@ static const char *cleanup_arg;static enum commit_whence whence;static int sequencer_in_use;static int use_editor =1 , include_status =1 ; -static int show_ignored_in_status, have_option_m; +static int have_option_m;static struct strbuf message =STRBUF_INIT ;static enum wt_status_format status_format =STATUS_FORMAT_UNSPECIFIED ;
@@ -1075,6 +1075,19 @@ static const char *find_author_by_nickname(const char *name)die (_ ("--author '%s' is not 'Name <email>' and matches no existing author" ), name); } +static void handle_ignored_arg (struct wt_status *s) +{ +if (!ignored_arg) + ;/* default already initialized */ +else if (!strcmp (ignored_arg,"traditional" )) + s->show_ignored_mode =SHOW_TRADITIONAL_IGNORED ; +else if (!strcmp (ignored_arg,"no" )) + s->show_ignored_mode =SHOW_NO_IGNORED ; +else if (!strcmp (ignored_arg,"matching" )) + s->show_ignored_mode =SHOW_MATCHING_IGNORED ; +else +die (_ ("Invalid ignored mode '%s'" ), ignored_arg); +}static void handle_untracked_files_arg (struct wt_status *s) {
@@ -1363,8 +1376,10 @@ int cmd_status(int argc, const char **argv, const char *prefix)N_ ("mode" ),N_ ("show untracked files, optional modes: all, normal, no. (Default: all)" ), PARSE_OPT_OPTARG, NULL, (intptr_t)"all" }, -OPT_BOOL (0 ,"ignored" , &show_ignored_in_status, -N_ ("show ignored files" )), + { OPTION_STRING, 0, "ignored", &ignored_arg, +N_ ("mode" ), +N_ ("show ignored files, optional modes: traditional, matching, no. (Default: traditional)" ), + PARSE_OPT_OPTARG, NULL, (intptr_t)"traditional" }, { OPTION_STRING, 0, "ignore-submodules", &ignore_submodule_arg, N_("when"),N_ ("ignore changes to submodules, optional when: all, dirty, untracked. (Default: all)" ), PARSE_OPT_OPTARG, NULL, (intptr_t)"all" },
@@ -1383,8 +1398,12 @@ int cmd_status(int argc, const char **argv, const char *prefix)finalize_deferred_config (&s);handle_untracked_files_arg (&s); -if (show_ignored_in_status) - s.show_ignored_files =1 ; +handle_ignored_arg (&s); + +if (s.show_ignored_mode ==SHOW_MATCHING_IGNORED && + s.show_untracked_files ==SHOW_NO_UNTRACKED_FILES ) +die (_ ("Unsupported combination of ignored and untracked-files arguments" )); +parse_pathspec (&s.pathspec,0 ,PATHSPEC_PREFER_FULL , prefix, argv);
dir.c +24 -0
@@ -1389,6 +1389,30 @@ static enum path_treatment treat_directory(struct dir_struct *dir,case index_nonexistent:if (dir->flags &DIR_SHOW_OTHER_DIRECTORIES )break ; +if (exclude && + (dir->flags &DIR_SHOW_IGNORED_TOO ) && + (dir->flags &DIR_SHOW_IGNORED_TOO_MODE_MATCHING )) { + +/* +* This is an excluded directory and we are +* showing ignored paths that match an exclude +* pattern. (e.g. show directory as ignored +* only if it matches an exclude pattern). +* This path will either be 'path_excluded` +* (if we are showing empty directories or if +* the directory is not empty), or will be +* 'path_none' (empty directory, and we are +* not showing empty directories). +*/ +if (!(dir->flags &DIR_HIDE_EMPTY_DIRECTORIES )) +return path_excluded; + +if (read_directory_recursive (dir, istate, dirname, len, + untracked,1 ,1 , pathspec) == path_excluded) +return path_excluded; + +return path_none; + }if (!(dir->flags &DIR_NO_GITLINKS )) {unsigned char sha1[20 ];if (resolve_gitlink_ref (dirname,"HEAD" , sha1) ==0 )
dir.h +2 -1
@@ -152,7 +152,8 @@ struct dir_struct {DIR_COLLECT_IGNORED =1 <<4 ,DIR_SHOW_IGNORED_TOO =1 <<5 ,DIR_COLLECT_KILLED_ONLY =1 <<6 , - DIR_KEEP_UNTRACKED_CONTENTS = 1<<7 +DIR_KEEP_UNTRACKED_CONTENTS =1 <<7 , + DIR_SHOW_IGNORED_TOO_MODE_MATCHING = 1<<8 } flags;struct dir_entry **entries;struct dir_entry **ignored;
wt-status.c +8 -3
@@ -658,10 +658,15 @@ static void wt_status_collect_untracked(struct wt_status *s)if (s->show_untracked_files !=SHOW_ALL_UNTRACKED_FILES ) dir.flags |=DIR_SHOW_OTHER_DIRECTORIES |DIR_HIDE_EMPTY_DIRECTORIES ; -if (s->show_ignored_files) +if (s->show_ignored_mode) { dir.flags |=DIR_SHOW_IGNORED_TOO ; -else + +if (s->show_ignored_mode ==SHOW_MATCHING_IGNORED ) + dir.flags |=DIR_SHOW_IGNORED_TOO_MODE_MATCHING ; + }else { dir.untracked = the_index.untracked; + } +setup_standard_excludes (&dir);fill_directory (&dir, &the_index, &s->pathspec);
@@ -1619,7 +1624,7 @@ static void wt_longstatus_print(struct wt_status *s) }if (s->show_untracked_files) {wt_longstatus_print_other (s, &s->untracked,_ ("Untracked files" ),"add" ); -if (s->show_ignored_files) +if (s->show_ignored_mode)wt_longstatus_print_other (s, &s->ignored,_ ("Ignored files" ),"add -f" );if (advice_status_u_option &&2000 < s->untracked_in_ms) {status_printf_ln (s,GIT_COLOR_NORMAL ,"%s" ,"" );
wt-status.h +7 -1
@@ -27,6 +27,12 @@ enum untracked_status_type {SHOW_ALL_UNTRACKED_FILES }; +enum show_ignored_type { +SHOW_NO_IGNORED , +SHOW_TRADITIONAL_IGNORED , +SHOW_MATCHING_IGNORED , +}; +/* from where does this commit originate */ enum commit_whence {FROM_COMMIT ,/* normal */
@@ -70,7 +76,7 @@ struct wt_status {int display_comment_prefix;int relative_paths;int submodule_summary; -int show_ignored_files; +enum show_ignored_type show_ignored_mode;enum untracked_status_type show_untracked_files;const char *ignore_submodule_arg;char color_palette[WT_STATUS_MAXSLOT ][COLOR_MAXLEN ];
Signature · 1 line
2.13.6
PATCH v5 2/4 status: report matching ignored and normal untracked
In reply to [email protected]From: Jameson Miller <[email protected]>
Teach status command to handle --ignored=matching with --untracked-files=normal
--- dir.c | 20 ++++++++++++++++++-- 1 file changed, 18 insertions(+), 2 deletions(-)
dir.c +18 -2
@@ -1585,6 +1585,7 @@ static enum path_treatment treat_one_path(struct dir_struct *dir, {int exclude;int has_path_in_index = !!index_file_exists (istate, path->buf, path->len, ignore_case); +enum path_treatment path_treatment;if (dtype ==DT_UNKNOWN ) dtype =get_dtype (de, istate, path->buf, path->len);
@@ -1631,8 +1632,23 @@ static enum path_treatment treat_one_path(struct dir_struct *dir,return path_none;case DT_DIR :strbuf_addch (path,'/' ); -return treat_directory (dir, istate, untracked, path->buf, path->len, - baselen, exclude, pathspec); + path_treatment =treat_directory (dir, istate, untracked, + path->buf, path->len, + baselen, exclude, pathspec); +/* +* If 1) we only want to return directories that +* match an exclude pattern and 2) this directory does +* not match an exclude pattern but all of its +* contents are excluded, then indicate that we should +* recurse into this directory (instead of marking the +* directory itself as an ignored path). +*/ +if (!exclude && + path_treatment == path_excluded && + (dir->flags &DIR_SHOW_IGNORED_TOO ) && + (dir->flags &DIR_SHOW_IGNORED_TOO_MODE_MATCHING )) +return path_recurse; +return path_treatment;case DT_REG :case DT_LNK :return exclude ? path_excluded : path_untracked;
Signature · 1 line
2.13.6
PATCH v5 3/4 status: document options to show matching ignored files
In reply to [email protected]From: Jameson Miller <[email protected]>
--- Documentation/git-status.txt | 21 +++++++++++++++++- Documentation/technical/api-directory-listing.txt | 27 +++++++++++++++++++---- 2 files changed, 43 insertions(+), 5 deletions(-)
Documentation/git-status.txt +20 -1
@@ -97,8 +97,27 @@ configuration variable documented in linkgit:git-config[1]. (and suppresses the output of submodule summaries when the config option `status.submoduleSummary` is set). ---ignored:: +--ignored[=<mode>]:: Show ignored files as well. ++ +The mode parameter is used to specify the handling of ignored files. +It is optional: it defaults to 'traditional'. ++ +The possible options are: ++ + - 'traditional' - Shows ignored files and directories, unless + --untracked-files=all is specifed, in which case + individual files in ignored directories are + displayed. + - 'no' - Show no ignored files. + - 'matching' - Shows ignored files and directories matching an + ignore pattern. ++ +When 'matching' mode is specified, paths that explicity match an +ignored pattern are shown. If a directory matches an ignore pattern, +then it is shown, but not paths contained in the ignored directory. If +a directory does not match an ignore pattern, but all contents are +ignored, then the directory is not shown, but all contents are shown. -z:: Terminate entries with NUL, instead of LF. This implies
Documentation/technical/api-directory-listing.txt +23 -4
@@ -22,16 +22,20 @@ The notable options are: `flags`:: - A bit-field of options (the `*IGNORED*` flags are mutually exclusive): + A bit-field of options: `DIR_SHOW_IGNORED`::: - Return just ignored files in `entries[]`, not untracked files. + Return just ignored files in `entries[]`, not untracked + files. This flag is mutually exclusive with + `DIR_SHOW_IGNORED_TOO`. `DIR_SHOW_IGNORED_TOO`::: - Similar to `DIR_SHOW_IGNORED`, but return ignored files in `ignored[]` - in addition to untracked files in `entries[]`. + Similar to `DIR_SHOW_IGNORED`, but return ignored files in + `ignored[]` in addition to untracked files in + `entries[]`. This flag is mutually exclusive with + `DIR_SHOW_IGNORED`. `DIR_KEEP_UNTRACKED_CONTENTS`:::
@@ -39,6 +43,21 @@ The notable options are: untracked contents of untracked directories are also returned in `entries[]`. +`DIR_SHOW_IGNORED_TOO_MODE_MATCHING`::: + + Only has meaning if `DIR_SHOW_IGNORED_TOO` is also set; if + this is set, returns ignored files and directories that match + an exclude pattern. If a directory matches an exclude pattern, + then the directory is returned and the contained paths are + not. A directory that does not match an exclude pattern will + not be returned even if all of its contents are ignored. In + this case, the contents are returned as individual entries. ++ +If this is set, files and directories that explicity match an ignore +pattern are reported. Implicity ignored directories (directories that +do not match an ignore pattern, but whose contents are all ignored) +are not reported, instead all of the contents are reported. + `DIR_COLLECT_IGNORED`::: Special mode for git-add. Return ignored files in `ignored[]` and
Signature · 1 line
2.13.6
PATCH v5 4/4 status: test ignored modes
In reply to [email protected]From: Jameson Miller <[email protected]>
Add tests around status reporting ignord files that match an exclude pattern for both --untracked-files=normal and --untracked-files=all.
--- t/t7521-ignored-mode.sh | 233 ++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 233 insertions(+) create mode 100755 t/t7521-ignored-mode.sh
t/t7521-ignored-mode.sh new file +233 -0
@@ -0,0 +1,233 @@ +#!/bin/sh + +test_description='git status ignored modes' + +. ./test-lib.sh + +test_expect_success 'setup initial commit and ignore file' ' + cat >.gitignore <<-\EOF && + *.ign + ignored_dir/ + !*.unignore + EOF + git add . && + git commit -m "Initial commit" +' + +test_expect_success 'Verify behavior of status on directories with ignored files' ' + test_when_finished "git clean -fdx" && + cat >expect <<-\EOF && + ? expect + ? output + ! dir/ignored/ignored_1.ign + ! dir/ignored/ignored_2.ign + ! ignored/ignored_1.ign + ! ignored/ignored_2.ign + EOF + + mkdir -p ignored dir/ignored && + touch ignored/ignored_1.ign ignored/ignored_2.ign \ + dir/ignored/ignored_1.ign dir/ignored/ignored_2.ign && + + git status --porcelain=v2 --ignored=matching --untracked-files=all >output && + test_i18ncmp expect output +' + +test_expect_success 'Verify status behavior on directory with tracked & ignored files' ' + test_when_finished "git clean -fdx && git reset HEAD~1 --hard" && + cat >expect <<-\EOF && + ? expect + ? output + ! dir/tracked_ignored/ignored_1.ign + ! dir/tracked_ignored/ignored_2.ign + ! tracked_ignored/ignored_1.ign + ! tracked_ignored/ignored_2.ign + EOF + + mkdir -p tracked_ignored dir/tracked_ignored && + touch tracked_ignored/tracked_1 tracked_ignored/tracked_2 \ + tracked_ignored/ignored_1.ign tracked_ignored/ignored_2.ign \ + dir/tracked_ignored/tracked_1 dir/tracked_ignored/tracked_2 \ + dir/tracked_ignored/ignored_1.ign dir/tracked_ignored/ignored_2.ign && + + git add tracked_ignored/tracked_1 tracked_ignored/tracked_2 \ + dir/tracked_ignored/tracked_1 dir/tracked_ignored/tracked_2 && + git commit -m "commit tracked files" && + + git status --porcelain=v2 --ignored=matching --untracked-files=all >output && + test_i18ncmp expect output +' + +test_expect_success 'Verify status behavior on directory with untracked and ignored files' ' + test_when_finished "git clean -fdx" && + cat >expect <<-\EOF && + ? dir/untracked_ignored/untracked_1 + ? dir/untracked_ignored/untracked_2 + ? expect + ? output + ? untracked_ignored/untracked_1 + ? untracked_ignored/untracked_2 + ! dir/untracked_ignored/ignored_1.ign + ! dir/untracked_ignored/ignored_2.ign + ! untracked_ignored/ignored_1.ign + ! untracked_ignored/ignored_2.ign + EOF + + mkdir -p untracked_ignored dir/untracked_ignored && + touch untracked_ignored/untracked_1 untracked_ignored/untracked_2 \ + untracked_ignored/ignored_1.ign untracked_ignored/ignored_2.ign \ + dir/untracked_ignored/untracked_1 dir/untracked_ignored/untracked_2 \ + dir/untracked_ignored/ignored_1.ign dir/untracked_ignored/ignored_2.ign && + + git status --porcelain=v2 --ignored=matching --untracked-files=all >output && + test_i18ncmp expect output +' + +test_expect_success 'Verify status matching ignored files on ignored directory' ' + test_when_finished "git clean -fdx" && + cat >expect <<-\EOF && + ? expect + ? output + ! ignored_dir/ + EOF + + mkdir ignored_dir && + touch ignored_dir/ignored_1 ignored_dir/ignored_2 \ + ignored_dir/ignored_1.ign ignored_dir/ignored_2.ign && + + git status --porcelain=v2 --ignored=matching --untracked-files=all >output && + test_i18ncmp expect output +' + +test_expect_success 'Verify status behavior on ignored directory containing tracked file' ' + test_when_finished "git clean -fdx && git reset HEAD~1 --hard" && + cat >expect <<-\EOF && + ? expect + ? output + ! ignored_dir/ignored_1 + ! ignored_dir/ignored_1.ign + ! ignored_dir/ignored_2 + ! ignored_dir/ignored_2.ign + EOF + + mkdir ignored_dir && + touch ignored_dir/ignored_1 ignored_dir/ignored_2 \ + ignored_dir/ignored_1.ign ignored_dir/ignored_2.ign \ + ignored_dir/tracked && + git add -f ignored_dir/tracked && + git commit -m "Force add file in ignored directory" && + git status --porcelain=v2 --ignored=matching --untracked-files=all >output && + test_i18ncmp expect output +' + +test_expect_success 'Verify matching ignored files with --untracked-files=normal' ' + test_when_finished "git clean -fdx" && + cat >expect <<-\EOF && + ? expect + ? output + ? untracked_dir/ + ! ignored_dir/ + ! ignored_files/ignored_1.ign + ! ignored_files/ignored_2.ign + EOF + + mkdir ignored_dir ignored_files untracked_dir && + touch ignored_dir/ignored_1 ignored_dir/ignored_2 \ + ignored_files/ignored_1.ign ignored_files/ignored_2.ign \ + untracked_dir/untracked && + git status --porcelain=v2 --ignored=matching --untracked-files=normal >output && + test_i18ncmp expect output +' + +test_expect_success 'Verify matching ignored files with --untracked-files=normal' ' + test_when_finished "git clean -fdx" && + cat >expect <<-\EOF && + ? expect + ? output + ? untracked_dir/ + ! ignored_dir/ + ! ignored_files/ignored_1.ign + ! ignored_files/ignored_2.ign + EOF + + mkdir ignored_dir ignored_files untracked_dir && + touch ignored_dir/ignored_1 ignored_dir/ignored_2 \ + ignored_files/ignored_1.ign ignored_files/ignored_2.ign \ + untracked_dir/untracked && + git status --porcelain=v2 --ignored=matching --untracked-files=normal >output && + test_i18ncmp expect output +' + +test_expect_success 'Verify status behavior on ignored directory containing tracked file' ' + test_when_finished "git clean -fdx && git reset HEAD~1 --hard" && + cat >expect <<-\EOF && + ? expect + ? output + ! ignored_dir/ignored_1 + ! ignored_dir/ignored_1.ign + ! ignored_dir/ignored_2 + ! ignored_dir/ignored_2.ign + EOF + + mkdir ignored_dir && + touch ignored_dir/ignored_1 ignored_dir/ignored_2 \ + ignored_dir/ignored_1.ign ignored_dir/ignored_2.ign \ + ignored_dir/tracked && + git add -f ignored_dir/tracked && + git commit -m "Force add file in ignored directory" && + git status --porcelain=v2 --ignored=matching --untracked-files=normal >output && + test_i18ncmp expect output +' + +test_expect_success 'Verify behavior of status with --ignored=no' ' + test_when_finished "git clean -fdx" && + cat >expect <<-\EOF && + ? expect + ? output + EOF + + mkdir -p ignored dir/ignored && + touch ignored/ignored_1.ign ignored/ignored_2.ign \ + dir/ignored/ignored_1.ign dir/ignored/ignored_2.ign && + + git status --porcelain=v2 --ignored=no --untracked-files=all >output && + test_i18ncmp expect output +' + +test_expect_success 'Verify behavior of status with --ignored=traditional and --untracked-files=all' ' + test_when_finished "git clean -fdx" && + cat >expect <<-\EOF && + ? expect + ? output + ! dir/ignored/ignored_1.ign + ! dir/ignored/ignored_2.ign + ! ignored/ignored_1.ign + ! ignored/ignored_2.ign + EOF + + mkdir -p ignored dir/ignored && + touch ignored/ignored_1.ign ignored/ignored_2.ign \ + dir/ignored/ignored_1.ign dir/ignored/ignored_2.ign && + + git status --porcelain=v2 --ignored=traditional --untracked-files=all >output && + test_i18ncmp expect output +' + +test_expect_success 'Verify behavior of status with --ignored=traditional and --untracked-files=normal' ' + test_when_finished "git clean -fdx" && + cat >expect <<-\EOF && + ? expect + ? output + ! dir/ + ! ignored/ + EOF + + mkdir -p ignored dir/ignored && + touch ignored/ignored_1.ign ignored/ignored_2.ign \ + dir/ignored/ignored_1.ign dir/ignored/ignored_2.ign && + + git status --porcelain=v2 --ignored=traditional --untracked-files=normal >output && + test_i18ncmp expect output +' + +test_done
Signature · 1 line
2.13.6
Re: [PATCH v5 0/4] status: add option to show ignored files differently
In reply to [email protected]Quoted 2 lines · [email protected] writes:
Only difference from previous version is to update the commit author email to match corporate email address.
Will replace; thanks.