All of lore.kernel.org
 help / color / mirror / Atom feed
From: Denton Liu <liu.denton@gmail.com>
To: Git Mailing List <git@vger.kernel.org>
Cc: Junio C Hamano <gitster@pobox.com>,
	Eric Sunshine <sunshine@sunshineco.com>
Subject: [PATCH v4 0/2] stash show: learn --include-untracked and --only-untracked
Date: Wed,  3 Mar 2021 03:16:41 -0800	[thread overview]
Message-ID: <cover.1614770171.git.liu.denton@gmail.com> (raw)
In-Reply-To: <cover.1613459474.git.liu.denton@gmail.com>

A blindspot that I've noticed in git is that it's not possible to
properly view a stash entry that has untracked files via `git stash
show`. Teach `git stash show --include-untracked` which should do this.
In addition, this series also teaches `--only-untracked` and the
`stash.showIncludeUntracked` config option.

This series is based on 'dl/stash-cleanup'.

Changes since v3:

* Incorporate Junio's SQUASH??? commits

* Implement a custom unpack_trees() callback to detect the case where
  there are duplicate entries in worktree and untracked commits

Changes since v2:

* Base this series on top of 'dl/stash-cleanup'

* Attempt to replicate the read-tree code to merge the untracked tree

Changes since v1:

* Add a dash for <log-options> and <diff-options>

* Fix the misspelling of --include-untracked in a commit message

* Change the approach from concatenating diffs to using `git read-tree`

Denton Liu (2):
  stash show: teach --include-untracked and --only-untracked
  stash show: learn stash.showIncludeUntracked

 Documentation/config/stash.txt         |   5 ++
 Documentation/git-stash.txt            |  22 +++--
 builtin/stash.c                        |  62 +++++++++++++-
 contrib/completion/git-completion.bash |   2 +-
 t/t3905-stash-include-untracked.sh     | 108 +++++++++++++++++++++++++
 unpack-trees.c                         |  22 +++++
 unpack-trees.h                         |   2 +
 7 files changed, 214 insertions(+), 9 deletions(-)

Range-diff against v3:
1:  85b81f2f06 ! 1:  af3757135b stash show: teach --include-untracked and --only-untracked
    @@ Commit message
         third-parent if it exists, are shown in addition to the paths that have
         modifications between the stash base and the working tree in the stash.
     
    -    One limitation of this is that it would be possible to manually craft a
    -    stash entry where duplicate untracked files in the stash entry will mask
    -    tracked files. This seems like an instance of "Doctor, it hurts when I
    -    do this! So don't do that!" so this can be written off.
    +    It is possible to manually craft a malformed stash entry where duplicate
    +    untracked files in the stash entry will mask tracked files. We detect
    +    and error out in that case via a custom unpack_trees() callback:
    +    stash_worktree_untracked_merge().
     
         Also, teach stash the --only-untracked option which only shows the
         untracked files of a stash entry. This is similar to `git show stash^3`
         but it is nice to provide a convenient abstraction for it so that users
         do not have to think about the underlying implementation.
     
    -
    - ## Notes ##
    -    I am not familiar with the read-tree code so this attempt at replicating
    -    the read-tree code may in diff_include_untracked() may be incorrect
    -    (particularly the use of the_index?).
    -
    -    Also, I could not figure out how to make unpack_trees() error out in the
    -    case where untracked tree entry contains duplicate entries with the
    -    worktree entry.
    -
      ## Documentation/git-stash.txt ##
     @@ Documentation/git-stash.txt: SYNOPSIS
      --------
    @@ builtin/stash.c: static int git_stash_config(const char *var, const char *value,
     +	unpack_tree_opt.head_idx = -1;
     +	unpack_tree_opt.src_index = &the_index;
     +	unpack_tree_opt.dst_index = &the_index;
    -+	unpack_tree_opt.fn = twoway_merge;
    ++	unpack_tree_opt.merge = 1;
    ++	unpack_tree_opt.fn = stash_worktree_untracked_merge;
     +
     +	if (unpack_trees(ARRAY_SIZE(tree_desc), tree_desc, &unpack_tree_opt))
     +		die(_("failed to unpack trees"));
    @@ t/t3905-stash-include-untracked.sh: test_expect_success 'stash -u with globs' '
     +	>untracked &&
     +	>tracked &&
     +	git add tracked &&
    ++	empty_blob_oid=$(git rev-parse --short :tracked) &&
     +	git stash -u &&
     +
     +	cat >expect <<-EOF &&
    @@ t/t3905-stash-include-untracked.sh: test_expect_success 'stash -u with globs' '
     +	cat >expect <<-EOF &&
     +	diff --git a/tracked b/tracked
     +	new file mode 100644
    -+	index 0000000..e69de29
    ++	index 0000000..$empty_blob_oid
     +	diff --git a/untracked b/untracked
     +	new file mode 100644
    -+	index 0000000..e69de29
    ++	index 0000000..$empty_blob_oid
     +	EOF
     +	git stash show -p --include-untracked >actual &&
     +	test_cmp expect actual &&
    @@ t/t3905-stash-include-untracked.sh: test_expect_success 'stash -u with globs' '
     +	>untracked &&
     +	>tracked &&
     +	git add tracked &&
    ++	empty_blob_oid=$(git rev-parse --short :tracked) &&
     +	git stash -u &&
     +
     +	cat >expect <<-EOF &&
    @@ t/t3905-stash-include-untracked.sh: test_expect_success 'stash -u with globs' '
     +	cat >expect <<-EOF &&
     +	diff --git a/untracked b/untracked
     +	new file mode 100644
    -+	index 0000000..e69de29
    ++	index 0000000..$empty_blob_oid
     +	EOF
     +	git stash show -p --only-untracked >actual &&
     +	test_cmp expect actual &&
    @@ t/t3905-stash-include-untracked.sh: test_expect_success 'stash -u with globs' '
     +	git stash show --include-untracked --no-include-untracked >actual &&
     +	test_cmp expect actual
     +'
    ++
    ++test_expect_success 'stash show --include-untracked errors on duplicate files' '
    ++	git reset --hard &&
    ++	git clean -xf &&
    ++	>tracked &&
    ++	git add tracked &&
    ++	tree=$(git write-tree) &&
    ++	i_commit=$(git commit-tree -p HEAD -m "index on any-branch" "$tree") &&
    ++	test_when_finished "rm -f untracked_index" &&
    ++	u_commit=$(
    ++		GIT_INDEX_FILE="untracked_index" &&
    ++		export GIT_INDEX_FILE &&
    ++		git update-index --add tracked &&
    ++		u_tree=$(git write-tree) &&
    ++		git commit-tree -m "untracked files on any-branch" "$u_tree"
    ++	) &&
    ++	w_commit=$(git commit-tree -p HEAD -p "$i_commit" -p "$u_commit" -m "WIP on any-branch" "$tree") &&
    ++	test_must_fail git stash show --include-untracked "$w_commit" 2>err &&
    ++	test_i18ngrep "worktree and untracked commit have duplicate entries: tracked" err
    ++'
     +
      test_done
    +
    + ## unpack-trees.c ##
    +@@ unpack-trees.c: int oneway_merge(const struct cache_entry * const *src,
    + 	}
    + 	return merged_entry(a, old, o);
    + }
    ++
    ++/*
    ++ * Merge worktree and untracked entries in a stash entry.
    ++ *
    ++ * Ignore all index entries. Collapse remaining trees but make sure that they
    ++ * don't have any conflicting files.
    ++ */
    ++int stash_worktree_untracked_merge(const struct cache_entry * const *src,
    ++				   struct unpack_trees_options *o)
    ++{
    ++	const struct cache_entry *worktree = src[1];
    ++	const struct cache_entry *untracked = src[2];
    ++
    ++	if (o->merge_size != 2)
    ++		BUG("invalid merge_size: %d", o->merge_size);
    ++
    ++	if (worktree && untracked)
    ++		return error(_("worktree and untracked commit have duplicate entries: %s"),
    ++			     super_prefixed(worktree->name));
    ++
    ++	return merged_entry(worktree ? worktree : untracked, NULL, o);
    ++}
    +
    + ## unpack-trees.h ##
    +@@ unpack-trees.h: int bind_merge(const struct cache_entry * const *src,
    + 	       struct unpack_trees_options *o);
    + int oneway_merge(const struct cache_entry * const *src,
    + 		 struct unpack_trees_options *o);
    ++int stash_worktree_untracked_merge(const struct cache_entry * const *src,
    ++				   struct unpack_trees_options *o);
    + 
    + #endif
2:  d19d07ec27 = 2:  3480086f1d stash show: learn stash.showIncludeUntracked
-- 
2.31.0.rc1.228.gb75b4e4ce2


  parent reply	other threads:[~2021-03-04  0:22 UTC|newest]

Thread overview: 46+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2021-02-02  9:31 [PATCH 0/9] stash show: learn --include-untracked and --only-untracked Denton Liu
2021-02-02  9:33 ` Denton Liu
2021-02-02  9:33 ` [PATCH 1/9] git-stash.txt: be explicit about subcommand options Denton Liu
2021-02-02 17:37   ` Eric Sunshine
2021-02-02  9:33 ` [PATCH 2/9] t3905: remove spaces after redirect operators Denton Liu
2021-02-02  9:33 ` [PATCH 3/9] t3905: move all commands into test cases Denton Liu
2021-02-02 21:41   ` Junio C Hamano
2021-02-02  9:33 ` [PATCH 4/9] t3905: remove nested git in command substitution Denton Liu
2021-02-02  9:33 ` [PATCH 5/9] t3905: replace test -s with test_file_not_empty Denton Liu
2021-02-02  9:33 ` [PATCH 6/9] t3905: use test_cmp() to check file contents Denton Liu
2021-02-02  9:33 ` [PATCH 7/9] stash: declare ref_stash as an array Denton Liu
2021-02-02 21:46   ` Junio C Hamano
2021-02-02  9:33 ` [PATCH 8/9] stash show: teach --include-tracked and --only-untracked Denton Liu
2021-02-02 21:56   ` Junio C Hamano
2021-02-02  9:33 ` [PATCH 9/9] stash show: learn stash.showIncludeUntracked Denton Liu
2021-02-09  7:28 ` [PATCH v2 0/9] stash show: learn --include-untracked and --only-untracked Denton Liu
2021-02-09  7:28   ` [PATCH v2 1/9] git-stash.txt: be explicit about subcommand options Denton Liu
2021-02-10  7:17     ` Junio C Hamano
2021-02-11 19:07       ` [PATCH] fixup! " Denton Liu
2021-02-09  7:28   ` [PATCH v2 2/9] t3905: remove spaces after redirect operators Denton Liu
2021-02-10  7:18     ` Junio C Hamano
2021-02-09  7:28   ` [PATCH v2 3/9] t3905: move all commands into test cases Denton Liu
2021-02-09  7:28   ` [PATCH v2 4/9] t3905: remove nested git in command substitution Denton Liu
2021-02-10  7:24     ` Junio C Hamano
2021-02-09  7:28   ` [PATCH v2 5/9] t3905: replace test -s with test_file_not_empty Denton Liu
2021-02-09  7:28   ` [PATCH v2 6/9] t3905: use test_cmp() to check file contents Denton Liu
2021-02-09  7:28   ` [PATCH v2 7/9] stash: declare ref_stash as an array Denton Liu
2021-02-10  7:28     ` Junio C Hamano
2021-02-09  7:28   ` [PATCH v2 8/9] stash show: teach --include-untracked and --only-untracked Denton Liu
2021-02-10  7:53     ` Junio C Hamano
2021-02-16  3:15       ` Denton Liu
2021-02-16  6:42         ` Junio C Hamano
2021-02-09  7:28   ` [PATCH v2 9/9] stash show: learn stash.showIncludeUntracked Denton Liu
2021-02-16  7:11   ` [PATCH v3 0/2] stash show: learn --include-untracked and --only-untracked Denton Liu
2021-02-16  7:11     ` [PATCH v3 1/2] stash show: teach " Denton Liu
2021-02-16 20:22       ` Junio C Hamano
2021-02-17 11:18         ` Denton Liu
2021-02-17 17:50           ` Junio C Hamano
2021-02-17  2:31       ` Junio C Hamano
2021-02-16  7:11     ` [PATCH v3 2/2] stash show: learn stash.showIncludeUntracked Denton Liu
2021-03-03 11:16     ` Denton Liu [this message]
2021-03-03 11:16       ` [PATCH v4 1/2] stash show: teach --include-untracked and --only-untracked Denton Liu
2021-03-03 11:16       ` [PATCH v4 2/2] stash show: learn stash.showIncludeUntracked Denton Liu
2021-03-04  0:38       ` [PATCH v4 0/2] stash show: learn --include-untracked and --only-untracked Junio C Hamano
2021-03-04  1:33         ` Denton Liu
2021-03-04  1:42           ` Denton Liu

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=cover.1614770171.git.liu.denton@gmail.com \
    --to=liu.denton@gmail.com \
    --cc=git@vger.kernel.org \
    --cc=gitster@pobox.com \
    --cc=sunshine@sunshineco.com \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.