@@ -465,6 +465,64 @@ static void invalidate_ce_path(struct cache_entry *ce)
465
465
cache_tree_invalidate_path (active_cache_tree , ce -> name );
466
466
}
467
467
468
+ static int verify_clean_subdirectory (const char * path , const char * action ,
469
+ struct unpack_trees_options * o )
470
+ {
471
+ /*
472
+ * we are about to extract "path"; we would not want to lose
473
+ * anything in the existing directory there.
474
+ */
475
+ int namelen ;
476
+ int pos , i ;
477
+ struct dir_struct d ;
478
+ char * pathbuf ;
479
+ int cnt = 0 ;
480
+
481
+ /*
482
+ * First let's make sure we do not have a local modification
483
+ * in that directory.
484
+ */
485
+ namelen = strlen (path );
486
+ pos = cache_name_pos (path , namelen );
487
+ if (0 <= pos )
488
+ return cnt ; /* we have it as nondirectory */
489
+ pos = - pos - 1 ;
490
+ for (i = pos ; i < active_nr ; i ++ ) {
491
+ struct cache_entry * ce = active_cache [i ];
492
+ int len = ce_namelen (ce );
493
+ if (len < namelen ||
494
+ strncmp (path , ce -> name , namelen ) ||
495
+ ce -> name [namelen ] != '/' )
496
+ break ;
497
+ /*
498
+ * ce->name is an entry in the subdirectory.
499
+ */
500
+ if (!ce_stage (ce )) {
501
+ verify_uptodate (ce , o );
502
+ ce -> ce_mode = 0 ;
503
+ }
504
+ cnt ++ ;
505
+ }
506
+
507
+ /*
508
+ * Then we need to make sure that we do not lose a locally
509
+ * present file that is not ignored.
510
+ */
511
+ pathbuf = xmalloc (namelen + 2 );
512
+ memcpy (pathbuf , path , namelen );
513
+ strcpy (pathbuf + namelen , "/" );
514
+
515
+ memset (& d , 0 , sizeof (d ));
516
+ if (o -> dir )
517
+ d .exclude_per_dir = o -> dir -> exclude_per_dir ;
518
+ i = read_directory (& d , path , pathbuf , namelen + 1 , NULL );
519
+ if (i )
520
+ die ("Updating '%s' would lose untracked files in it" ,
521
+ path );
522
+ free (pathbuf );
523
+ return cnt ;
524
+ }
525
+
468
526
/*
469
527
* We do not want to remove or overwrite a working tree file that
470
528
* is not tracked, unless it is ignored.
@@ -476,9 +534,62 @@ static void verify_absent(const char *path, const char *action,
476
534
477
535
if (o -> index_only || o -> reset || !o -> update )
478
536
return ;
479
- if (!lstat (path , & st ) && !(o -> dir && excluded (o -> dir , path )))
537
+
538
+ if (!lstat (path , & st )) {
539
+ int cnt ;
540
+
541
+ if (o -> dir && excluded (o -> dir , path ))
542
+ /*
543
+ * path is explicitly excluded, so it is Ok to
544
+ * overwrite it.
545
+ */
546
+ return ;
547
+ if (S_ISDIR (st .st_mode )) {
548
+ /*
549
+ * We are checking out path "foo" and
550
+ * found "foo/." in the working tree.
551
+ * This is tricky -- if we have modified
552
+ * files that are in "foo/" we would lose
553
+ * it.
554
+ */
555
+ cnt = verify_clean_subdirectory (path , action , o );
556
+
557
+ /*
558
+ * If this removed entries from the index,
559
+ * what that means is:
560
+ *
561
+ * (1) the caller unpack_trees_rec() saw path/foo
562
+ * in the index, and it has not removed it because
563
+ * it thinks it is handling 'path' as blob with
564
+ * D/F conflict;
565
+ * (2) we will return "ok, we placed a merged entry
566
+ * in the index" which would cause o->pos to be
567
+ * incremented by one;
568
+ * (3) however, original o->pos now has 'path/foo'
569
+ * marked with "to be removed".
570
+ *
571
+ * We need to increment it by the number of
572
+ * deleted entries here.
573
+ */
574
+ o -> pos += cnt ;
575
+ return ;
576
+ }
577
+
578
+ /*
579
+ * The previous round may already have decided to
580
+ * delete this path, which is in a subdirectory that
581
+ * is being replaced with a blob.
582
+ */
583
+ cnt = cache_name_pos (path , strlen (path ));
584
+ if (0 <= cnt ) {
585
+ struct cache_entry * ce = active_cache [cnt ];
586
+ if (!ce_stage (ce ) && !ce -> ce_mode )
587
+ return ;
588
+ }
589
+
480
590
die ("Untracked working tree file '%s' "
481
591
"would be %s by merge." , path , action );
592
+ }
482
593
}
483
594
484
595
static int merged_entry (struct cache_entry * merge , struct cache_entry * old ,
0 commit comments