[PATCH] Ensure that commit/status don't stat all files when core.ignoreStat = true

Subsystems: the rest

STALE3716d

19 messages, 6 authors, 2016-06-15 · open the first message on its own page

[PATCH] Ensure that commit/status don't stat all files when core.ignoreStat = true

From: Marius Storm-Olsen <hidden>
Date: 2016-06-15 22:44:39

The core.ignoreStat option is used to assume that files in the
index are unchanged, thus avoiding expensive lstat()s on slow
systems. However, due to refresh_cache_ent still stating but
ignoring the info, and the listing of untracked files in
commit/status, we would still lstat() all the files.

This change shortcuts the refresh_cache_ent(), and makes
commit/status not list untracked files, unless the -u option
is specified.

Signed-off-by: Marius Storm-Olsen <redacted>
---
 read-cache.c |   10 ++++++++++
 wt-status.c  |   11 ++++++++++-
 2 files changed, 20 insertions(+), 1 deletions(-)
diff --git a/read-cache.c b/read-cache.c
index 8b467f8..104e387 100644
--- a/read-cache.c
+++ b/read-cache.c
@@ -882,6 +882,16 @@ static struct cache_entry *refresh_cache_ent(struct index_state *istate,
 	if (ce_uptodate(ce))
 		return ce;
 
+	/*
+	 * assume_unchanged is used to avoid lstats to check if the
+	 * file has been modified. When true, the user need to
+	 * manually update the index.
+	 */
+	if (assume_unchanged) {
+		ce_mark_uptodate(ce);
+		return ce;
+	}
+
 	if (lstat(ce->name, &st) < 0) {
 		if (err)
 			*err = errno;
diff --git a/wt-status.c b/wt-status.c
index a44c543..72db466 100644
--- a/wt-status.c
+++ b/wt-status.c
@@ -342,7 +342,14 @@ void wt_status_print(struct wt_status *s)
 	wt_status_print_changed(s);
 	if (wt_status_submodule_summary)
 		wt_status_print_submodule_summary(s);
-	wt_status_print_untracked(s);
+
+	if (assume_unchanged && !s->untracked) {
+		if (s->commitable)
+			fprintf(s->fp, "# Untracked files not listed (use -u option to show untracked files)\n");
+		/* !s->commitable message displayed below */
+	}
+	else
+		wt_status_print_untracked(s);
 
 	if (s->verbose && !s->is_initial)
 		wt_status_print_verbose(s);
@@ -357,6 +364,8 @@ void wt_status_print(struct wt_status *s)
 			printf("nothing added to commit but untracked files present (use \"git add\" to track)\n");
 		else if (s->is_initial)
 			printf("nothing to commit (create/copy files and use \"git add\" to track)\n");
+		else if (assume_unchanged && !s->untracked)
+			printf("nothing to commit (use -u to show untracked files)\n");
 		else
 			printf("nothing to commit (working directory clean)\n");
 	}
-- 
1.5.5.1.501.gefb4

Re: [PATCH] Ensure that commit/status don't stat all files when core.ignoreStat = true

From: Junio C Hamano <hidden>
Date: 2016-06-15 22:44:39

Marius Storm-Olsen [off-list ref] writes:
quoted hunk
diff --git a/read-cache.c b/read-cache.c
index 8b467f8..104e387 100644
--- a/read-cache.c
+++ b/read-cache.c
@@ -882,6 +882,16 @@ static struct cache_entry *refresh_cache_ent(struct index_state *istate,
 	if (ce_uptodate(ce))
 		return ce;
 
+	/*
+	 * assume_unchanged is used to avoid lstats to check if the
+	 * file has been modified. When true, the user need to
+	 * manually update the index.
+	 */
+	if (assume_unchanged) {
+		ce_mark_uptodate(ce);
+		return ce;
+	}
+
The description for core.ignorestat in Documentation/config.txt is quite
bogus.  That single bit does _not_ determine globally if we lstat(2) or
not.  The description in Documentation/git-update-index.txt about it (look
for the section "Using assume unchanged bit") accurately describes what it
is meant to do.  The rules are:

 - (ce->ce_flags & CE_VALID) is the only thing that decides if we can omit
   lstat(2) for _that particular path_.  There is no global "we would
   never ever run lstat(2)" option, and core.ignorestat certainly isn't
   it.

 - you can use the assume-unchanged mechanism without setting
   core.ignorestat.  You flip the CE_VALID bit for selected paths manually
   and forget about them afterwards, when you would want all of your usual
   "active" changes noticed by git, while skipping lstat(2) overhead in
   areas you are not interested in.

 - when you say "git update-index" (or "git add") for a path, if you have
   core.ignorestat set, that path is automatically marked with CE_VALID,
   so that later lstat(2) will be omitted for that particular path.  IOW,
   by having core.ignorestat set, you are promising that you are not going
   to _further_ change the work tree contents _without_ telling git --- or
   at least you are promising that you _will_ tell git if you change it
   when it matters.  But you have to tell git at least once what the
   contents are.

Would it be sufficient for what you are trying to do if you changed that
test to something like this?

        /*
         * CE_VALID means the user promised us that the change to
         * the work tree does not matter and told us not to worry.
         */
	if (!ignore_valid && (ce->ce_flags & CE_VALID)) {
        	ce_mark_uptodate(ce);
		return ce;
	}
quoted hunk
diff --git a/wt-status.c b/wt-status.c
index a44c543..72db466 100644
--- a/wt-status.c
+++ b/wt-status.c
@@ -342,7 +342,14 @@ void wt_status_print(struct wt_status *s)
 	wt_status_print_changed(s);
 	if (wt_status_submodule_summary)
 		wt_status_print_submodule_summary(s);
-	wt_status_print_untracked(s);
+
+	if (assume_unchanged && !s->untracked) {
+		if (s->commitable)
+			fprintf(s->fp, "# Untracked files not listed (use -u option to show untracked files)\n");
+		/* !s->commitable message displayed below */
+	}
+	else
+		wt_status_print_untracked(s);
 
 	if (s->verbose && !s->is_initial)
 		wt_status_print_verbose(s);
@@ -357,6 +364,8 @@ void wt_status_print(struct wt_status *s)
 			printf("nothing added to commit but untracked files present (use \"git add\" to track)\n");
 		else if (s->is_initial)
 			printf("nothing to commit (create/copy files and use \"git add\" to track)\n");
+		else if (assume_unchanged && !s->untracked)
+			printf("nothing to commit (use -u to show untracked files)\n");
 		else
 			printf("nothing to commit (working directory clean)\n");
 	}
The core.ignorestat variable does not have anything to do with showing
untracked files.  It is about "do we mark the added path as CE_VALID,
meaning that we do not have to lstat(2) them?"  IOW, it is about tracked
files.

While it might be useful in certain workflows to ignore untracked files, I
do not think it is a good idea to overload such an unrelated meaning to
the variable.

Re: [PATCH] Ensure that commit/status don't stat all files when core.ignoreStat = true

From: Marius Storm-Olsen <hidden>
Date: 2016-06-15 22:44:39

Junio C Hamano said the following on 27.05.2008 22:00:
Marius Storm-Olsen [off-list ref] writes:
The description for core.ignorestat in Documentation/config.txt is quite
bogus.  That single bit does _not_ determine globally if we lstat(2) or
not.  The description in Documentation/git-update-index.txt about it (look
for the section "Using assume unchanged bit") accurately describes what it
is meant to do.  The rules are:
Aha! Thanks for the detailed explanation of core.ignoreStat. Given 
your description, the patch is certainly bogus.
Would it be sufficient for what you are trying to do if you changed that
test to something like this?

        /*
         * CE_VALID means the user promised us that the change to
         * the work tree does not matter and told us not to worry.
         */
	if (!ignore_valid && (ce->ce_flags & CE_VALID)) {
        	ce_mark_uptodate(ce);
		return ce;
	}
I'll give it a shot tomorrow, to see how it affects my use-cases.
Thanks.

quoted
diff --git a/wt-status.c b/wt-status.c
index a44c543..72db466 100644
--- a/wt-status.c
+++ b/wt-status.c
...
The core.ignorestat variable does not have anything to do with showing
untracked files.  It is about "do we mark the added path as CE_VALID,
meaning that we do not have to lstat(2) them?"  IOW, it is about tracked
files.

While it might be useful in certain workflows to ignore untracked files, I
do not think it is a good idea to overload such an unrelated meaning to
the variable.
Indeed. I'll resend a new patch tomorrow with a new variable which 
will only affect the stat'ing of untracked files, if you think that's 
reasonable. IMO, we certainly need a way of avoiding to stat the whole 
filetree on commits and status. I mean, that's what you have the -u 
option for, right? :-) In any case, an opt-in feature, of course.

Thanks for checking the patch!

--
.marius

[PATCH 1/3] Clearify the documentation for core.ignoreStat

From: Marius Storm-Olsen <hidden>
Date: 2016-06-15 22:44:39

The previous documentation didn't make it clear that the
"assume unchanged" was on per file basis, and not a global
flag.

Signed-off-by: Marius Storm-Olsen <redacted>
---
 Documentation/config.txt |   11 +++++++----
 1 files changed, 7 insertions(+), 4 deletions(-)
diff --git a/Documentation/config.txt b/Documentation/config.txt
index c298dc2..5331b45 100644
--- a/Documentation/config.txt
+++ b/Documentation/config.txt
@@ -205,10 +205,13 @@ Can be overridden by the 'GIT_PROXY_COMMAND' environment variable
 handling).
 
 core.ignoreStat::
-	The working copy files are assumed to stay unchanged until you
-	mark them otherwise manually - Git will not detect the file changes
-	by lstat() calls. This is useful on systems where those are very
-	slow, such as Microsoft Windows.  See linkgit:git-update-index[1].
+	If true, commands which modify both the working tree and the index
+	will mark the updated paths with the "assume unchanged" bit in the
+	index. These marked files are then assumed to stay unchanged in the
+	working copy, until you	mark them otherwise manually - Git will not
+	detect the file changes	by lstat() calls. This is useful on systems
+	where those are very slow, such as Microsoft Windows.
+	See linkgit:git-update-index[1].
 	False by default.
 
 core.preferSymlinkRefs::
-- 
1.5.5.GIT

[PATCH 2/3] Introduce core.showUntrackedFiles to make it possible to disable showing of untracked files.

From: Simon Hausmann <hidden>
Date: 2016-06-15 22:44:39

Determining untracked files can be a very slow operation on large trees. This commit introduces
a configuration variable that makes it possible to disable showing of untracked files by default
as well as a -U commandline option to override this.

Signed-off-by: Simon Hausmann <redacted>
Signed-off-by: Marius Storm-Olsen <redacted>
---
 Documentation/config.txt     |    5 +++++
 Documentation/git-commit.txt |   11 ++++++++---
 builtin-commit.c             |    1 +
 config.c                     |    7 +++++++
 environment.c                |    1 +
 wt-status.c                  |    7 ++++++-
 wt-status.h                  |    1 +
 7 files changed, 29 insertions(+), 4 deletions(-)
diff --git a/Documentation/config.txt b/Documentation/config.txt
index 5331b45..e42ead0 100644
--- a/Documentation/config.txt
+++ b/Documentation/config.txt
@@ -214,6 +214,11 @@ core.ignoreStat::
 	See linkgit:git-update-index[1].
 	False by default.
 
+core.showUntrackedFiles::
+	A boolean to enable/disable displaying untracked files in the output
+	of linkgit:git-status[1] and linkgit:git-commit[1].
+	Defaults to true.
+
 core.preferSymlinkRefs::
 	Instead of the default "symref" format for HEAD
 	and other symbolic reference files, use symbolic links.
diff --git a/Documentation/git-commit.txt b/Documentation/git-commit.txt
index c3c9f5b..a3174e4 100644
--- a/Documentation/git-commit.txt
+++ b/Documentation/git-commit.txt
@@ -150,12 +150,17 @@ but can be used to amend a merge commit.
 	the last commit without committing changes that have
 	already been staged.
 
+-U|--untracked::
+	Show untracked files, in the "Untracked files:" section of commit
+	message template.
+	This option overrides the core.showUntrackedFiles
+	configuration option, and is normally not needed.
+
 -u|--untracked-files::
 	Show all untracked files, also those in uninteresting
-	directories, in the "Untracked files:" section of commit
-	message template.  Without this option only its name and
+	directories.  Without this option only its name and
 	a trailing slash are displayed for each untracked
-	directory.
+	directory. This option implies --untracked.
 
 -v|--verbose::
 	Show unified diff between the HEAD commit and what
diff --git a/builtin-commit.c b/builtin-commit.c
index b294c1f..28cc170 100644
--- a/builtin-commit.c
+++ b/builtin-commit.c
@@ -103,6 +103,7 @@ static struct option builtin_commit_options[] = {
 	OPT_BOOLEAN('n', "no-verify", &no_verify, "bypass pre-commit hook"),
 	OPT_BOOLEAN(0, "amend", &amend, "amend previous commit"),
 	OPT_BOOLEAN('u', "untracked-files", &untracked_files, "show all untracked files"),
+	OPT_BOOLEAN('U', "untracked", &show_untracked_files, "show untracked files"),
 	OPT_BOOLEAN(0, "allow-empty", &allow_empty, "ok to record an empty change"),
 	OPT_STRING(0, "cleanup", &cleanup_arg, "default", "how to strip spaces and #comments from message"),
 
diff --git a/config.c b/config.c
index c2f2bbb..ba3efd1 100644
--- a/config.c
+++ b/config.c
@@ -7,6 +7,7 @@
  */
 #include "cache.h"
 #include "exec_cmd.h"
+#include "wt-status.h"
 
 #define MAXNAME (256)
 
@@ -511,6 +512,12 @@ int git_default_config(const char *var, const char *value, void *dummy)
 			return error("Malformed value for %s", var);
 		return 0;
 	}
+	if (!strcmp(var, "core.showuntrackedfiles")) {
+		if (!value)
+			return config_error_nonbool(var);
+		show_untracked_files = git_config_bool(var, value);
+		return 0;
+	}
 
 	/* Add other config variables here and to Documentation/config.txt. */
 	return 0;
diff --git a/environment.c b/environment.c
index 73feb2d..210ae17 100644
--- a/environment.c
+++ b/environment.c
@@ -41,6 +41,7 @@ enum safe_crlf safe_crlf = SAFE_CRLF_WARN;
 unsigned whitespace_rule_cfg = WS_DEFAULT_RULE;
 enum branch_track git_branch_track = BRANCH_TRACK_REMOTE;
 enum rebase_setup_type autorebase = AUTOREBASE_NEVER;
+int show_untracked_files = 1;
 
 /* This is set by setup_git_dir_gently() and/or git_default_config() */
 char *git_work_tree_cfg;
diff --git a/wt-status.c b/wt-status.c
index 5b4d74c..819fe2d 100644
--- a/wt-status.c
+++ b/wt-status.c
@@ -347,7 +347,10 @@ void wt_status_print(struct wt_status *s)
 	wt_status_print_changed(s);
 	if (wt_status_submodule_summary)
 		wt_status_print_submodule_summary(s);
-	wt_status_print_untracked(s);
+	if (show_untracked_files)
+		wt_status_print_untracked(s);
+	else if (s->commitable)
+		fprintf(s->fp, "# Untracked files not listed (use -U option to show untracked files)\n");
 
 	if (s->verbose && !s->is_initial)
 		wt_status_print_verbose(s);
@@ -362,6 +365,8 @@ void wt_status_print(struct wt_status *s)
 			printf("nothing added to commit but untracked files present (use \"git add\" to track)\n");
 		else if (s->is_initial)
 			printf("nothing to commit (create/copy files and use \"git add\" to track)\n");
+		else if (!show_untracked_files)
+			printf("nothing to commit (use -U to show untracked files)\n");
 		else
 			printf("nothing to commit (working directory clean)\n");
 	}
diff --git a/wt-status.h b/wt-status.h
index 597c7ea..4b643b4 100644
--- a/wt-status.h
+++ b/wt-status.h
@@ -33,5 +33,6 @@ extern int wt_status_use_color;
 extern int wt_status_relative_paths;
 void wt_status_prepare(struct wt_status *s);
 void wt_status_print(struct wt_status *s);
+extern int show_untracked_files;
 
 #endif /* STATUS_H */
-- 
1.5.5.GIT

[PATCH 3/3] Add shortcut in refresh_cache_ent() for marked entries.

From: Marius Storm-Olsen <hidden>
Date: 2016-06-15 22:44:39

When a cache entry has been marked as CE_VALID, the user has
promised us that any change in the work tree does not matter.
Just mark the entry as up-to-date, and continue.

Done-by: Junio C Hamano [off-list ref]
Signed-off-by: Marius Storm-Olsen <redacted>
---
 read-cache.c |    9 +++++++++
 1 files changed, 9 insertions(+), 0 deletions(-)
diff --git a/read-cache.c b/read-cache.c
index ac9a8e7..8e5fbb6 100644
--- a/read-cache.c
+++ b/read-cache.c
@@ -893,6 +893,15 @@ static struct cache_entry *refresh_cache_ent(struct index_state *istate,
 	if (ce_uptodate(ce))
 		return ce;
 
+	/*
+	 * CE_VALID means the user promised us that the change to
+	 * the work tree does not matter and told us not to worry.
+	 */
+	if (!ignore_valid && (ce->ce_flags & CE_VALID)) {
+		ce_mark_uptodate(ce);
+		return ce;
+	}
+
 	if (lstat(ce->name, &st) < 0) {
 		if (err)
 			*err = errno;
-- 
1.5.5.GIT

Re: [PATCH 2/3] Introduce core.showUntrackedFiles to make it possible to disable showing of untracked files.

From: Marius Storm-Olsen <hidden>
Date: 2016-06-15 22:44:39

(Err.. Sent from me, and should have had a:)
From: Simon Hausmann <redacted>
Determining untracked files can be a very slow operation on large trees. This commit introduces
a configuration variable that makes it possible to disable showing of untracked files by default
as well as a -U commandline option to override this.

Signed-off-by: Simon Hausmann <redacted>
Signed-off-by: Marius Storm-Olsen <redacted>
Sorry for the confusion...

-- 
.marius [@trolltech.com]
'if you know what you're doing, it's not research'

Re: [PATCH 3/3] Add shortcut in refresh_cache_ent() for marked entries.

From: Marius Storm-Olsen <hidden>
Date: 2016-06-15 22:44:39

Marius Storm-Olsen said the following on 30.05.2008 14:38:
When a cache entry has been marked as CE_VALID, the user has
promised us that any change in the work tree does not matter.
Just mark the entry as up-to-date, and continue.

Done-by: Junio C Hamano [off-list ref]
Signed-off-by: Marius Storm-Olsen <redacted>
This patch actually cuts the commit/status time in half for me, on my 
Windows machine, when the whole work tree is validated, and 
core.ignoreStat == true.

-- 
.marius [@trolltech.com]
'if you know what you're doing, it's not research'

Re: [PATCH 2/3] Introduce core.showUntrackedFiles to make it possible to disable showing of untracked files.

From: Marius Storm-Olsen <hidden>
Date: 2016-06-15 22:44:39

Simon Hausmann said the following on 30.05.2008 10:54:
Determining untracked files can be a very slow operation on large trees. This commit introduces
a configuration variable that makes it possible to disable showing of untracked files by default
as well as a -U commandline option to override this.

Signed-off-by: Simon Hausmann <redacted>
Signed-off-by: Marius Storm-Olsen <redacted>
---
This gives me ~80% improvement on commit/status. Reasonable, since my 
work tree nearly doubles in size on a full build.

-- 
.marius [@trolltech.com]
'if you know what you're doing, it's not research'

Re: [PATCH 2/3] Introduce core.showUntrackedFiles to make it possible to disable showing of untracked files.

From: Junio C Hamano <hidden>
Date: 2016-06-15 22:44:40

Simon Hausmann [off-list ref] writes:
quoted hunk
diff --git a/Documentation/config.txt b/Documentation/config.txt
index 5331b45..e42ead0 100644
--- a/Documentation/config.txt
+++ b/Documentation/config.txt
@@ -214,6 +214,11 @@ core.ignoreStat::
 	See linkgit:git-update-index[1].
 	False by default.
 
+core.showUntrackedFiles::
+	A boolean to enable/disable displaying untracked files in the output
+	of linkgit:git-status[1] and linkgit:git-commit[1].
+	Defaults to true.
+
This does not belong to the 'core.*', which is about the low-level
plumbing.  It perhaps could live in 'status.*' section, but I think you
can do better than introducing this as a boolean.
quoted hunk
diff --git a/Documentation/git-commit.txt b/Documentation/git-commit.txt
index c3c9f5b..a3174e4 100644
--- a/Documentation/git-commit.txt
+++ b/Documentation/git-commit.txt
@@ -150,12 +150,17 @@ but can be used to amend a merge commit.
 	the last commit without committing changes that have
 	already been staged.
 
+-U|--untracked::
+	Show untracked files, in the "Untracked files:" section of commit
+	message template.
+	This option overrides the core.showUntrackedFiles
+	configuration option, and is normally not needed.
+
 -u|--untracked-files::
 	Show all untracked files, also those in uninteresting
-	directories, in the "Untracked files:" section of commit
-	message template.  Without this option only its name and
+	directories.  Without this option only its name and
 	a trailing slash are displayed for each untracked
-	directory.
+	directory. This option implies --untracked.
I wonder if we really need a new option that is half independent to an
existing one.

Step back a bit and think.  You have three choice:

 (1) Do not show untracked files at all; or

 (2) Show untracked but summarize untracked directories; or

 (3) Show all untracked files.

We have had (2) and (3) so far, and you are adding (1) as a new feature.
How about allowing -u on the command line to take an optional parameter to
say what kind the user wants?  I.e.

        -u=none		shows nothing (i.e. (1))
        -u=normal	shows summarized report (i.e. (2))
	-u=all		shows all untracked files (i.e. (3))

And (3) can also be spelled as "-u without parameter"; absense of -u
anywhere defaults to (2).  That would be the first patch.

Then, in the second patch, you can add support to 'status.showuntracked';
you pretend that it is set to 'normal' if it is not defined in the
configuration file.

Hmm?

Re: [PATCH 2/3] Introduce core.showUntrackedFiles to make it possible to disable showing of untracked files.

From: Marius Storm-Olsen <hidden>
Date: 2016-06-15 22:44:40

Junio C Hamano wrote:
I wonder if we really need a new option that is half independent to an
existing one.
...
        -u=none		shows nothing (i.e. (1))
        -u=normal	shows summarized report (i.e. (2))
	-u=all		shows all untracked files (i.e. (3))
...
Then, in the second patch, you can add support to 'status.showuntracked';
you pretend that it is set to 'normal' if it is not defined in the
configuration file.

Hmm?
Sounds good to me. Will redo the patch. Thanks!

--
.marius

[PATCH] Add configuration option for default untracked files mode

From: Marius Storm-Olsen <hidden>
Date: 2016-06-15 22:44:40

By default, the untracked files mode for commit/status is 'normal'.

Signed-off-by: Marius Storm-Olsen <redacted>
---
 Documentation/config.txt     |   15 +++++++++++++++
 Documentation/git-commit.txt |    4 +++-
 wt-status.c                  |   13 +++++++++++++
 3 files changed, 31 insertions(+), 1 deletions(-)
diff --git a/Documentation/config.txt b/Documentation/config.txt
index 5331b45..12c0be3 100644
--- a/Documentation/config.txt
+++ b/Documentation/config.txt
@@ -1013,6 +1013,21 @@ status.relativePaths::
 	relative to the repository root (this was the default for git
 	prior to v1.5.4).
 
+status.showUntrackedFiles::
+	By default, linkgit:git-status[1] and linkgit:git-commit[1] show
+	files which are not currently tracked by Git. Directories which
+	contain only untracked files, are shown with the directory name
+	only. Showing untracked files means that Git needs to lstat() all
+	all the files in the whole repository, which might be slow on some
+	systems. So, this variable controls how the commands displays
+	the untracked files. Possible values are:
+		none   - Show no untracked files
+		normal - Shows untracked files and directories
+		all    - Shows also individual files in untracked directories.
+	If this variable is not specified, it defaults to 'normal'.
+	This variable can be overridden with the -u|--untracked-files option
+	of linkgit:git-status[1] and linkgit:git-commit[1].
+
 tar.umask::
 	This variable can be used to restrict the permission bits of
 	tar archive entries.  The default is 0002, which turns off the
diff --git a/Documentation/git-commit.txt b/Documentation/git-commit.txt
index d8a3aa3..bcbc2c2 100644
--- a/Documentation/git-commit.txt
+++ b/Documentation/git-commit.txt
@@ -158,7 +158,9 @@ but can be used to amend a merge commit.
 		normal - Shows untracked files and directories
 		all    - Also shows individual files in untracked directories.
 	If the mode parameter is not specified, the defaults is
-	'all'.
+	'all'. See linkgit:git-config[1] for configuration variable
+	used to change the default for when the option is not
+	specified.
 
 -v|--verbose::
 	Show unified diff between the HEAD commit and what
diff --git a/wt-status.c b/wt-status.c
index 742a474..9ffe1c3 100644
--- a/wt-status.c
+++ b/wt-status.c
@@ -397,5 +397,18 @@ int git_status_config(const char *k, const char *v, void *cb)
 		wt_status_relative_paths = git_config_bool(k, v);
 		return 0;
 	}
+	if (!strcmp(k, "status.showuntrackedfiles")) {
+		if (!v)
+			return config_error_nonbool(v);
+		else if (!strcmp(v, "none"))
+			show_untracked_files = NONE_UNTRACKED;
+		else if (!strcmp(v, "normal"))
+			show_untracked_files = NORMAL_UNTRACKED;
+		else if (!strcmp(v, "all"))
+			show_untracked_files = ALL_UNTRACKED;
+		else
+			return error("Invalid untracked files mode '%s'", v);
+		return 0;
+	}
 	return git_color_default_config(k, v, cb);
 }
-- 
1.5.5.GIT

[PATCH] Add an optional <mode> argument to commit/status -u|--untracked-files option

From: Marius Storm-Olsen <hidden>
Date: 2016-06-15 22:44:40

Determining untracked files can be a very slow operation on large trees.
This commit adds a <mode> argument, which allows you to avoid showing the
untracked files in a repository. Possible options are:
    none   - Show no untracked files
    normal - Show untracked files and directories
    all    - Show all untracked files

If the optional argument is not specified, the option defaults to 'all'.

Signed-off-by: Marius Storm-Olsen <redacted>
---
 Documentation/git-commit.txt |   15 +++++++++------
 builtin-commit.c             |   18 +++++++++++++++---
 wt-status.c                  |    8 +++++++-
 wt-status.h                  |    7 +++++++
 4 files changed, 38 insertions(+), 10 deletions(-)
diff --git a/Documentation/git-commit.txt b/Documentation/git-commit.txt
index c3c9f5b..d8a3aa3 100644
--- a/Documentation/git-commit.txt
+++ b/Documentation/git-commit.txt
@@ -150,12 +150,15 @@ but can be used to amend a merge commit.
 	the last commit without committing changes that have
 	already been staged.
 
--u|--untracked-files::
-	Show all untracked files, also those in uninteresting
-	directories, in the "Untracked files:" section of commit
-	message template.  Without this option only its name and
-	a trailing slash are displayed for each untracked
-	directory.
+-u[<mode>]|--untracked-files[=<mode>]::
+	Show all untracked files.
+	The mode parameter is optional, and is used to specify
+	the handling of untracked files. The possible options are:
+		none   - Show no untracked files
+		normal - Shows untracked files and directories
+		all    - Also shows individual files in untracked directories.
+	If the mode parameter is not specified, the defaults is
+	'all'.
 
 -v|--verbose::
 	Show unified diff between the HEAD commit and what
diff --git a/builtin-commit.c b/builtin-commit.c
index 90200ed..28db2ba 100644
--- a/builtin-commit.c
+++ b/builtin-commit.c
@@ -49,7 +49,8 @@ static char *logfile, *force_author, *template_file;
 static char *edit_message, *use_message;
 static char *author_name, *author_email, *author_date;
 static int all, edit_flag, also, interactive, only, amend, signoff;
-static int quiet, verbose, untracked_files, no_verify, allow_empty;
+static int quiet, verbose, no_verify, allow_empty;
+static char *untracked_files_arg;
 /*
  * The default commit message cleanup mode will remove the lines
  * beginning with # (shell comments) and leading and trailing
@@ -102,7 +103,7 @@ static struct option builtin_commit_options[] = {
 	OPT_BOOLEAN('o', "only", &only, "commit only specified files"),
 	OPT_BOOLEAN('n', "no-verify", &no_verify, "bypass pre-commit hook"),
 	OPT_BOOLEAN(0, "amend", &amend, "amend previous commit"),
-	OPT_BOOLEAN('u', "untracked-files", &untracked_files, "show all untracked files"),
+	{ OPTION_STRING, 'u', "untracked-files", &untracked_files_arg, "mode", "show untracked files, optional modes: all, normal, none. (Default: all)", PARSE_OPT_OPTARG, NULL, (int)"all" },
 	OPT_BOOLEAN(0, "allow-empty", &allow_empty, "ok to record an empty change"),
 	OPT_STRING(0, "cleanup", &cleanup_arg, "default", "how to strip spaces and #comments from message"),
 
@@ -347,7 +348,7 @@ static int run_status(FILE *fp, const char *index_file, const char *prefix, int
 		s.reference = "HEAD^1";
 	}
 	s.verbose = verbose;
-	s.untracked = untracked_files;
+	s.untracked = (show_untracked_files == ALL_UNTRACKED);
 	s.index_file = index_file;
 	s.fp = fp;
 	s.nowarn = nowarn;
@@ -795,6 +796,17 @@ static int parse_and_validate_options(int argc, const char *argv[],
 	else
 		die("Invalid cleanup mode %s", cleanup_arg);
 
+	if (!untracked_files_arg)
+		; /* default already initialized */
+	else if (!strcmp(untracked_files_arg, "none"))
+		show_untracked_files = NONE_UNTRACKED;
+	else if (!strcmp(untracked_files_arg, "normal"))
+		show_untracked_files = NORMAL_UNTRACKED;
+	else if (!strcmp(untracked_files_arg, "all"))
+		show_untracked_files = ALL_UNTRACKED;
+	else
+		die("Invalid untracked files mode '%s'", untracked_files_arg);
+
 	if (all && argc > 0)
 		die("Paths with -a does not make sense.");
 	else if (interactive && argc > 0)
diff --git a/wt-status.c b/wt-status.c
index 5b4d74c..742a474 100644
--- a/wt-status.c
+++ b/wt-status.c
@@ -27,6 +27,7 @@ static const char use_add_rm_msg[] =
 "use \"git add/rm <file>...\" to update what will be committed";
 static const char use_add_to_include_msg[] =
 "use \"git add <file>...\" to include in what will be committed";
+enum untracked_status_type show_untracked_files = NORMAL_UNTRACKED;
 
 static int parse_status_slot(const char *var, int offset)
 {
@@ -347,7 +348,10 @@ void wt_status_print(struct wt_status *s)
 	wt_status_print_changed(s);
 	if (wt_status_submodule_summary)
 		wt_status_print_submodule_summary(s);
-	wt_status_print_untracked(s);
+	if (show_untracked_files)
+		wt_status_print_untracked(s);
+	else if (s->commitable)
+		fprintf(s->fp, "# Untracked files not listed (use -u option to show untracked files)\n");
 
 	if (s->verbose && !s->is_initial)
 		wt_status_print_verbose(s);
@@ -362,6 +366,8 @@ void wt_status_print(struct wt_status *s)
 			printf("nothing added to commit but untracked files present (use \"git add\" to track)\n");
 		else if (s->is_initial)
 			printf("nothing to commit (create/copy files and use \"git add\" to track)\n");
+		else if (!show_untracked_files)
+			printf("nothing to commit (use -u to show untracked files)\n");
 		else
 			printf("nothing to commit (working directory clean)\n");
 	}
diff --git a/wt-status.h b/wt-status.h
index 597c7ea..343d975 100644
--- a/wt-status.h
+++ b/wt-status.h
@@ -11,6 +11,13 @@ enum color_wt_status {
 	WT_STATUS_NOBRANCH,
 };
 
+enum untracked_status_type {
+	NONE_UNTRACKED,
+	NORMAL_UNTRACKED,
+	ALL_UNTRACKED
+};
+extern enum untracked_status_type show_untracked_files;
+
 struct wt_status {
 	int is_initial;
 	char *branch;
-- 
1.5.5.GIT

Re: [PATCH] Add an optional <mode> argument to commit/status -u|--untracked-files option

From: Jeff King <hidden>
Date: 2016-06-15 22:44:40

On Tue, Jun 03, 2008 at 03:09:10PM +0200, Marius Storm-Olsen wrote:
+-u[<mode>]|--untracked-files[=<mode>]::
+	Show all untracked files.
+	The mode parameter is optional, and is used to specify
+	the handling of untracked files. The possible options are:
+		none   - Show no untracked files
+		normal - Shows untracked files and directories
+		all    - Also shows individual files in untracked directories.
+	If the mode parameter is not specified, the defaults is
+	'all'.
Hmm. Doesn't this change bundling semantics of "git commit -us"? Do we
care?

-Peff

Re: [PATCH] Add an optional <mode> argument to commit/status -u|--untracked-files option

From: Marius Storm-Olsen <hidden>
Date: 2016-06-15 22:44:40

Jeff King said the following on 03.06.2008 22:14:
On Tue, Jun 03, 2008 at 03:09:10PM +0200, Marius Storm-Olsen wrote:
quoted
+-u[<mode>]|--untracked-files[=<mode>]::
+	Show all untracked files.
+	The mode parameter is optional, and is used to specify
+	the handling of untracked files. The possible options are:
+		none   - Show no untracked files
+		normal - Shows untracked files and directories
+		all    - Also shows individual files in untracked directories.
+	If the mode parameter is not specified, the defaults is
+	'all'.
Hmm. Doesn't this change bundling semantics of "git commit -us"? Do we
care?
You are right. This is the joy of the parse-options() handling of 
short-options with optional arguments.

-us before meant:
     1) commit
     2) show all untracked files
     3) sign-of the commit

I guess it would be possible to reparse the options without the -u, if 
the argument is not one of the three (none,normal,all), but I'm not 
sure it's _that_ critical. Opinions?

--
.marius

Re: [PATCH] Add an optional <mode> argument to commit/status -u|--untracked-files option

From: Jeff King <hidden>
Date: 2016-06-15 22:44:41

On Tue, Jun 03, 2008 at 11:17:28PM +0200, Marius Storm-Olsen wrote:
You are right. This is the joy of the parse-options() handling of  
short-options with optional arguments.

-us before meant:
    1) commit
    2) show all untracked files
    3) sign-of the commit

I guess it would be possible to reparse the options without the -u, if  
the argument is not one of the three (none,normal,all), but I'm not sure 
it's _that_ critical. Opinions?
I think it would be reasonable to make "-u" mean the same as always, and
for "--untracked-files" to have an optional argument. There isn't direct
support for that construct in parse_options, but you could just make it
two separate options that happen to tweak the same value (though I guess
they would be displayed separately in the auto-generated usage).

Some GNU utils use this strategy to extend existing options. E.g., "ls
-p" comes from XSI and takes no argument, but the long-option form of
--indicator-style=<none|slash|file-type|classify> gives more options.

That makes it a little less pleasant to type the extended version, but
compatibility is maintained.  Though I tend to wonder about this option
in particular...isn't this generally a user preference? Should it
perhaps be found in the config file instead?

-Peff

Re: [PATCH] Add an optional <mode> argument to commit/status -u|--untracked-files option

From: しらいしななこ <hidden>
Date: 2016-06-15 22:44:41

Quoting Marius Storm-Olsen [off-list ref] writes:
Jeff King said the following on 03.06.2008 22:14:
quoted
On Tue, Jun 03, 2008 at 03:09:10PM +0200, Marius Storm-Olsen wrote:
quoted
+-u[<mode>]|--untracked-files[=<mode>]::
+	Show all untracked files.
+	The mode parameter is optional, and is used to specify
+	the handling of untracked files. The possible options are:
+		none   - Show no untracked files
+		normal - Shows untracked files and directories
+		all    - Also shows individual files in untracked directories.
+	If the mode parameter is not specified, the defaults is
+	'all'.
Hmm. Doesn't this change bundling semantics of "git commit -us"? Do we
care?
You are right. This is the joy of the parse-options() handling of
short-options with optional arguments.

-us before meant:
    1) commit
    2) show all untracked files
    3) sign-of the commit

I guess it would be possible to reparse the options without the -u, if
the argument is not one of the three (none,normal,all), but I'm not
sure it's _that_ critical. Opinions?
Isn't the second bullet point in the description in:

    http://www.kernel.org/pub/software/scm/git/docs/gitcli.html

good enough?

-- 
Nanako Shiraishi
http://ivory.ap.teacup.com/nanako3/

----------------------------------------------------------------------
Find out how you can get spam free email.
http://www.bluebottle.com/tag/3

Re: [PATCH] Add an optional <mode> argument to commit/status -u|--untracked-files option

From: Alex Riesen <hidden>
Date: 2016-06-15 22:44:42

Marius Storm-Olsen, Tue, Jun 03, 2008 15:09:10 +0200:
Determining untracked files can be a very slow operation on large trees.
This commit adds a <mode> argument, which allows you to avoid showing the
untracked files in a repository. Possible options are:
    none   - Show no untracked files
    normal - Show untracked files and directories
    all    - Show all untracked files

If the optional argument is not specified, the option defaults to 'all'.
Looks very familiar:

    http://thread.gmane.org/gmane.comp.version-control.git/66183

Re: [PATCH] Add an optional <mode> argument to commit/status -u|--untracked-files option

From: Marius Storm-Olsen <hidden>
Date: 2016-06-15 22:44:42

Alex Riesen said the following on 06.06.2008 08:32:
Marius Storm-Olsen, Tue, Jun 03, 2008 15:09:10 +0200:
quoted
Determining untracked files can be a very slow operation on large trees.
This commit adds a <mode> argument, which allows you to avoid showing the
untracked files in a repository. Possible options are:
    none   - Show no untracked files
    normal - Show untracked files and directories
    all    - Show all untracked files

If the optional argument is not specified, the option defaults to 'all'.
Looks very familiar:

    http://thread.gmane.org/gmane.comp.version-control.git/66183
Similar, but not quite. This patch doesn't care about the index, just 
providing the option to avoid looking for untracked files.

Improving the index handling was done in the other patch
     Add shortcut in refresh_cache_ent() for marked entries.
(which is already in master, aa9349d4), so the core.ignoreStat option 
is more effective.

-- 
.marius [@trolltech.com]
'if you know what you're doing, it's not research'
Keyboard shortcuts
hback out one level
jnext message in thread
kprevious message in thread
ldrill in
Escclose help / fold thread tree
?toggle this help