Skip to content

Commit 1fdd51a

Browse files
newrengitster
authored andcommitted
unpack-trees: avoid nuking untracked dir in way of unmerged file
Signed-off-by: Elijah Newren <[email protected]> Signed-off-by: Junio C Hamano <[email protected]>
1 parent 480d3d6 commit 1fdd51a

File tree

2 files changed

+32
-5
lines changed

2 files changed

+32
-5
lines changed

t/t2500-untracked-overwriting.sh

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -197,7 +197,7 @@ test_expect_failure 'git stash and untracked files' '
197197
)
198198
'
199199

200-
test_expect_failure 'git am --abort and untracked dir vs. unmerged file' '
200+
test_expect_success 'git am --abort and untracked dir vs. unmerged file' '
201201
test_setup_sequencing am_abort_and_untracked &&
202202
(
203203
cd sequencing_am_abort_and_untracked &&

unpack-trees.c

Lines changed: 31 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -2176,9 +2176,15 @@ static int icase_exists(struct unpack_trees_options *o, const char *name, int le
21762176
return src && !ie_match_stat(o->src_index, src, st, CE_MATCH_IGNORE_VALID|CE_MATCH_IGNORE_SKIP_WORKTREE);
21772177
}
21782178

2179+
enum absent_checking_type {
2180+
COMPLETELY_ABSENT,
2181+
ABSENT_ANY_DIRECTORY
2182+
};
2183+
21792184
static int check_ok_to_remove(const char *name, int len, int dtype,
21802185
const struct cache_entry *ce, struct stat *st,
21812186
enum unpack_trees_error_types error_type,
2187+
enum absent_checking_type absent_type,
21822188
struct unpack_trees_options *o)
21832189
{
21842190
const struct cache_entry *result;
@@ -2213,6 +2219,10 @@ static int check_ok_to_remove(const char *name, int len, int dtype,
22132219
return 0;
22142220
}
22152221

2222+
/* If we only care about directories, then we can remove */
2223+
if (absent_type == ABSENT_ANY_DIRECTORY)
2224+
return 0;
2225+
22162226
/*
22172227
* The previous round may already have decided to
22182228
* delete this path, which is in a subdirectory that
@@ -2233,6 +2243,7 @@ static int check_ok_to_remove(const char *name, int len, int dtype,
22332243
*/
22342244
static int verify_absent_1(const struct cache_entry *ce,
22352245
enum unpack_trees_error_types error_type,
2246+
enum absent_checking_type absent_type,
22362247
struct unpack_trees_options *o)
22372248
{
22382249
int len;
@@ -2259,7 +2270,8 @@ static int verify_absent_1(const struct cache_entry *ce,
22592270
NULL, o);
22602271
else
22612272
ret = check_ok_to_remove(path, len, DT_UNKNOWN, NULL,
2262-
&st, error_type, o);
2273+
&st, error_type,
2274+
absent_type, o);
22632275
}
22642276
free(path);
22652277
return ret;
@@ -2274,7 +2286,7 @@ static int verify_absent_1(const struct cache_entry *ce,
22742286

22752287
return check_ok_to_remove(ce->name, ce_namelen(ce),
22762288
ce_to_dtype(ce), ce, &st,
2277-
error_type, o);
2289+
error_type, absent_type, o);
22782290
}
22792291
}
22802292

@@ -2284,14 +2296,23 @@ static int verify_absent(const struct cache_entry *ce,
22842296
{
22852297
if (!o->skip_sparse_checkout && (ce->ce_flags & CE_NEW_SKIP_WORKTREE))
22862298
return 0;
2287-
return verify_absent_1(ce, error_type, o);
2299+
return verify_absent_1(ce, error_type, COMPLETELY_ABSENT, o);
2300+
}
2301+
2302+
static int verify_absent_if_directory(const struct cache_entry *ce,
2303+
enum unpack_trees_error_types error_type,
2304+
struct unpack_trees_options *o)
2305+
{
2306+
if (!o->skip_sparse_checkout && (ce->ce_flags & CE_NEW_SKIP_WORKTREE))
2307+
return 0;
2308+
return verify_absent_1(ce, error_type, ABSENT_ANY_DIRECTORY, o);
22882309
}
22892310

22902311
static int verify_absent_sparse(const struct cache_entry *ce,
22912312
enum unpack_trees_error_types error_type,
22922313
struct unpack_trees_options *o)
22932314
{
2294-
return verify_absent_1(ce, error_type, o);
2315+
return verify_absent_1(ce, error_type, COMPLETELY_ABSENT, o);
22952316
}
22962317

22972318
static int merged_entry(const struct cache_entry *ce,
@@ -2365,6 +2386,12 @@ static int merged_entry(const struct cache_entry *ce,
23652386
* Previously unmerged entry left as an existence
23662387
* marker by read_index_unmerged();
23672388
*/
2389+
if (verify_absent_if_directory(merge,
2390+
ERROR_WOULD_LOSE_UNTRACKED_OVERWRITTEN, o)) {
2391+
discard_cache_entry(merge);
2392+
return -1;
2393+
}
2394+
23682395
invalidate_ce_path(old, o);
23692396
}
23702397

0 commit comments

Comments
 (0)