summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorElijah Newren <newren@gmail.com>2021-09-24 06:37:06 (GMT)
committerJunio C Hamano <gitster@pobox.com>2021-09-24 16:24:25 (GMT)
commit6b657a4c4c6dbb250982c9c31219426437f2ca35 (patch)
tree9388fabe85cecbaf10421c2dfee518878314b817
parentbad4c54684272345b31c1e052406b2d3da739127 (diff)
downloadgit-6b657a4c4c6dbb250982c9c31219426437f2ca35.zip
git-6b657a4c4c6dbb250982c9c31219426437f2ca35.tar.gz
git-6b657a4c4c6dbb250982c9c31219426437f2ca35.tar.bz2
unpack-trees: avoid nuking untracked dir in way of unmerged file
Signed-off-by: Elijah Newren <newren@gmail.com> Signed-off-by: Junio C Hamano <gitster@pobox.com>
-rwxr-xr-xt/t2500-untracked-overwriting.sh2
-rw-r--r--unpack-trees.c35
2 files changed, 32 insertions, 5 deletions
diff --git a/t/t2500-untracked-overwriting.sh b/t/t2500-untracked-overwriting.sh
index 1860436..5ec6605 100755
--- a/t/t2500-untracked-overwriting.sh
+++ b/t/t2500-untracked-overwriting.sh
@@ -197,7 +197,7 @@ test_expect_failure 'git stash and untracked files' '
)
'
-test_expect_failure 'git am --abort and untracked dir vs. unmerged file' '
+test_expect_success 'git am --abort and untracked dir vs. unmerged file' '
test_setup_sequencing am_abort_and_untracked &&
(
cd sequencing_am_abort_and_untracked &&
diff --git a/unpack-trees.c b/unpack-trees.c
index 4b2fb2f..788a092 100644
--- a/unpack-trees.c
+++ b/unpack-trees.c
@@ -2159,9 +2159,15 @@ static int icase_exists(struct unpack_trees_options *o, const char *name, int le
return src && !ie_match_stat(o->src_index, src, st, CE_MATCH_IGNORE_VALID|CE_MATCH_IGNORE_SKIP_WORKTREE);
}
+enum absent_checking_type {
+ COMPLETELY_ABSENT,
+ ABSENT_ANY_DIRECTORY
+};
+
static int check_ok_to_remove(const char *name, int len, int dtype,
const struct cache_entry *ce, struct stat *st,
enum unpack_trees_error_types error_type,
+ enum absent_checking_type absent_type,
struct unpack_trees_options *o)
{
const struct cache_entry *result;
@@ -2196,6 +2202,10 @@ static int check_ok_to_remove(const char *name, int len, int dtype,
return 0;
}
+ /* If we only care about directories, then we can remove */
+ if (absent_type == ABSENT_ANY_DIRECTORY)
+ return 0;
+
/*
* The previous round may already have decided to
* delete this path, which is in a subdirectory that
@@ -2216,6 +2226,7 @@ static int check_ok_to_remove(const char *name, int len, int dtype,
*/
static int verify_absent_1(const struct cache_entry *ce,
enum unpack_trees_error_types error_type,
+ enum absent_checking_type absent_type,
struct unpack_trees_options *o)
{
int len;
@@ -2242,7 +2253,8 @@ static int verify_absent_1(const struct cache_entry *ce,
NULL, o);
else
ret = check_ok_to_remove(path, len, DT_UNKNOWN, NULL,
- &st, error_type, o);
+ &st, error_type,
+ absent_type, o);
}
free(path);
return ret;
@@ -2257,7 +2269,7 @@ static int verify_absent_1(const struct cache_entry *ce,
return check_ok_to_remove(ce->name, ce_namelen(ce),
ce_to_dtype(ce), ce, &st,
- error_type, o);
+ error_type, absent_type, o);
}
}
@@ -2267,14 +2279,23 @@ static int verify_absent(const struct cache_entry *ce,
{
if (!o->skip_sparse_checkout && (ce->ce_flags & CE_NEW_SKIP_WORKTREE))
return 0;
- return verify_absent_1(ce, error_type, o);
+ return verify_absent_1(ce, error_type, COMPLETELY_ABSENT, o);
+}
+
+static int verify_absent_if_directory(const struct cache_entry *ce,
+ enum unpack_trees_error_types error_type,
+ struct unpack_trees_options *o)
+{
+ if (!o->skip_sparse_checkout && (ce->ce_flags & CE_NEW_SKIP_WORKTREE))
+ return 0;
+ return verify_absent_1(ce, error_type, ABSENT_ANY_DIRECTORY, o);
}
static int verify_absent_sparse(const struct cache_entry *ce,
enum unpack_trees_error_types error_type,
struct unpack_trees_options *o)
{
- return verify_absent_1(ce, error_type, o);
+ return verify_absent_1(ce, error_type, COMPLETELY_ABSENT, o);
}
static int merged_entry(const struct cache_entry *ce,
@@ -2348,6 +2369,12 @@ static int merged_entry(const struct cache_entry *ce,
* Previously unmerged entry left as an existence
* marker by read_index_unmerged();
*/
+ if (verify_absent_if_directory(merge,
+ ERROR_WOULD_LOSE_UNTRACKED_OVERWRITTEN, o)) {
+ discard_cache_entry(merge);
+ return -1;
+ }
+
invalidate_ce_path(old, o);
}