10
10
#include "cache-tree.h"
11
11
#include "path-list.h"
12
12
#include "unpack-trees.h"
13
+ #include "refs.h"
13
14
14
15
/*
15
16
* diff-files
@@ -333,6 +334,26 @@ int run_diff_files_cmd(struct rev_info *revs, int argc, const char **argv)
333
334
}
334
335
return run_diff_files (revs , options );
335
336
}
337
+ /*
338
+ * See if work tree has an entity that can be staged. Return 0 if so,
339
+ * return 1 if not and return -1 if error.
340
+ */
341
+ static int check_work_tree_entity (const struct cache_entry * ce , struct stat * st , char * symcache )
342
+ {
343
+ if (lstat (ce -> name , st ) < 0 ) {
344
+ if (errno != ENOENT && errno != ENOTDIR )
345
+ return -1 ;
346
+ return 1 ;
347
+ }
348
+ if (has_symlink_leading_path (ce -> name , symcache ))
349
+ return 1 ;
350
+ if (S_ISDIR (st -> st_mode )) {
351
+ unsigned char sub [20 ];
352
+ if (resolve_gitlink_ref (ce -> name , "HEAD" , sub ))
353
+ return 1 ;
354
+ }
355
+ return 0 ;
356
+ }
336
357
337
358
int run_diff_files (struct rev_info * revs , unsigned int option )
338
359
{
@@ -468,6 +489,11 @@ int run_diff_files(struct rev_info *revs, unsigned int option)
468
489
* diff-index
469
490
*/
470
491
492
+ struct oneway_unpack_data {
493
+ struct rev_info * revs ;
494
+ char symcache [PATH_MAX ];
495
+ };
496
+
471
497
/* A file entry went away or appeared */
472
498
static void diff_index_show_file (struct rev_info * revs ,
473
499
const char * prefix ,
@@ -481,16 +507,20 @@ static void diff_index_show_file(struct rev_info *revs,
481
507
static int get_stat_data (struct cache_entry * ce ,
482
508
const unsigned char * * sha1p ,
483
509
unsigned int * modep ,
484
- int cached , int match_missing )
510
+ int cached , int match_missing ,
511
+ struct oneway_unpack_data * cbdata )
485
512
{
486
513
const unsigned char * sha1 = ce -> sha1 ;
487
514
unsigned int mode = ce -> ce_mode ;
488
515
489
516
if (!cached ) {
490
517
int changed ;
491
518
struct stat st ;
492
- if (lstat (ce -> name , & st ) < 0 ) {
493
- if (errno == ENOENT && match_missing ) {
519
+ changed = check_work_tree_entity (ce , & st , cbdata -> symcache );
520
+ if (changed < 0 )
521
+ return -1 ;
522
+ else if (changed ) {
523
+ if (match_missing ) {
494
524
* sha1p = sha1 ;
495
525
* modep = mode ;
496
526
return 0 ;
@@ -509,32 +539,35 @@ static int get_stat_data(struct cache_entry *ce,
509
539
return 0 ;
510
540
}
511
541
512
- static void show_new_file (struct rev_info * revs ,
542
+ static void show_new_file (struct oneway_unpack_data * cbdata ,
513
543
struct cache_entry * new ,
514
544
int cached , int match_missing )
515
545
{
516
546
const unsigned char * sha1 ;
517
547
unsigned int mode ;
548
+ struct rev_info * revs = cbdata -> revs ;
518
549
519
- /* New file in the index: it might actually be different in
550
+ /*
551
+ * New file in the index: it might actually be different in
520
552
* the working copy.
521
553
*/
522
- if (get_stat_data (new , & sha1 , & mode , cached , match_missing ) < 0 )
554
+ if (get_stat_data (new , & sha1 , & mode , cached , match_missing , cbdata ) < 0 )
523
555
return ;
524
556
525
557
diff_index_show_file (revs , "+" , new , sha1 , mode );
526
558
}
527
559
528
- static int show_modified (struct rev_info * revs ,
560
+ static int show_modified (struct oneway_unpack_data * cbdata ,
529
561
struct cache_entry * old ,
530
562
struct cache_entry * new ,
531
563
int report_missing ,
532
564
int cached , int match_missing )
533
565
{
534
566
unsigned int mode , oldmode ;
535
567
const unsigned char * sha1 ;
568
+ struct rev_info * revs = cbdata -> revs ;
536
569
537
- if (get_stat_data (new , & sha1 , & mode , cached , match_missing ) < 0 ) {
570
+ if (get_stat_data (new , & sha1 , & mode , cached , match_missing , cbdata ) < 0 ) {
538
571
if (report_missing )
539
572
diff_index_show_file (revs , "-" , old ,
540
573
old -> sha1 , old -> ce_mode );
@@ -602,7 +635,8 @@ static void do_oneway_diff(struct unpack_trees_options *o,
602
635
struct cache_entry * idx ,
603
636
struct cache_entry * tree )
604
637
{
605
- struct rev_info * revs = o -> unpack_data ;
638
+ struct oneway_unpack_data * cbdata = o -> unpack_data ;
639
+ struct rev_info * revs = cbdata -> revs ;
606
640
int match_missing , cached ;
607
641
608
642
/*
@@ -625,7 +659,7 @@ static void do_oneway_diff(struct unpack_trees_options *o,
625
659
* Something added to the tree?
626
660
*/
627
661
if (!tree ) {
628
- show_new_file (revs , idx , cached , match_missing );
662
+ show_new_file (cbdata , idx , cached , match_missing );
629
663
return ;
630
664
}
631
665
@@ -638,7 +672,7 @@ static void do_oneway_diff(struct unpack_trees_options *o,
638
672
}
639
673
640
674
/* Show difference between old and new */
641
- show_modified (revs , tree , idx , 1 , cached , match_missing );
675
+ show_modified (cbdata , tree , idx , 1 , cached , match_missing );
642
676
}
643
677
644
678
static inline void skip_same_name (struct cache_entry * ce , struct unpack_trees_options * o )
@@ -675,7 +709,8 @@ static int oneway_diff(struct cache_entry **src, struct unpack_trees_options *o)
675
709
{
676
710
struct cache_entry * idx = src [0 ];
677
711
struct cache_entry * tree = src [1 ];
678
- struct rev_info * revs = o -> unpack_data ;
712
+ struct oneway_unpack_data * cbdata = o -> unpack_data ;
713
+ struct rev_info * revs = cbdata -> revs ;
679
714
680
715
if (idx && ce_stage (idx ))
681
716
skip_same_name (idx , o );
@@ -702,6 +737,7 @@ int run_diff_index(struct rev_info *revs, int cached)
702
737
const char * tree_name ;
703
738
struct unpack_trees_options opts ;
704
739
struct tree_desc t ;
740
+ struct oneway_unpack_data unpack_cb ;
705
741
706
742
mark_merge_entries ();
707
743
@@ -711,12 +747,14 @@ int run_diff_index(struct rev_info *revs, int cached)
711
747
if (!tree )
712
748
return error ("bad tree object %s" , tree_name );
713
749
750
+ unpack_cb .revs = revs ;
751
+ unpack_cb .symcache [0 ] = '\0' ;
714
752
memset (& opts , 0 , sizeof (opts ));
715
753
opts .head_idx = 1 ;
716
754
opts .index_only = cached ;
717
755
opts .merge = 1 ;
718
756
opts .fn = oneway_diff ;
719
- opts .unpack_data = revs ;
757
+ opts .unpack_data = & unpack_cb ;
720
758
opts .src_index = & the_index ;
721
759
opts .dst_index = NULL ;
722
760
@@ -738,6 +776,7 @@ int do_diff_cache(const unsigned char *tree_sha1, struct diff_options *opt)
738
776
struct cache_entry * last = NULL ;
739
777
struct unpack_trees_options opts ;
740
778
struct tree_desc t ;
779
+ struct oneway_unpack_data unpack_cb ;
741
780
742
781
/*
743
782
* This is used by git-blame to run diff-cache internally;
@@ -766,12 +805,14 @@ int do_diff_cache(const unsigned char *tree_sha1, struct diff_options *opt)
766
805
if (!tree )
767
806
die ("bad tree object %s" , sha1_to_hex (tree_sha1 ));
768
807
808
+ unpack_cb .revs = & revs ;
809
+ unpack_cb .symcache [0 ] = '\0' ;
769
810
memset (& opts , 0 , sizeof (opts ));
770
811
opts .head_idx = 1 ;
771
812
opts .index_only = 1 ;
772
813
opts .merge = 1 ;
773
814
opts .fn = oneway_diff ;
774
- opts .unpack_data = & revs ;
815
+ opts .unpack_data = & unpack_cb ;
775
816
opts .src_index = & the_index ;
776
817
opts .dst_index = & the_index ;
777
818
0 commit comments