@@ -2271,6 +2271,25 @@ static struct patch *in_fn_table(const char *name)
2271
2271
return NULL ;
2272
2272
}
2273
2273
2274
+ /*
2275
+ * item->util in the filename table records the status of the path.
2276
+ * Usually it points at a patch (whose result records the contents
2277
+ * of it after applying it), but it could be PATH_WAS_DELETED for a
2278
+ * path that a previously applied patch has already removed.
2279
+ */
2280
+ #define PATH_TO_BE_DELETED ((struct patch *) -2)
2281
+ #define PATH_WAS_DELETED ((struct patch *) -1)
2282
+
2283
+ static int to_be_deleted (struct patch * patch )
2284
+ {
2285
+ return patch == PATH_TO_BE_DELETED ;
2286
+ }
2287
+
2288
+ static int was_deleted (struct patch * patch )
2289
+ {
2290
+ return patch == PATH_WAS_DELETED ;
2291
+ }
2292
+
2274
2293
static void add_to_fn_table (struct patch * patch )
2275
2294
{
2276
2295
struct string_list_item * item ;
@@ -2291,7 +2310,22 @@ static void add_to_fn_table(struct patch *patch)
2291
2310
*/
2292
2311
if ((patch -> new_name == NULL ) || (patch -> is_rename )) {
2293
2312
item = string_list_insert (patch -> old_name , & fn_table );
2294
- item -> util = (struct patch * ) -1 ;
2313
+ item -> util = PATH_WAS_DELETED ;
2314
+ }
2315
+ }
2316
+
2317
+ static void prepare_fn_table (struct patch * patch )
2318
+ {
2319
+ /*
2320
+ * store information about incoming file deletion
2321
+ */
2322
+ while (patch ) {
2323
+ if ((patch -> new_name == NULL ) || (patch -> is_rename )) {
2324
+ struct string_list_item * item ;
2325
+ item = string_list_insert (patch -> old_name , & fn_table );
2326
+ item -> util = PATH_TO_BE_DELETED ;
2327
+ }
2328
+ patch = patch -> next ;
2295
2329
}
2296
2330
}
2297
2331
@@ -2304,8 +2338,8 @@ static int apply_data(struct patch *patch, struct stat *st, struct cache_entry *
2304
2338
struct patch * tpatch ;
2305
2339
2306
2340
if (!(patch -> is_copy || patch -> is_rename ) &&
2307
- (( tpatch = in_fn_table (patch -> old_name )) != NULL )) {
2308
- if (tpatch == ( struct patch * ) -1 ) {
2341
+ (tpatch = in_fn_table (patch -> old_name )) != NULL && ! to_be_deleted ( tpatch )) {
2342
+ if (was_deleted ( tpatch ) ) {
2309
2343
return error ("patch %s has been renamed/deleted" ,
2310
2344
patch -> old_name );
2311
2345
}
@@ -2399,17 +2433,19 @@ static int check_preimage(struct patch *patch, struct cache_entry **ce, struct s
2399
2433
assert (patch -> is_new <= 0 );
2400
2434
2401
2435
if (!(patch -> is_copy || patch -> is_rename ) &&
2402
- (tpatch = in_fn_table (old_name )) != NULL ) {
2403
- if (tpatch == ( struct patch * ) -1 ) {
2436
+ (tpatch = in_fn_table (old_name )) != NULL && ! to_be_deleted ( tpatch ) ) {
2437
+ if (was_deleted ( tpatch ))
2404
2438
return error ("%s: has been deleted/renamed" , old_name );
2405
- }
2406
2439
st_mode = tpatch -> new_mode ;
2407
2440
} else if (!cached ) {
2408
2441
stat_ret = lstat (old_name , st );
2409
2442
if (stat_ret && errno != ENOENT )
2410
2443
return error ("%s: %s" , old_name , strerror (errno ));
2411
2444
}
2412
2445
2446
+ if (to_be_deleted (tpatch ))
2447
+ tpatch = NULL ;
2448
+
2413
2449
if (check_index && !tpatch ) {
2414
2450
int pos = cache_name_pos (old_name , strlen (old_name ));
2415
2451
if (pos < 0 ) {
@@ -2471,6 +2507,7 @@ static int check_patch(struct patch *patch)
2471
2507
const char * new_name = patch -> new_name ;
2472
2508
const char * name = old_name ? old_name : new_name ;
2473
2509
struct cache_entry * ce = NULL ;
2510
+ struct patch * tpatch ;
2474
2511
int ok_if_exists ;
2475
2512
int status ;
2476
2513
@@ -2481,7 +2518,8 @@ static int check_patch(struct patch *patch)
2481
2518
return status ;
2482
2519
old_name = patch -> old_name ;
2483
2520
2484
- if (in_fn_table (new_name ) == (struct patch * ) -1 )
2521
+ if ((tpatch = in_fn_table (new_name )) &&
2522
+ (was_deleted (tpatch ) || to_be_deleted (tpatch )))
2485
2523
/*
2486
2524
* A type-change diff is always split into a patch to
2487
2525
* delete old, immediately followed by a patch to
@@ -2533,6 +2571,7 @@ static int check_patch_list(struct patch *patch)
2533
2571
{
2534
2572
int err = 0 ;
2535
2573
2574
+ prepare_fn_table (patch );
2536
2575
while (patch ) {
2537
2576
if (apply_verbosely )
2538
2577
say_patch_name (stderr ,
0 commit comments