summaryrefslogtreecommitdiff
path: root/unpack-trees.c
diff options
context:
space:
mode:
authorDenton Liu <liu.denton@gmail.com>2021-03-03 11:16:42 (GMT)
committerJunio C Hamano <gitster@pobox.com>2021-03-05 22:31:26 (GMT)
commitd3c7bf73bdb679dd98c6aff65edbce4df743ddd3 (patch)
tree7e4757674006ff07cfe29906afdc6bb8f0ec8aea /unpack-trees.c
parent3e885f02775dad0d907d447bc3c24fa07870b41f (diff)
downloadgit-d3c7bf73bdb679dd98c6aff65edbce4df743ddd3.zip
git-d3c7bf73bdb679dd98c6aff65edbce4df743ddd3.tar.gz
git-d3c7bf73bdb679dd98c6aff65edbce4df743ddd3.tar.bz2
stash show: teach --include-untracked and --only-untracked
Stash entries can be made with untracked files via `git stash push --include-untracked`. However, because the untracked files are stored in the third parent of the stash entry and not the stash entry itself, running `git stash show` does not include the untracked files as part of the diff. With --include-untracked, untracked paths, which are recorded in the 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. 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. Signed-off-by: Denton Liu <liu.denton@gmail.com> Signed-off-by: Junio C Hamano <gitster@pobox.com>
Diffstat (limited to 'unpack-trees.c')
-rw-r--r--unpack-trees.c22
1 files changed, 22 insertions, 0 deletions
diff --git a/unpack-trees.c b/unpack-trees.c
index af6e9b9..dde8c32 100644
--- a/unpack-trees.c
+++ b/unpack-trees.c
@@ -2566,3 +2566,25 @@ 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);
+}