git/list[1] front-page[2] threads[3] people[4] search[5] about
 

Re: [PATCH] builtin/stash: configs keepIndex, includeUntracked

From
Jean-Noël Avila <avila.jn@gmail.com>
Date
Feb 19, 2024, 08:04 UTC
Message-ID
<fc7a8c46-61e4-4b5d-b625-cbc845b81590@gmail.com>
In-Reply-To
<20240218033146.372727-2-rpc01234@gmail.com>
Hello,
Le 18/02/2024 à 04:30, MithicSpirit a écrit :
Show 152 quoted lines
> Adds options `stash.keepIndex` and `stash.includeUntracked`, which
> enable `--keep-index` and `--include-untracked` by default (unless it
> would conflict with another option). This is done to facilitate the
> workflow where a user:
> 
> . Makes modifications;
> . Selectively adds them with `git add -p`; and
> . Stashes the unadded changes to run tests with only the current
>    modifications.
> 
> `stash.keepIndex` is especially important for this, as otherwise the
> work done in `git add -p` is lost since applying the stash does not
> restore the index. This problem could also be solved by adding
> functionality to the stash to restore the index specifically, but this
> would create much more complexity and still wouldn't be as convenient
> for that workflow.
> 
> Signed-off-by: Ricardo Prado Cunha (MithicSpirit) <rpc01234@gmail.com>
> ---
> This is my first patch to git and my first time using mailing lists for this
> kind of stuff. Please do let me know of any mistakes or gaffes I've made.
> 
>   Documentation/config/stash.txt |  13 ++++
>   builtin/stash.c                |  65 ++++++++++++------
>   t/t3903-stash.sh               | 119 +++++++++++++++++++++++++++++++++
>   3 files changed, 178 insertions(+), 19 deletions(-)
> 
> diff --git a/Documentation/config/stash.txt b/Documentation/config/stash.txt
> index ec1edaeba6..d6d9ea7daa 100644
> --- a/Documentation/config/stash.txt
> +++ b/Documentation/config/stash.txt
> @@ -1,6 +1,19 @@
> +stash.includeUntracked::
> +	Boolean option that configures whether the `git stash push` and `git
> +	stash save` commands also stash untracked files by default. This option
> +	is ignored if `--include-untracked`, `--no-include-untracked`, `--all`,
> +	`--patch`, or `--staged` are used. Defaults to `false`. See
> +	linkgit:git-stash[1].
> +
> +stash.keepIndex::
> +	Boolean option that configures whether the `git stash push` and `git
> +	stash save` commands also stash changes that have been added to the
> +	index. This option is ignored if `--keep-index`, `--no-keep-index`, or
> +	`--patch` are used. Defaults to `false`. See linkgit:git-stash[1].
> +
>   stash.showIncludeUntracked::
>   	If this is set to true, the `git stash show` command will show
>   	the untracked files of a stash entry.  Defaults to false. See
>   	the description of the 'show' command in linkgit:git-stash[1].
> 
>   stash.showPatch::
> diff --git a/builtin/stash.c b/builtin/stash.c
> index 7fb355bff0..c591a2bf4b 100644
> --- a/builtin/stash.c
> +++ b/builtin/stash.c
> @@ -836,12 +836,14 @@ static int list_stash(int argc, const char **argv, const char *prefix)
>   	return run_command(&cp);
>   }
> 
>   static int show_stat = 1;
>   static int show_patch;
>   static int show_include_untracked;
> +static int default_keep_index;
> +static int default_include_untracked;
> 
>   static int git_stash_config(const char *var, const char *value,
>   			    const struct config_context *ctx, void *cb)
>   {
>   	if (!strcmp(var, "stash.showstat")) {
>   		show_stat = git_config_bool(var, value);
> @@ -852,12 +854,20 @@ static int git_stash_config(const char *var, const char *value,
>   		return 0;
>   	}
>   	if (!strcmp(var, "stash.showincludeuntracked")) {
>   		show_include_untracked = git_config_bool(var, value);
>   		return 0;
>   	}
> +	if (!strcmp(var, "stash.keepindex")) {
> +		default_keep_index = git_config_bool(var, value);
> +		return 0;
> +	}
> +	if (!strcmp(var, "stash.includeuntracked")) {
> +		default_include_untracked = git_config_bool(var, value);
> +		return 0;
> +	}
>   	return git_diff_basic_config(var, value, ctx, cb);
>   }
> 
>   static void diff_include_untracked(const struct stash_info *info, struct diff_options *diff_opt)
>   {
>   	const struct object_id *oid[] = { &info->w_commit, &info->u_tree };
> @@ -1509,33 +1519,50 @@ static int do_push_stash(const struct pathspec *ps, const char *stash_msg, int q
>   	int ret = 0;
>   	struct stash_info info = STASH_INFO_INIT;
>   	struct strbuf patch = STRBUF_INIT;
>   	struct strbuf stash_msg_buf = STRBUF_INIT;
>   	struct strbuf untracked_files = STRBUF_INIT;
> 
> -	if (patch_mode && keep_index == -1)
> -		keep_index = 1;
> -
> -	if (patch_mode && include_untracked) {
> -		fprintf_ln(stderr, _("Can't use --patch and --include-untracked"
> -				     " or --all at the same time"));
> -		ret = -1;
> -		goto done;
> +	if (keep_index == -1) {
> +		if (patch_mode)
> +			keep_index = 1;
> +		else
> +			keep_index = default_keep_index;
>   	}
> 
> -	/* --patch overrides --staged */
> -	if (patch_mode)
> +	if (patch_mode) {
> +		if (include_untracked == -1)
> +			include_untracked = 0;
> +		else if (include_untracked) {
> +			fprintf_ln(stderr,
> +				   _("Can't use --patch and --include-untracked"
> +				     " or --all at the same time"));
> +			ret = -1;
> +			goto done;
> +		}
> +
> +		/* --patch overrides --staged */
>   		only_staged = 0;
> -
> -	if (only_staged && include_untracked) {
> -		fprintf_ln(stderr, _("Can't use --staged and --include-untracked"
> -				     " or --all at the same time"));
> -		ret = -1;
> -		goto done;
>   	}
> 
> +	if (only_staged) {
> +		if (include_untracked == -1)
> +			include_untracked = 0;
> +		else if (include_untracked) {
> +			fprintf_ln(
> +				stderr,
> +				_("Can't use --staged and --include-untracked"
> +				  " or --all at the same time"));
> +			ret = -1;
> +			goto done;
> +		}
> +	}
> +
> +	if (include_untracked == -1)
> +		include_untracked = default_include_untracked;
> +

I'm not sure this would be better, but instead of mixing option compatibility and actually building your logic, why not use a series of die_for_incompatible_opt3 and the like in order to clear the option lists, then build your action logic without resorting to special values?

Show 185 quoted lines
>   	repo_read_index_preload(the_repository, NULL, 0);
>   	if (!include_untracked && ps->nr) {
>   		int i;
>   		char *ps_matched = xcalloc(ps->nr, 1);
> 
>   		/* TODO: audit for interaction with sparse-index. */
> @@ -1688,13 +1715,13 @@ static int do_push_stash(const struct pathspec *ps, const char *stash_msg, int q
>   				fprintf_ln(stderr, _("Cannot remove "
>   						     "worktree changes"));
>   			ret = -1;
>   			goto done;
>   		}
> 
> -		if (keep_index < 1) {
> +		if (!keep_index) {
>   			struct child_process cp = CHILD_PROCESS_INIT;
> 
>   			cp.git_cmd = 1;
>   			strvec_pushl(&cp.args, "reset", "-q", "--refresh", "--",
>   				     NULL);
>   			add_pathspecs(&cp.args, ps);
> @@ -1718,13 +1745,13 @@ static int push_stash(int argc, const char **argv, const char *prefix,
>   		      int push_assumed)
>   {
>   	int force_assume = 0;
>   	int keep_index = -1;
>   	int only_staged = 0;
>   	int patch_mode = 0;
> -	int include_untracked = 0;
> +	int include_untracked = -1;
>   	int quiet = 0;
>   	int pathspec_file_nul = 0;
>   	const char *stash_msg = NULL;
>   	const char *pathspec_from_file = NULL;
>   	struct pathspec ps;
>   	struct option options[] = {
> @@ -1798,13 +1825,13 @@ static int push_stash_unassumed(int argc, const char **argv, const char *prefix)
> 
>   static int save_stash(int argc, const char **argv, const char *prefix)
>   {
>   	int keep_index = -1;
>   	int only_staged = 0;
>   	int patch_mode = 0;
> -	int include_untracked = 0;
> +	int include_untracked = -1;
>   	int quiet = 0;
>   	int ret = 0;
>   	const char *stash_msg = NULL;
>   	struct pathspec ps;
>   	struct strbuf stash_msg_buf = STRBUF_INIT;
>   	struct option options[] = {
> diff --git a/t/t3903-stash.sh b/t/t3903-stash.sh
> index 00db82fb24..4ffcca742c 100755
> --- a/t/t3903-stash.sh
> +++ b/t/t3903-stash.sh
> @@ -1565,7 +1565,126 @@ test_expect_success 'stash apply reports a locked index' '
>   		EOF
>   		test_must_fail git stash apply 2>err &&
>   		test_cmp expect err
>   	)
>   '
> 
> +setup_dirty() {
> +	echo a >tracked &&
> +	echo b >added-modified &&
> +	git add tracked added-modified &&
> +	git commit -m initial &&
> +	echo 1 >>tracked &&
> +	echo 2 >>added-modified &&
> +	echo c >added-new &&
> +	echo d >untracked &&
> +	git add added-modified added-new
> +}
> +
> +test_expect_success 'stash.includeuntracked equivalent to --include-untracked' '
> +	git init using_opt &&
> +	test_when_finished rm -rf using_opt &&
> +	(
> +		cd using_opt &&
> +		setup_dirty &&
> +		git stash push &&
> +		git stash show -u --patch >../using-opt
> +	) &&
> +
> +	test_config stash.includeuntracked true &&
> +	git init using_config &&
> +	test_when_finished rm -rf using_config &&
> +	(
> +		cd using_config &&
> +		setup_dirty &&
> +		git stash push &&
> +		git stash show -u --patch >../using-config
> +	) &&
> +
> +	test_cmp using-opt using-config
> +'
> +
> +test_expect_success 'stash.includeuntracked yields to --no-include-untracked' '
> +	git init no_config &&
> +	test_when_finished rm -rf no_config &&
> +	(
> +		cd no_config &&
> +		setup_dirty &&
> +		git stash push --no-include-untracked &&
> +		git stash show -u --patch >../no-config
> +	) &&
> +
> +	test_config stash.includeuntracked true &&
> +	git init using_config &&
> +	test_when_finished rm -rf using_config &&
> +	(
> +		cd using_config &&
> +		setup_dirty &&
> +		git stash push --no-include-untracked &&
> +		git stash show -u --patch >../using-config
> +	) &&
> +
> +	test_cmp no-config using-config
> +'
> +
> +test_expect_success 'stash.includeuntracked succeeds with --patch' '
> +	test_config stash.includeuntracked true &&
> +	git stash --patch
> +'
> +
> +test_expect_success 'stash.includeuntracked succeeds with --staged' '
> +	test_config stash.includeuntracked true &&
> +	git stash --staged
> +'
> +
> +test_expect_success 'stash.keepindex equivalent to --keep-index' '
> +	git init using_opt &&
> +	test_when_finished rm -rf using_opt &&
> +	(
> +		cd using_opt &&
> +		setup_dirty &&
> +		git stash push &&
> +		git stash show -u --patch >../using-opt
> +	) &&
> +
> +	test_config stash.keepindex true &&
> +	git init using_config &&
> +	test_when_finished rm -rf using_config &&
> +	(
> +		cd using_config &&
> +		setup_dirty &&
> +		git stash push &&
> +		git stash show -u --patch >../using-config
> +	) &&
> +
> +	test_cmp using-opt using-config
> +'
> +
> +test_expect_success 'stash.keepindex yields to --no-keep-index' '
> +	git init no_config &&
> +	test_when_finished rm -rf no_config &&
> +	(
> +		cd no_config &&
> +		setup_dirty &&
> +		git stash push --no-keep-index &&
> +		git stash show -u --patch >../no-config
> +	) &&
> +
> +	test_config stash.keepindex true &&
> +	git init using_config &&
> +	test_when_finished rm -rf using_config &&
> +	(
> +		cd using_config &&
> +		setup_dirty &&
> +		git stash push --no-keep-index &&
> +		git stash show -u --patch >../using-config
> +	) &&
> +
> +	test_cmp no-config using-config
> +'
> +
> +test_expect_success 'stash.keepindex succeeds with --patch' '
> +	test_config stash.keepindex true &&
> +	git stash --patch
> +'
> +
>   test_done
> --
> 2.43.2
> 
Previous: Kristoffer HaugsbakkNext: Ricardo C
Message 15 of 16 in “builtin/stash: configs keepIndex, includeUntracked”
  1. builtin/stash: configs keepIndex, includeUntrackedMithicSpirit, Feb 18, 2024
  2. Phillip WoodFeb 18, 2024
  3. Ricardo CFeb 18, 2024
  4. Phillip WoodFeb 20, 2024
  5. Junio C HamanoFeb 20, 2024
  6. Ricardo CFeb 21, 2024
  7. Junio C HamanoFeb 21, 2024
  8. Ricardo CFeb 21, 2024
  9. Junio C HamanoFeb 21, 2024
  10. Junio C HamanoFeb 20, 2024
  11. Ricardo CFeb 20, 2024
  12. Junio C HamanoFeb 20, 2024
  13. Ricardo CFeb 20, 2024
  14. Kristoffer HaugsbakkFeb 20, 2024
  15. Jean-Noël AvilaFeb 19, 2024
  16. Ricardo CFeb 19, 2024

Read the whole thread, see it on lore, or plain text.

$ cat FOOTERMessages come from the public archive at lore.kernel.org/git, fetched every hour. The front page is chosen and written each morning by an AI editor and can be wrong; the threads themselves are the record. About and API. For agents: an MCP server at https://gitlist.dev/mcp, and any thread, story or person page as Markdown by adding .md to its URL (or sending Accept: text/markdown). Details in /llms.txt.