Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Support untracked cache with '--untracked-files=all' if configured #985

Closed
wants to merge 2 commits into from

Conversation

TaoK
Copy link

@TaoK TaoK commented Jun 23, 2021

Make it possible for users of the -uall flag to git status, either by preference or by need (eg UI tooling), to benefit from the untracked cache when they set their 'status.showuntrackedfiles' config setting to 'all'. This is especially useful for large repos in Windows, where without untracked cache "git status" times can easily be 5x higher, and GUI tooling typically does use -uall.

In this sixth version, clarify the main commit message and some of the code comments, and adjust the logic slightly such that an existing untracked cache structure, when consistent with the requested flags in the current run, can be reused even though the current config would set/store/use the other set of flags on a new untracked cache structure.

I'm comfortable with this patch as-is, but am still interested in any thoughts as to whether it makes sense and is likely to be accepted to do this as a simple enhancement as proposed here, or whether people be more comfortable with a new configuration option, given the potential for worse performance under specific (and, I believe, vanishingly rare) circumstances.

cc: Tao Klerks tao@klerks.biz
cc: Ævar Arnfjörð Bjarmason avarab@gmail.com

@gitgitgadget
Copy link

gitgitgadget bot commented Jun 23, 2021

There is an issue in commit a8bf8f7:
Commit not signed off

@TaoK TaoK force-pushed the taok-untracked-cache-with-uall branch from a8bf8f7 to 2797efa Compare June 23, 2021 05:55
@TaoK
Copy link
Author

TaoK commented Jun 23, 2021

/submit

@gitgitgadget
Copy link

gitgitgadget bot commented Jun 23, 2021

Submitted as pull.985.git.1624430668741.gitgitgadget@gmail.com

To fetch this version into FETCH_HEAD:

git fetch https://github.com/gitgitgadget/git pr-985/TaoK/taok-untracked-cache-with-uall-v1

To fetch this version to local tag pr-985/TaoK/taok-untracked-cache-with-uall-v1:

git fetch --no-tags https://github.com/gitgitgadget/git tag pr-985/TaoK/taok-untracked-cache-with-uall-v1

@TaoK TaoK force-pushed the taok-untracked-cache-with-uall branch from 2797efa to e2f1ad2 Compare February 25, 2022 16:00
@TaoK
Copy link
Author

TaoK commented Feb 25, 2022

/submit

@gitgitgadget
Copy link

gitgitgadget bot commented Feb 25, 2022

Submitted as pull.985.v2.git.1645811564461.gitgitgadget@gmail.com

To fetch this version into FETCH_HEAD:

git fetch https://github.com/gitgitgadget/git/ pr-985/TaoK/taok-untracked-cache-with-uall-v2

To fetch this version to local tag pr-985/TaoK/taok-untracked-cache-with-uall-v2:

git fetch --no-tags https://github.com/gitgitgadget/git/ tag pr-985/TaoK/taok-untracked-cache-with-uall-v2

@gitgitgadget
Copy link

gitgitgadget bot commented Feb 25, 2022

On the Git mailing list, Junio C Hamano wrote (reply to this):

"Tao Klerks via GitGitGadget" <gitgitgadget@gmail.com> writes:

> If the previously stored flags no longer match the current
> configuration, but the currently-applicable flags do match the current
> configuration, then the previously stored untracked cache data is
> discarded.
>
> For most users there will be no change in behavior. Users who need
> '--untracked-files=all' to perform well will have the option of
> setting "status.showuntrackedfiles" to "all".
>
> Users who need '--untracked-files=all' to perform well for their
> tooling AND prefer to avoid the verbosity of "all" when running
> git status explicitly without options... are out of luck for now (no
> change).

So, in short, the root of the problem is that untracked cache can be
used to serve only one mode (between normal and all) of operation,
and the real solution to that problem must come in a different form,
i.e. allowing a single unified untracked cache to be usable in both
modes, perhaps by maintaining all the untracked ones in the cache,
but filter out upon output when the 'normal' mode is asked for?

> Users who set "status.showuntrackedfiles" to "all" and yet most
> frequently explicitly call 'git status --untracked-files=normal' (and
> use the untracked cache) are the only ones who would be disadvantaged
> by this change. It seems unlikely there are any such users.

Given how widely used we are these days, I am afraid that the days
we can safely say "users with such a strange use pattern would not
exist at all" is long gone.

> +static unsigned configured_default_dir_flags(struct index_state *istate)
> +{
> +	/* This logic is coordinated with the setting of these flags in
> +	 * wt-status.c#wt_status_collect_untracked(), and the evaluation
> +	 * of the config setting in commit.c#git_status_config()
> +	 */

Good thing to note here.

Style.

  /*
   * Our multi-line comments reads more like this, with
   * slash-asterisk that opens, and asterisk-slash that closes,
   * sitting on their own lines.
   */

> +	char *status_untracked_files_config_value;
> +	int config_outcome = repo_config_get_string(istate->repo,
> +								"status.showuntrackedfiles",

The indentation looks a bit off.

In this project, tab width is 8.  The beginning of the second
parameter to the function call on the second line should align with
the beginning of the first parameter that immediately follows the
open parenthesis '('.

> +								&status_untracked_files_config_value);
> +	if (!config_outcome && !strcmp(status_untracked_files_config_value, "all")) {
> +		return 0;
> +	} else {
> +		/*
> +		 * The default, if "all" is not set, is "normal" - leading us here.
> +		 * If the value is "none" then it really doesn't matter.
> +		 */
> +		return DIR_SHOW_OTHER_DIRECTORIES | DIR_HIDE_EMPTY_DIRECTORIES;
> +	}
> +}

I didn't see the need to pass istate to this function, though.
Shouldn't it take a repository instead?

> -static void new_untracked_cache(struct index_state *istate)
> +static void new_untracked_cache(struct index_state *istate, unsigned flags)
>  {
>  	struct untracked_cache *uc = xcalloc(1, sizeof(*uc));
>  	strbuf_init(&uc->ident, 100);
>  	uc->exclude_per_dir = ".gitignore";
> -	/* should be the same flags used by git-status */
> -	uc->dir_flags = DIR_SHOW_OTHER_DIRECTORIES | DIR_HIDE_EMPTY_DIRECTORIES;
> +	uc->dir_flags = flags;

So we used to hardcode these two flags to match what is done in
wt-status.c when show_untracked_files != SHOW_ALL_UNTRACKEDFILES;
we allow a different set of flags to be given by the caller.

> @@ -2761,11 +2781,13 @@ static void new_untracked_cache(struct index_state *istate)
>  void add_untracked_cache(struct index_state *istate)
>  {
>  	if (!istate->untracked) {
> -		new_untracked_cache(istate);
> +		new_untracked_cache(istate,
> +				configured_default_dir_flags(istate));
>  	} else {
>  		if (!ident_in_untracked(istate->untracked)) {
>  			free_untracked_cache(istate->untracked);
> -			new_untracked_cache(istate);
> +			new_untracked_cache(istate,
> +					configured_default_dir_flags(istate));
>  		}
>  	}
>  }

OK.  That's quite straight-forward to see how the tweak is made.

> @@ -2781,10 +2803,12 @@ void remove_untracked_cache(struct index_state *istate)
>  
>  static struct untracked_cache_dir *validate_untracked_cache(struct dir_struct *dir,
>  						      int base_len,
> -						      const struct pathspec *pathspec)
> +						      const struct pathspec *pathspec,
> +							  struct index_state *istate)
>  {
>  	struct untracked_cache_dir *root;
>  	static int untracked_cache_disabled = -1;
> +	unsigned configured_dir_flags;
>  
>  	if (!dir->untracked)
>  		return NULL;
> @@ -2812,17 +2836,9 @@ static struct untracked_cache_dir *validate_untracked_cache(struct dir_struct *d
>  	if (base_len || (pathspec && pathspec->nr))
>  		return NULL;
>  
> -	/* Different set of flags may produce different results */
> -	if (dir->flags != dir->untracked->dir_flags ||

This is removed because we are making sure that dir->flags and
dir->untracked->dir_flags match?

> -	    /*
> -	     * See treat_directory(), case index_nonexistent. Without
> -	     * this flag, we may need to also cache .git file content
> -	     * for the resolve_gitlink_ref() call, which we don't.
> -	     */
> -	    !(dir->flags & DIR_SHOW_OTHER_DIRECTORIES) ||

This is removed because...?

> -	    /* We don't support collecting ignore files */
> -	    (dir->flags & (DIR_SHOW_IGNORED | DIR_SHOW_IGNORED_TOO |
> -			   DIR_COLLECT_IGNORED)))

> +	/* We don't support collecting ignore files */
> +	if (dir->flags & (DIR_SHOW_IGNORED | DIR_SHOW_IGNORED_TOO |
> +			DIR_COLLECT_IGNORED))
>  		return NULL;
>  
>  	/*
> @@ -2845,6 +2861,40 @@ static struct untracked_cache_dir *validate_untracked_cache(struct dir_struct *d
>  		return NULL;
>  	}
>  
> +	/* We don't support using or preparing the untracked cache if
> +	 * the current effective flags don't match the configured
> +	 * flags.
> +	 */

Style (another one in large comment below).

> +	configured_dir_flags = configured_default_dir_flags(istate);
> +	if (dir->flags != configured_dir_flags)
> +		return NULL;

Hmph.  If this weren't necessary, this function does not need to
call configured_default_dir_flags(), and it can lose the
configured_dir_flags variable, too.  Which means that
new_untracked_cache() function does not need to take the flags word
as a caller-supplied parameter.  Instead, it can make a call to
configured_dir_flags() and assign the result to uc->dir_flags
itself, which would have been much nicer.

> +	/* If the untracked structure we received does not have the same flags
> +	 * as configured, but the configured flags do match the effective flags,
> +	 * then we need to reset / create a new "untracked" structure to match
> +	 * the new config.
> +	 * Keeping the saved and used untracked cache in-line with the
> +	 * configuration provides an opportunity for frequent users of
> +	 * "git status -uall" to leverage the untracked cache by aligning their
> +	 * configuration (setting "status.showuntrackedfiles" to "all" or
> +	 * "normal" as appropriate), where previously this option was
> +	 * incompatible with untracked cache and *consistently* caused
> +	 * surprisingly bad performance (with fscache and fsmonitor enabled) on
> +	 * Windows.
> +	 *
> +	 * IMPROVEMENT OPPORTUNITY: If we reworked the untracked cache storage
> +	 * to not be as bound up with the desired output in a given run,
> +	 * and instead iterated through and stored enough information to
> +	 * correctly serve both "modes", then users could get peak performance
> +	 * with or without '-uall' regardless of their
> +	 * "status.showuntrackedfiles" config.
> +	 */
> +	if (dir->flags != dir->untracked->dir_flags) {
> +		free_untracked_cache(istate->untracked);
> +		new_untracked_cache(istate, configured_dir_flags);
> +		dir->untracked = istate->untracked;
> +	}


This compensates what we lost in the validate_untracked_cache()
above by making them match.  Looking reasonable.

>  	if (!dir->untracked->root)
>  		FLEX_ALLOC_STR(dir->untracked->root, name, "");
>  
> @@ -2916,7 +2966,7 @@ int read_directory(struct dir_struct *dir, struct index_state *istate,
>  		return dir->nr;
>  	}
>  
> -	untracked = validate_untracked_cache(dir, len, pathspec);
> +	untracked = validate_untracked_cache(dir, len, pathspec, istate);
>  	if (!untracked)
>  		/*
>  		 * make sure untracked cache code path is disabled,
>
> base-commit: dab1b7905d0b295f1acef9785bb2b9cbb0fdec84

@gitgitgadget
Copy link

gitgitgadget bot commented Feb 26, 2022

This branch is now known as tk/untracked-cache-with-uall.

@gitgitgadget
Copy link

gitgitgadget bot commented Feb 26, 2022

This patch series was integrated into seen via git@f68b759.

@gitgitgadget gitgitgadget bot added the seen label Feb 26, 2022
@gitgitgadget
Copy link

gitgitgadget bot commented Feb 26, 2022

This patch series was integrated into seen via git@01e0ccf.

@gitgitgadget
Copy link

gitgitgadget bot commented Feb 26, 2022

There was a status update in the "New Topics" section about the branch tk/untracked-cache-with-uall on the Git mailing list:

The untracked cache system does not work well when the setting of
status.showuntrackedfiles is 'normal' and not 'all', which has been
updated.

Needs review.
source: <pull.985.v2.git.1645811564461.gitgitgadget@gmail.com>

@gitgitgadget
Copy link

gitgitgadget bot commented Feb 26, 2022

This patch series was integrated into seen via git@cb1be9e.

@gitgitgadget
Copy link

gitgitgadget bot commented Feb 26, 2022

This patch series was integrated into seen via git@f6e29ae.

@TaoK TaoK force-pushed the taok-untracked-cache-with-uall branch from e2f1ad2 to 49cf90b Compare February 27, 2022 07:09
@TaoK
Copy link
Author

TaoK commented Feb 27, 2022

/submit

@gitgitgadget
Copy link

gitgitgadget bot commented Feb 27, 2022

Submitted as pull.985.v3.git.1645960973798.gitgitgadget@gmail.com

To fetch this version into FETCH_HEAD:

git fetch https://github.com/gitgitgadget/git/ pr-985/TaoK/taok-untracked-cache-with-uall-v3

To fetch this version to local tag pr-985/TaoK/taok-untracked-cache-with-uall-v3:

git fetch --no-tags https://github.com/gitgitgadget/git/ tag pr-985/TaoK/taok-untracked-cache-with-uall-v3

@gitgitgadget
Copy link

gitgitgadget bot commented Feb 27, 2022

On the Git mailing list, Tao Klerks wrote (reply to this):

On Fri, Feb 25, 2022 at 8:44 PM Junio C Hamano <gitster@pobox.com> wrote:
>
> "Tao Klerks via GitGitGadget" <gitgitgadget@gmail.com> writes:
>
> > If the previously stored flags no longer match the current
> > configuration, but the currently-applicable flags do match the current
> > configuration, then the previously stored untracked cache data is
> > discarded.
> >
> > For most users there will be no change in behavior. Users who need
> > '--untracked-files=all' to perform well will have the option of
> > setting "status.showuntrackedfiles" to "all".
> >
> > Users who need '--untracked-files=all' to perform well for their
> > tooling AND prefer to avoid the verbosity of "all" when running
> > git status explicitly without options... are out of luck for now (no
> > change).
>
> So, in short, the root of the problem is that untracked cache can be
> used to serve only one mode (between normal and all) of operation,
> and the real solution to that problem must come in a different form,
> i.e. allowing a single unified untracked cache to be usable in both
> modes, perhaps by maintaining all the untracked ones in the cache,
> but filter out upon output when the 'normal' mode is asked for?

I wouldn't call this the root of the problem I was trying to solve with this
patch, but rather the root of the remaining problem, yes.

The challenge that I can't get my head around for this longer-term
approach or objective, is *when* the untracked-folder nested files
should be enumerated.

Currently, untracked folders are only recursed into if -uall is
specified or configured - and that's a significant characteristic:
It's perfectly plausible that some users sometimes have huge
deep untracked folder hierarchies that take a long time to explore,
but git never needs to because they never specify -uall.

If we decided to serve both modes with one single untracked
cache structure, then we would either need to always fully
recurse, or implement some sort of "just-in-time" filling in of the
recursive bits when someone specifies -uall for the first time.

Either way, I'm pretty sure it's beyond me to do that right. Hence
this very-pragmatic approach that makes it *possible* to get
good/normal performance with -uall.

>
> > Users who set "status.showuntrackedfiles" to "all" and yet most
> > frequently explicitly call 'git status --untracked-files=normal' (and
> > use the untracked cache) are the only ones who would be disadvantaged
> > by this change. It seems unlikely there are any such users.
>
> Given how widely used we are these days, I am afraid that the days
> we can safely say "users with such a strange use pattern would not
> exist at all" is long gone.
>
> > +static unsigned configured_default_dir_flags(struct index_state *istate)
> > +{
> > +     /* This logic is coordinated with the setting of these flags in
> > +      * wt-status.c#wt_status_collect_untracked(), and the evaluation
> > +      * of the config setting in commit.c#git_status_config()
> > +      */
>
> Good thing to note here.
>
> Style.
>
>   /*
>    * Our multi-line comments reads more like this, with
>    * slash-asterisk that opens, and asterisk-slash that closes,
>    * sitting on their own lines.
>    */

Thanks, sorry, I thought I'd corrected them all but clearly missed some.

>
> > +     char *status_untracked_files_config_value;
> > +     int config_outcome = repo_config_get_string(istate->repo,
> > +                                                             "status.showuntrackedfiles",
>
> The indentation looks a bit off.
>
> In this project, tab width is 8.  The beginning of the second
> parameter to the function call on the second line should align with
> the beginning of the first parameter that immediately follows the
> open parenthesis '('.
>

Fixed, thx.

> > +                                                             &status_untracked_files_config_value);
> > +     if (!config_outcome && !strcmp(status_untracked_files_config_value, "all")) {
> > +             return 0;
> > +     } else {
> > +             /*
> > +              * The default, if "all" is not set, is "normal" - leading us here.
> > +              * If the value is "none" then it really doesn't matter.
> > +              */
> > +             return DIR_SHOW_OTHER_DIRECTORIES | DIR_HIDE_EMPTY_DIRECTORIES;
> > +     }
> > +}
>
> I didn't see the need to pass istate to this function, though.
> Shouldn't it take a repository instead?

Makes sense, fixed, thx.

>
> > -static void new_untracked_cache(struct index_state *istate)
> > +static void new_untracked_cache(struct index_state *istate, unsigned flags)
> >  {
> >       struct untracked_cache *uc = xcalloc(1, sizeof(*uc));
> >       strbuf_init(&uc->ident, 100);
> >       uc->exclude_per_dir = ".gitignore";
> > -     /* should be the same flags used by git-status */
> > -     uc->dir_flags = DIR_SHOW_OTHER_DIRECTORIES | DIR_HIDE_EMPTY_DIRECTORIES;
> > +     uc->dir_flags = flags;
>
> So we used to hardcode these two flags to match what is done in
> wt-status.c when show_untracked_files != SHOW_ALL_UNTRACKEDFILES;
> we allow a different set of flags to be given by the caller.
>
> > @@ -2761,11 +2781,13 @@ static void new_untracked_cache(struct index_state *istate)
> >  void add_untracked_cache(struct index_state *istate)
> >  {
> >       if (!istate->untracked) {
> > -             new_untracked_cache(istate);
> > +             new_untracked_cache(istate,
> > +                             configured_default_dir_flags(istate));
> >       } else {
> >               if (!ident_in_untracked(istate->untracked)) {
> >                       free_untracked_cache(istate->untracked);
> > -                     new_untracked_cache(istate);
> > +                     new_untracked_cache(istate,
> > +                                     configured_default_dir_flags(istate));
> >               }
> >       }
> >  }
>
> OK.  That's quite straight-forward to see how the tweak is made.
>
> > @@ -2781,10 +2803,12 @@ void remove_untracked_cache(struct index_state *istate)
> >
> >  static struct untracked_cache_dir *validate_untracked_cache(struct dir_struct *dir,
> >                                                     int base_len,
> > -                                                   const struct pathspec *pathspec)
> > +                                                   const struct pathspec *pathspec,
> > +                                                       struct index_state *istate)
> >  {
> >       struct untracked_cache_dir *root;
> >       static int untracked_cache_disabled = -1;
> > +     unsigned configured_dir_flags;
> >
> >       if (!dir->untracked)
> >               return NULL;
> > @@ -2812,17 +2836,9 @@ static struct untracked_cache_dir *validate_untracked_cache(struct dir_struct *d
> >       if (base_len || (pathspec && pathspec->nr))
> >               return NULL;
> >
> > -     /* Different set of flags may produce different results */
> > -     if (dir->flags != dir->untracked->dir_flags ||
>
> This is removed because we are making sure that dir->flags and
> dir->untracked->dir_flags match?
>
> > -         /*
> > -          * See treat_directory(), case index_nonexistent. Without
> > -          * this flag, we may need to also cache .git file content
> > -          * for the resolve_gitlink_ref() call, which we don't.
> > -          */
> > -         !(dir->flags & DIR_SHOW_OTHER_DIRECTORIES) ||
>
> This is removed because...?

Because we *do* now support using untracked cache with -uall...
As long as the config matches the runtime flags (new check later).

>
> > -         /* We don't support collecting ignore files */
> > -         (dir->flags & (DIR_SHOW_IGNORED | DIR_SHOW_IGNORED_TOO |
> > -                        DIR_COLLECT_IGNORED)))
>
> > +     /* We don't support collecting ignore files */
> > +     if (dir->flags & (DIR_SHOW_IGNORED | DIR_SHOW_IGNORED_TOO |
> > +                     DIR_COLLECT_IGNORED))
> >               return NULL;
> >
> >       /*
> > @@ -2845,6 +2861,40 @@ static struct untracked_cache_dir *validate_untracked_cache(struct dir_struct *d
> >               return NULL;
> >       }
> >
> > +     /* We don't support using or preparing the untracked cache if
> > +      * the current effective flags don't match the configured
> > +      * flags.
> > +      */
>
> Style (another one in large comment below).
>

Thx.

> > +     configured_dir_flags = configured_default_dir_flags(istate);
> > +     if (dir->flags != configured_dir_flags)
> > +             return NULL;
>
> Hmph.  If this weren't necessary, this function does not need to
> call configured_default_dir_flags(), and it can lose the
> configured_dir_flags variable, too.  Which means that
> new_untracked_cache() function does not need to take the flags word
> as a caller-supplied parameter.  Instead, it can make a call to
> configured_dir_flags() and assign the result to uc->dir_flags
> itself, which would have been much nicer.

I've tightened this up a little with an inline call to
configured_default_dir_flags(), getting rid of the variable, let's see
if that makes more sense / is cleaner.

Sending new version with these changes.

>
> > +     /* If the untracked structure we received does not have the same flags
> > +      * as configured, but the configured flags do match the effective flags,
> > +      * then we need to reset / create a new "untracked" structure to match
> > +      * the new config.
> > +      * Keeping the saved and used untracked cache in-line with the
> > +      * configuration provides an opportunity for frequent users of
> > +      * "git status -uall" to leverage the untracked cache by aligning their
> > +      * configuration (setting "status.showuntrackedfiles" to "all" or
> > +      * "normal" as appropriate), where previously this option was
> > +      * incompatible with untracked cache and *consistently* caused
> > +      * surprisingly bad performance (with fscache and fsmonitor enabled) on
> > +      * Windows.
> > +      *
> > +      * IMPROVEMENT OPPORTUNITY: If we reworked the untracked cache storage
> > +      * to not be as bound up with the desired output in a given run,
> > +      * and instead iterated through and stored enough information to
> > +      * correctly serve both "modes", then users could get peak performance
> > +      * with or without '-uall' regardless of their
> > +      * "status.showuntrackedfiles" config.
> > +      */
> > +     if (dir->flags != dir->untracked->dir_flags) {
> > +             free_untracked_cache(istate->untracked);
> > +             new_untracked_cache(istate, configured_dir_flags);
> > +             dir->untracked = istate->untracked;
> > +     }
>
>
> This compensates what we lost in the validate_untracked_cache()
> above by making them match.  Looking reasonable.
>
> >       if (!dir->untracked->root)
> >               FLEX_ALLOC_STR(dir->untracked->root, name, "");
> >
> > @@ -2916,7 +2966,7 @@ int read_directory(struct dir_struct *dir, struct index_state *istate,
> >               return dir->nr;
> >       }
> >
> > -     untracked = validate_untracked_cache(dir, len, pathspec);
> > +     untracked = validate_untracked_cache(dir, len, pathspec, istate);
> >       if (!untracked)
> >               /*
> >                * make sure untracked cache code path is disabled,
> >
> > base-commit: dab1b7905d0b295f1acef9785bb2b9cbb0fdec84

@gitgitgadget
Copy link

gitgitgadget bot commented Feb 27, 2022

User Tao Klerks <tao@klerks.biz> has been added to the cc: list.

@TaoK TaoK force-pushed the taok-untracked-cache-with-uall branch from 49cf90b to 5da418e Compare February 27, 2022 14:37
@gitgitgadget
Copy link

gitgitgadget bot commented Feb 27, 2022

On the Git mailing list, Tao Klerks wrote (reply to this):

Bad submission, my apologies - commit message is right but code
changes are missing. New one coming soon.

On Sun, Feb 27, 2022 at 12:22 PM Tao Klerks via GitGitGadget
<gitgitgadget@gmail.com> wrote:
>
> From: Tao Klerks <tao@klerks.biz>
>
> Untracked cache was originally designed to only work with
> '-untracked-files=normal', but this causes performance issues for UI
> tooling that wants to see "all" on a frequent basis. On the other hand,
> the conditions that prevented applicability to the "all" mode no
> longer seem to apply.
>
> The disqualification of untracked cache has a particularly significant
> impact on Windows with the defaulted fscache, where the introduction
> of fsmonitor can make the first and costly directory-iteration happen
> in untracked file detection, single-threaded, rather than in
> preload-index on multiple threads. Improving the performance of a
> "normal" 'git status' run with fsmonitor can make
> 'git status --untracked-files=all' perform much worse.
>
> To partially address this, align the supported directory flags for the
> stored untracked cache data with the git config. If a user specifies
> an '--untracked-files=' commandline parameter that does not align with
> their 'status.showuntrackedfiles' config value, then the untracked
> cache will be ignored - as it is for other unsupported situations like
> when a pathspec is specified.
>
> If the previously stored flags no longer match the current
> configuration, but the currently-applicable flags do match the current
> configuration, then discard the previously stored untracked cache
> data.
>
> For most users there will be no change in behavior. Users who need
> '--untracked-files=all' to perform well will now have the option of
> setting "status.showuntrackedfiles" to "all" for better / more
> consistent performance.
>
> Users who need '--untracked-files=all' to perform well for their
> tooling AND prefer to avoid the verbosity of "all" when running
> git status explicitly without options... are out of luck for now (no
> change).
>
> Users who have the "status.showuntrackedfiles" config set to "all"
> and yet frequently explicitly call
> 'git status --untracked-files=normal' (and use the untracked cache)
> are the only ones who will be disadvantaged by this change. Their
> "--untracked-files=normal" calls will, after this change, no longer
> use the untracked cache.
>
> Signed-off-by: Tao Klerks <tao@klerks.biz>
> ---
>     Support untracked cache with '--untracked-files=all' if configured
>
>     Resending this patch from a few months ago (with better standards
>     compliance) - it hasn't seen any comments yet, I would dearly love some
>     eyes on this as the change can make a big difference to hundreds of
>     windows users in my environment (and I'd really rather not start
>     distributing customized git builds!)
>
>     This patch aims to make it possible for users of the -uall flag to git
>     status, either by preference or by need (eg UI tooling), to benefit from
>     the untracked cache when they set their 'status.showuntrackedfiles'
>     config setting to 'all'. This is very important for large repos in
>     Windows.
>
>     More detail on the change and context in the commit message, I assume
>     repeating a verbose message here is discouraged.
>
>     These changes result from a couple of conversations,
>     81153d02-8e7a-be59-e709-e90cd5906f3a@jeffhostetler.com and
>     CABPp-BFiwzzUgiTj_zu+vF5x20L0=1cf25cHwk7KZQj2YkVzXw@mail.gmail.com>.
>
>     The test suite passes, but as a n00b I do have questions:
>
>      * Is there any additional validation that could/should be done to
>        confirm that "-uall" untracked data can be cached safely?
>        * It looks safe from following the code
>        * It seems from discussing briefly with Elijah Newren in the thread
>          above that thare are no obvious red flags
>        * Manual testing, explicitly and implicitly through months of use,
>          yields no issues
>      * Is it OK to check the repo configuration in the body of processing?
>        It seems to be a rare pattern
>      * Can anyone think of a way to test this change?
>
> Published-As: https://github.com/gitgitgadget/git/releases/tag/pr-985%2FTaoK%2Ftaok-untracked-cache-with-uall-v3
> Fetch-It-Via: git fetch https://github.com/gitgitgadget/git pr-985/TaoK/taok-untracked-cache-with-uall-v3
> Pull-Request: https://github.com/gitgitgadget/git/pull/985
>
> Range-diff vs v2:
>
>  1:  e2f1ad26c78 ! 1:  49cf90bfab5 untracked-cache: support '--untracked-files=all' if configured
>      @@ Commit message
>           untracked-cache: support '--untracked-files=all' if configured
>
>           Untracked cache was originally designed to only work with
>      -    '-untracked-files=normal', but this is a concern for UI tooling that
>      -    wants to see "all" on a frequent basis, and the conditions that
>      -    prevented applicability to the "all" mode no longer seem to apply.
>      +    '-untracked-files=normal', but this causes performance issues for UI
>      +    tooling that wants to see "all" on a frequent basis. On the other hand,
>      +    the conditions that prevented applicability to the "all" mode no
>      +    longer seem to apply.
>
>      -    The disqualification of untracked cache is a particular problem on
>      -    Windows with the defaulted fscache, where the introduction of
>      -    fsmonitor can make the first and costly directory-iteration happen
>      +    The disqualification of untracked cache has a particularly significant
>      +    impact on Windows with the defaulted fscache, where the introduction
>      +    of fsmonitor can make the first and costly directory-iteration happen
>           in untracked file detection, single-threaded, rather than in
>           preload-index on multiple threads. Improving the performance of a
>           "normal" 'git status' run with fsmonitor can make
>           'git status --untracked-files=all' perform much worse.
>
>      -    In this change, align the supported directory flags for the stored
>      -    untracked cache data with the git config. If a user specifies an
>      -    '--untracked-files=' commandline parameter that does not align with
>      +    To partially address this, align the supported directory flags for the
>      +    stored untracked cache data with the git config. If a user specifies
>      +    an '--untracked-files=' commandline parameter that does not align with
>           their 'status.showuntrackedfiles' config value, then the untracked
>           cache will be ignored - as it is for other unsupported situations like
>           when a pathspec is specified.
>
>           If the previously stored flags no longer match the current
>           configuration, but the currently-applicable flags do match the current
>      -    configuration, then the previously stored untracked cache data is
>      -    discarded.
>      +    configuration, then discard the previously stored untracked cache
>      +    data.
>
>           For most users there will be no change in behavior. Users who need
>      -    '--untracked-files=all' to perform well will have the option of
>      -    setting "status.showuntrackedfiles" to "all".
>      +    '--untracked-files=all' to perform well will now have the option of
>      +    setting "status.showuntrackedfiles" to "all" for better / more
>      +    consistent performance.
>
>           Users who need '--untracked-files=all' to perform well for their
>           tooling AND prefer to avoid the verbosity of "all" when running
>           git status explicitly without options... are out of luck for now (no
>           change).
>
>      -    Users who set "status.showuntrackedfiles" to "all" and yet most
>      -    frequently explicitly call 'git status --untracked-files=normal' (and
>      -    use the untracked cache) are the only ones who would be disadvantaged
>      -    by this change. It seems unlikely there are any such users.
>      +    Users who have the "status.showuntrackedfiles" config set to "all"
>      +    and yet frequently explicitly call
>      +    'git status --untracked-files=normal' (and use the untracked cache)
>      +    are the only ones who will be disadvantaged by this change. Their
>      +    "--untracked-files=normal" calls will, after this change, no longer
>      +    use the untracked cache.
>
>           Signed-off-by: Tao Klerks <tao@klerks.biz>
>
>
>
>  dir.c | 86 ++++++++++++++++++++++++++++++++++++++++++++++-------------
>  1 file changed, 68 insertions(+), 18 deletions(-)
>
> diff --git a/dir.c b/dir.c
> index d91295f2bcd..e35331d3f71 100644
> --- a/dir.c
> +++ b/dir.c
> @@ -2746,13 +2746,33 @@ static void set_untracked_ident(struct untracked_cache *uc)
>         strbuf_addch(&uc->ident, 0);
>  }
>
> -static void new_untracked_cache(struct index_state *istate)
> +static unsigned configured_default_dir_flags(struct index_state *istate)
> +{
> +       /* This logic is coordinated with the setting of these flags in
> +        * wt-status.c#wt_status_collect_untracked(), and the evaluation
> +        * of the config setting in commit.c#git_status_config()
> +        */
> +       char *status_untracked_files_config_value;
> +       int config_outcome = repo_config_get_string(istate->repo,
> +                                                               "status.showuntrackedfiles",
> +                                                               &status_untracked_files_config_value);
> +       if (!config_outcome && !strcmp(status_untracked_files_config_value, "all")) {
> +               return 0;
> +       } else {
> +               /*
> +                * The default, if "all" is not set, is "normal" - leading us here.
> +                * If the value is "none" then it really doesn't matter.
> +                */
> +               return DIR_SHOW_OTHER_DIRECTORIES | DIR_HIDE_EMPTY_DIRECTORIES;
> +       }
> +}
> +
> +static void new_untracked_cache(struct index_state *istate, unsigned flags)
>  {
>         struct untracked_cache *uc = xcalloc(1, sizeof(*uc));
>         strbuf_init(&uc->ident, 100);
>         uc->exclude_per_dir = ".gitignore";
> -       /* should be the same flags used by git-status */
> -       uc->dir_flags = DIR_SHOW_OTHER_DIRECTORIES | DIR_HIDE_EMPTY_DIRECTORIES;
> +       uc->dir_flags = flags;
>         set_untracked_ident(uc);
>         istate->untracked = uc;
>         istate->cache_changed |= UNTRACKED_CHANGED;
> @@ -2761,11 +2781,13 @@ static void new_untracked_cache(struct index_state *istate)
>  void add_untracked_cache(struct index_state *istate)
>  {
>         if (!istate->untracked) {
> -               new_untracked_cache(istate);
> +               new_untracked_cache(istate,
> +                               configured_default_dir_flags(istate));
>         } else {
>                 if (!ident_in_untracked(istate->untracked)) {
>                         free_untracked_cache(istate->untracked);
> -                       new_untracked_cache(istate);
> +                       new_untracked_cache(istate,
> +                                       configured_default_dir_flags(istate));
>                 }
>         }
>  }
> @@ -2781,10 +2803,12 @@ void remove_untracked_cache(struct index_state *istate)
>
>  static struct untracked_cache_dir *validate_untracked_cache(struct dir_struct *dir,
>                                                       int base_len,
> -                                                     const struct pathspec *pathspec)
> +                                                     const struct pathspec *pathspec,
> +                                                         struct index_state *istate)
>  {
>         struct untracked_cache_dir *root;
>         static int untracked_cache_disabled = -1;
> +       unsigned configured_dir_flags;
>
>         if (!dir->untracked)
>                 return NULL;
> @@ -2812,17 +2836,9 @@ static struct untracked_cache_dir *validate_untracked_cache(struct dir_struct *d
>         if (base_len || (pathspec && pathspec->nr))
>                 return NULL;
>
> -       /* Different set of flags may produce different results */
> -       if (dir->flags != dir->untracked->dir_flags ||
> -           /*
> -            * See treat_directory(), case index_nonexistent. Without
> -            * this flag, we may need to also cache .git file content
> -            * for the resolve_gitlink_ref() call, which we don't.
> -            */
> -           !(dir->flags & DIR_SHOW_OTHER_DIRECTORIES) ||
> -           /* We don't support collecting ignore files */
> -           (dir->flags & (DIR_SHOW_IGNORED | DIR_SHOW_IGNORED_TOO |
> -                          DIR_COLLECT_IGNORED)))
> +       /* We don't support collecting ignore files */
> +       if (dir->flags & (DIR_SHOW_IGNORED | DIR_SHOW_IGNORED_TOO |
> +                       DIR_COLLECT_IGNORED))
>                 return NULL;
>
>         /*
> @@ -2845,6 +2861,40 @@ static struct untracked_cache_dir *validate_untracked_cache(struct dir_struct *d
>                 return NULL;
>         }
>
> +       /* We don't support using or preparing the untracked cache if
> +        * the current effective flags don't match the configured
> +        * flags.
> +        */
> +       configured_dir_flags = configured_default_dir_flags(istate);
> +       if (dir->flags != configured_dir_flags)
> +               return NULL;
> +
> +       /* If the untracked structure we received does not have the same flags
> +        * as configured, but the configured flags do match the effective flags,
> +        * then we need to reset / create a new "untracked" structure to match
> +        * the new config.
> +        * Keeping the saved and used untracked cache in-line with the
> +        * configuration provides an opportunity for frequent users of
> +        * "git status -uall" to leverage the untracked cache by aligning their
> +        * configuration (setting "status.showuntrackedfiles" to "all" or
> +        * "normal" as appropriate), where previously this option was
> +        * incompatible with untracked cache and *consistently* caused
> +        * surprisingly bad performance (with fscache and fsmonitor enabled) on
> +        * Windows.
> +        *
> +        * IMPROVEMENT OPPORTUNITY: If we reworked the untracked cache storage
> +        * to not be as bound up with the desired output in a given run,
> +        * and instead iterated through and stored enough information to
> +        * correctly serve both "modes", then users could get peak performance
> +        * with or without '-uall' regardless of their
> +        * "status.showuntrackedfiles" config.
> +        */
> +       if (dir->flags != dir->untracked->dir_flags) {
> +               free_untracked_cache(istate->untracked);
> +               new_untracked_cache(istate, configured_dir_flags);
> +               dir->untracked = istate->untracked;
> +       }
> +
>         if (!dir->untracked->root)
>                 FLEX_ALLOC_STR(dir->untracked->root, name, "");
>
> @@ -2916,7 +2966,7 @@ int read_directory(struct dir_struct *dir, struct index_state *istate,
>                 return dir->nr;
>         }
>
> -       untracked = validate_untracked_cache(dir, len, pathspec);
> +       untracked = validate_untracked_cache(dir, len, pathspec, istate);
>         if (!untracked)
>                 /*
>                  * make sure untracked cache code path is disabled,
>
> base-commit: dab1b7905d0b295f1acef9785bb2b9cbb0fdec84
> --
> gitgitgadget

@TaoK
Copy link
Author

TaoK commented Feb 27, 2022

note on OSX failure: I keep seeing these, it looks like there's something wrong with an OSX build host (or the whole setup?). Possibly the most disturbing thing is that the failure has something to do with the hash of a Helix Server (ie Perforce VCS) package. I don't know whether this failure prevents submission on GitGitGadget, but I will assume not. I am confident it is unrelated to my changes.

@TaoK
Copy link
Author

TaoK commented Feb 27, 2022

/submit

@gitgitgadget
Copy link

gitgitgadget bot commented Feb 27, 2022

Submitted as pull.985.v4.git.1645974782256.gitgitgadget@gmail.com

To fetch this version into FETCH_HEAD:

git fetch https://github.com/gitgitgadget/git/ pr-985/TaoK/taok-untracked-cache-with-uall-v4

To fetch this version to local tag pr-985/TaoK/taok-untracked-cache-with-uall-v4:

git fetch --no-tags https://github.com/gitgitgadget/git/ tag pr-985/TaoK/taok-untracked-cache-with-uall-v4

@gitgitgadget
Copy link

gitgitgadget bot commented Feb 27, 2022

On the Git mailing list, Junio C Hamano wrote (reply to this):

Tao Klerks <tao@klerks.biz> writes:

>> > +     configured_dir_flags = configured_default_dir_flags(istate);
>> > +     if (dir->flags != configured_dir_flags)
>> > +             return NULL;
>>
>> Hmph.  If this weren't necessary, this function does not need to
>> call configured_default_dir_flags(), and it can lose the
>> configured_dir_flags variable, too.  Which means that
>> new_untracked_cache() function does not need to take the flags word
>> as a caller-supplied parameter.  Instead, it can make a call to
>> configured_dir_flags() and assign the result to uc->dir_flags
>> itself, which would have been much nicer.
>
> I've tightened this up a little with an inline call to
> configured_default_dir_flags(), getting rid of the variable, let's see
> if that makes more sense / is cleaner.

The extra variable does not bother me at all.  Leaving the room for
the caller to screw up and pass an incorrect configred_dir_flags is
what disturbs me.

If this caller needs to call configred_default_dir_flags(istate),
then we cannot avoid it.  And the extra variable needed to call the
function only once, store its result, and use that result twice, is
perfectly a good thing to have.  We don't want to see inline or
anything tricky.

Thanks.

@dscho
Copy link
Member

dscho commented Feb 28, 2022

note on OSX failure: I keep seeing these, it looks like there's something wrong with an OSX build host (or the whole setup?). Possibly the most disturbing thing is that the failure has something to do with the hash of a Helix Server (ie Perforce VCS) package. I don't know whether this failure prevents submission on GitGitGadget, but I will assume not. I am confident it is unrelated to my changes.

Yes, Perforce does not provide stable links. So the same URL will result in different versions every once in a while.
See Homebrew/homebrew-cask#119770 for a semi-automate (but unfortunately failed) attempt to fix it.

@TaoK
Copy link
Author

TaoK commented Feb 28, 2022

Comment to self for next re-roll: It might make sense to include a performance (cache-use) matrix for betore and after this change:

Rows:

  • -uall
  • -unormal
  • other filters eg pathspec

Columns:

  • status.showuntrackedfiles=normal
  • status.showuntrackedfiles=all

Matrix before:

             +------------------------+
             |          Config        |
             +----------------+-------+
             | normal/default |  all  |
+------------+----------------+-------+
| (none)     |       ✓        |   ✗   |
+------------+----------------+-------+
| -unormal   |       ✓        |   ✓   |
+------------+----------------+-------+
| -all       |       ✗        |   ✗   |
+------------+----------------+-------+
| (pathspec) |       ✗        |   ✗   |
+------------+----------------+-------+

Matrix after:

             +------------------------+
             |          Config        |
             +----------------+-------+
             | normal/default |  all  |
+------------+----------------+-------+
| (none)     |       ✓        |   ✔   |
+------------+----------------+-------+
| -unormal   |       ✓        |   ✘   |
+------------+----------------+-------+
| -all       |       ✗        |   ✔   |
+------------+----------------+-------+
| (pathspec) |       ✗        |   ✗   |
+------------+----------------+-------+

(three cells are "flipped", two for better and one for worse; my claim
is that the worsened condition is likely very-rarely-exercised)

@gitgitgadget
Copy link

gitgitgadget bot commented Feb 28, 2022

On the Git mailing list, Ævar Arnfjörð Bjarmason wrote (reply to this):


On Sun, Feb 27 2022, Tao Klerks via GitGitGadget wrote:

> From: Tao Klerks <tao@klerks.biz>
> [...]
>     The test suite passes, but as a n00b I do have questions:
>     
>      * Is there any additional validation that could/should be done to
>        confirm that "-uall" untracked data can be cached safely?

I haven't given this any substantial review, sorry.

>        * It looks safe from following the code

Yes, at a glance it looks safe to me.

>        * It seems from discussing briefly with Elijah Newren in the thread
>          above that thare are no obvious red flags
>        * Manual testing, explicitly and implicitly through months of use,
>          yields no issues
>      * Is it OK to check the repo configuration in the body of processing?
>        It seems to be a rare pattern

Yes, it's not very common, but it's fine.

>      * Can anyone think of a way to test this change?

Well, if we set "flags" to 0 in your new helper the existing tests will
fail, so that's something at least.

> -static void new_untracked_cache(struct index_state *istate)
> +static unsigned configured_default_dir_flags(struct repository *repo)
> +{
> +	/*
> +	 * This logic is coordinated with the setting of these flags in
> +	 * wt-status.c#wt_status_collect_untracked(), and the evaluation
> +	 * of the config setting in commit.c#git_status_config()
> +	 */
> +	char *status_untracked_files_config_value;
> +	int config_outcome = repo_config_get_string(repo,
> +						    "status.showuntrackedfiles",
> +						    &status_untracked_files_config_value);
> +	if (!config_outcome && !strcmp(status_untracked_files_config_value, "all")) {
> +		return 0;
> +	} else {
> +		/*
> +		 * The default, if "all" is not set, is "normal" - leading us here.
> +		 * If the value is "none" then it really doesn't matter.
> +		 */
> +		return DIR_SHOW_OTHER_DIRECTORIES | DIR_HIDE_EMPTY_DIRECTORIES;
> +	}
> +}
> +
> [...]

In reviewing this I found the addition of very long lines & indentation
made this a bit harder to read. I came up with the below which should be
squashable on top, and perhaps makes this easier to read.

I.e. the one caller that needs custom flags passes them, others pass -1
now.

For throwaway "char *" variables we usually use "char *p", "char *val"
or whatever. A "status_untracked_files_config_value" is a bit much for
something function local whose body is <10 lines of code.

And if you drop the "int config_outcome" + rename the variable the
repo_config_get_string() fits on one line:

diff --git a/dir.c b/dir.c
index 57a7d42482f..22a27d7780f 100644
--- a/dir.c
+++ b/dir.c
@@ -2746,34 +2746,33 @@ static void set_untracked_ident(struct untracked_cache *uc)
 	strbuf_addch(&uc->ident, 0);
 }
 
-static unsigned configured_default_dir_flags(struct repository *repo)
+static unsigned new_untracked_cache_flags(struct index_state *istate)
 {
+	struct repository *repo = istate->repo;
+	char *val;
+
 	/*
 	 * This logic is coordinated with the setting of these flags in
 	 * wt-status.c#wt_status_collect_untracked(), and the evaluation
 	 * of the config setting in commit.c#git_status_config()
 	 */
-	char *status_untracked_files_config_value;
-	int config_outcome = repo_config_get_string(repo,
-						    "status.showuntrackedfiles",
-						    &status_untracked_files_config_value);
-	if (!config_outcome && !strcmp(status_untracked_files_config_value, "all")) {
+	if (!repo_config_get_string(repo, "status.showuntrackedfiles", &val) &&
+	    !strcmp(val, "all"))
 		return 0;
-	} else {
-		/*
-		 * The default, if "all" is not set, is "normal" - leading us here.
-		 * If the value is "none" then it really doesn't matter.
-		 */
-		return DIR_SHOW_OTHER_DIRECTORIES | DIR_HIDE_EMPTY_DIRECTORIES;
-	}
+
+	/*
+	 * The default, if "all" is not set, is "normal" - leading us here.
+	 * If the value is "none" then it really doesn't matter.
+	 */
+	return DIR_SHOW_OTHER_DIRECTORIES | DIR_HIDE_EMPTY_DIRECTORIES;
 }
 
-static void new_untracked_cache(struct index_state *istate, unsigned flags)
+static void new_untracked_cache(struct index_state *istate, int flags)
 {
 	struct untracked_cache *uc = xcalloc(1, sizeof(*uc));
 	strbuf_init(&uc->ident, 100);
 	uc->exclude_per_dir = ".gitignore";
-	uc->dir_flags = flags;
+	uc->dir_flags = flags >= 0 ? flags : new_untracked_cache_flags(istate);
 	set_untracked_ident(uc);
 	istate->untracked = uc;
 	istate->cache_changed |= UNTRACKED_CHANGED;
@@ -2782,13 +2781,11 @@ static void new_untracked_cache(struct index_state *istate, unsigned flags)
 void add_untracked_cache(struct index_state *istate)
 {
 	if (!istate->untracked) {
-		new_untracked_cache(istate,
-				    configured_default_dir_flags(istate->repo));
+		new_untracked_cache(istate, -1);
 	} else {
 		if (!ident_in_untracked(istate->untracked)) {
 			free_untracked_cache(istate->untracked);
-			new_untracked_cache(istate,
-					    configured_default_dir_flags(istate->repo));
+			new_untracked_cache(istate, -1);
 		}
 	}
 }
@@ -2866,7 +2863,7 @@ static struct untracked_cache_dir *validate_untracked_cache(struct dir_struct *d
 	 * the current effective flags don't match the configured
 	 * flags.
 	 */
-	if (dir->flags != configured_default_dir_flags(istate->repo))
+	if (dir->flags != new_untracked_cache_flags(istate))
 		return NULL;
 
 	/*

@gitgitgadget
Copy link

gitgitgadget bot commented Feb 28, 2022

User Ævar Arnfjörð Bjarmason <avarab@gmail.com> has been added to the cc: list.

@gitgitgadget
Copy link

gitgitgadget bot commented Apr 14, 2022

This patch series was integrated into seen via git@abfa6dd.

@gitgitgadget
Copy link

gitgitgadget bot commented Apr 14, 2022

This patch series was integrated into seen via git@09e178c.

@gitgitgadget
Copy link

gitgitgadget bot commented Apr 14, 2022

This patch series was integrated into seen via git@003d30f.

@gitgitgadget
Copy link

gitgitgadget bot commented Apr 15, 2022

There was a status update in the "Cooking" section about the branch tk/untracked-cache-with-uall on the Git mailing list:

The performance of the "untracked cache" feature has been improved
when "--untracked-files=<mode>" and "status.showUntrackedFiles"
are combined.

Will cook in 'next'.
source: <pull.985.v6.git.1648742535.gitgitgadget@gmail.com>

@gitgitgadget
Copy link

gitgitgadget bot commented Apr 16, 2022

This patch series was integrated into seen via git@da3b247.

@gitgitgadget
Copy link

gitgitgadget bot commented Apr 18, 2022

This patch series was integrated into seen via git@56f608c.

@gitgitgadget
Copy link

gitgitgadget bot commented Apr 18, 2022

There was a status update in the "Cooking" section about the branch tk/untracked-cache-with-uall on the Git mailing list:

The performance of the "untracked cache" feature has been improved
when "--untracked-files=<mode>" and "status.showUntrackedFiles"
are combined.

Will cook in 'next'.
source: <pull.985.v6.git.1648742535.gitgitgadget@gmail.com>

@gitgitgadget
Copy link

gitgitgadget bot commented Apr 20, 2022

This patch series was integrated into seen via git@26fe10f.

@gitgitgadget
Copy link

gitgitgadget bot commented Apr 22, 2022

This patch series was integrated into seen via git@2c1ec57.

@gitgitgadget
Copy link

gitgitgadget bot commented Apr 23, 2022

This patch series was integrated into seen via git@39bd3f0.

@gitgitgadget
Copy link

gitgitgadget bot commented Apr 26, 2022

There was a status update in the "Cooking" section about the branch tk/untracked-cache-with-uall on the Git mailing list:

The performance of the "untracked cache" feature has been improved
when "--untracked-files=<mode>" and "status.showUntrackedFiles"
are combined.

Will cook in 'next'.
source: <pull.985.v6.git.1648742535.gitgitgadget@gmail.com>

@gitgitgadget
Copy link

gitgitgadget bot commented Apr 26, 2022

This patch series was integrated into seen via git@8806d68.

@gitgitgadget
Copy link

gitgitgadget bot commented Apr 26, 2022

This patch series was integrated into seen via git@2c58517.

@gitgitgadget
Copy link

gitgitgadget bot commented Apr 28, 2022

This patch series was integrated into seen via git@0cb6291.

@gitgitgadget
Copy link

gitgitgadget bot commented Apr 28, 2022

There was a status update in the "Cooking" section about the branch tk/untracked-cache-with-uall on the Git mailing list:

The performance of the "untracked cache" feature has been improved
when "--untracked-files=<mode>" and "status.showUntrackedFiles"
are combined.

Will cook in 'next'.
source: <pull.985.v6.git.1648742535.gitgitgadget@gmail.com>

@gitgitgadget
Copy link

gitgitgadget bot commented Apr 29, 2022

This patch series was integrated into seen via git@5e3a219.

@gitgitgadget
Copy link

gitgitgadget bot commented May 2, 2022

This patch series was integrated into seen via git@5315b3a.

@gitgitgadget
Copy link

gitgitgadget bot commented May 2, 2022

There was a status update in the "Cooking" section about the branch tk/untracked-cache-with-uall on the Git mailing list:

The performance of the "untracked cache" feature has been improved
when "--untracked-files=<mode>" and "status.showUntrackedFiles"
are combined.

Will cook in 'next'.
source: <pull.985.v6.git.1648742535.gitgitgadget@gmail.com>

@gitgitgadget
Copy link

gitgitgadget bot commented May 3, 2022

This patch series was integrated into seen via git@8622808.

@gitgitgadget
Copy link

gitgitgadget bot commented May 4, 2022

This patch series was integrated into seen via git@5335ce1.

@gitgitgadget
Copy link

gitgitgadget bot commented May 5, 2022

There was a status update in the "Cooking" section about the branch tk/untracked-cache-with-uall on the Git mailing list:

The performance of the "untracked cache" feature has been improved
when "--untracked-files=<mode>" and "status.showUntrackedFiles"
are combined.

Will cook in 'next'.
source: <pull.985.v6.git.1648742535.gitgitgadget@gmail.com>

@gitgitgadget
Copy link

gitgitgadget bot commented May 6, 2022

This patch series was integrated into seen via git@4cd5da1.

@gitgitgadget
Copy link

gitgitgadget bot commented May 10, 2022

This patch series was integrated into seen via git@93a4cf3.

@gitgitgadget
Copy link

gitgitgadget bot commented May 11, 2022

There was a status update in the "Cooking" section about the branch tk/untracked-cache-with-uall on the Git mailing list:

The performance of the "untracked cache" feature has been improved
when "--untracked-files=<mode>" and "status.showUntrackedFiles"
are combined.

Will merge to 'master'.
source: <pull.985.v6.git.1648742535.gitgitgadget@gmail.com>

@gitgitgadget
Copy link

gitgitgadget bot commented May 11, 2022

This patch series was integrated into seen via git@301fc17.

@gitgitgadget
Copy link

gitgitgadget bot commented May 11, 2022

This patch series was integrated into master via git@301fc17.

@gitgitgadget
Copy link

gitgitgadget bot commented May 11, 2022

This patch series was integrated into next via git@301fc17.

@gitgitgadget gitgitgadget bot added the master label May 11, 2022
@gitgitgadget gitgitgadget bot closed this May 11, 2022
@gitgitgadget
Copy link

gitgitgadget bot commented May 11, 2022

Closed via 301fc17.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

Successfully merging this pull request may close these issues.

None yet

2 participants