10
#include "cache-tree.h"
11
#include "path-list.h"
12
#include "unpack-trees.h"
13
+#include "refs.h"
14
15
/*
16
* diff-files
334
}
335
return run_diff_files(revs, options);
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
+}
357
358
int run_diff_files(struct rev_info *revs, unsigned int option)
359
{
489
* diff-index
490
*/
491
492
+struct oneway_unpack_data {
493
+ struct rev_info *revs;
494
+ char symcache[PATH_MAX];
495
+};
496
+
497
/* A file entry went away or appeared */
498
static void diff_index_show_file(struct rev_info *revs,
499
const char *prefix,
507
static int get_stat_data(struct cache_entry *ce,
508
const unsigned char **sha1p,
509
unsigned int *modep,
484
- int cached, int match_missing)
510
+ int cached, int match_missing,
511
+ struct oneway_unpack_data *cbdata)
512
{
513
const unsigned char *sha1 = ce->sha1;
514
unsigned int mode = ce->ce_mode;
516
if (!cached) {
517
int changed;
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) {
524
*sha1p = sha1;
525
*modep = mode;
526
return 0;
539
return 0;
540
}
541
512
-static void show_new_file(struct rev_info *revs,
542
+static void show_new_file(struct oneway_unpack_data *cbdata,
543
struct cache_entry *new,
544
int cached, int match_missing)
545
{
546
const unsigned char *sha1;
547
unsigned int mode;
548
+ struct rev_info *revs = cbdata->revs;
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
552
* the working copy.
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)
555
return;
556
557
diff_index_show_file(revs, "+", new, sha1, mode);
558
}
559
528
-static int show_modified(struct rev_info *revs,
560
+static int show_modified(struct oneway_unpack_data *cbdata,
561
struct cache_entry *old,
562
struct cache_entry *new,
563
int report_missing,
565
{
566
unsigned int mode, oldmode;
567
const unsigned char *sha1;
568
+ struct rev_info *revs = cbdata->revs;
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) {
571
if (report_missing)
572
diff_index_show_file(revs, "-", old,
573
old->sha1, old->ce_mode);
635
struct cache_entry *idx,
636
struct cache_entry *tree)
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;
640
int match_missing, cached;
641
642
/*
659
* Something added to the tree?
660
*/
661
if (!tree) {
628
- show_new_file(revs, idx, cached, match_missing);
662
+ show_new_file(cbdata, idx, cached, match_missing);
663
return;
664
}
665
672
}
673
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);
676
}
677
678
static inline void skip_same_name(struct cache_entry *ce, struct unpack_trees_options *o)
709
{
710
struct cache_entry *idx = src[0];
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;
714
715
if (idx && ce_stage(idx))
716
skip_same_name(idx, o);
737
const char *tree_name;
738
struct unpack_trees_options opts;
739
struct tree_desc t;
740
+ struct oneway_unpack_data unpack_cb;
741
742
mark_merge_entries();
743
747
if (!tree)
748
return error("bad tree object %s", tree_name);
749
750
+ unpack_cb.revs = revs;
751
+ unpack_cb.symcache[0] = '\0';
752
memset(&opts, 0, sizeof(opts));
753
opts.head_idx = 1;
754
opts.index_only = cached;
755
opts.merge = 1;
756
opts.fn = oneway_diff;
719
- opts.unpack_data = revs;
757
+ opts.unpack_data = &unpack_cb;
758
opts.src_index = &the_index;
759
opts.dst_index = NULL;
760
776
struct cache_entry *last = NULL;
777
struct unpack_trees_options opts;
778
struct tree_desc t;
779
+ struct oneway_unpack_data unpack_cb;
780
781
/*
782
* This is used by git-blame to run diff-cache internally;
805
if (!tree)
806
die("bad tree object %s", sha1_to_hex(tree_sha1));
807
808
+ unpack_cb.revs = &revs;
809
+ unpack_cb.symcache[0] = '\0';
810
memset(&opts, 0, sizeof(opts));
811
opts.head_idx = 1;
812
opts.index_only = 1;
813
opts.merge = 1;
814
opts.fn = oneway_diff;
774
- opts.unpack_data = &revs;
815
+ opts.unpack_data = &unpack_cb;
816
opts.src_index = &the_index;
817
opts.dst_index = &the_index;
818