git-p4: Unset P4DIFF environment variable when using 'p4 -du diff'
[gitweb.git] / diff-lib.c
index 045f3cc58ec1e57e09b33bb2ade1bae9419ad450..52dbac34a40b2ca7bcbb7c2343a0487e5cb90ccf 100644 (file)
@@ -472,22 +472,21 @@ int run_diff_files(struct rev_info *revs, unsigned int option)
 static void diff_index_show_file(struct rev_info *revs,
                                 const char *prefix,
                                 struct cache_entry *ce,
-                                unsigned char *sha1, unsigned int mode)
+                                const unsigned char *sha1, unsigned int mode)
 {
        diff_addremove(&revs->diffopt, prefix[0], mode,
                       sha1, ce->name, NULL);
 }
 
 static int get_stat_data(struct cache_entry *ce,
-                        unsigned char **sha1p,
+                        const unsigned char **sha1p,
                         unsigned int *modep,
                         int cached, int match_missing)
 {
-       unsigned char *sha1 = ce->sha1;
+       const unsigned char *sha1 = ce->sha1;
        unsigned int mode = ce->ce_mode;
 
        if (!cached) {
-               static unsigned char no_sha1[20];
                int changed;
                struct stat st;
                if (lstat(ce->name, &st) < 0) {
@@ -501,7 +500,7 @@ static int get_stat_data(struct cache_entry *ce,
                changed = ce_match_stat(ce, &st, 0);
                if (changed) {
                        mode = ce_mode_from_stat(ce, st.st_mode);
-                       sha1 = no_sha1;
+                       sha1 = null_sha1;
                }
        }
 
@@ -514,7 +513,7 @@ static void show_new_file(struct rev_info *revs,
                          struct cache_entry *new,
                          int cached, int match_missing)
 {
-       unsigned char *sha1;
+       const unsigned char *sha1;
        unsigned int mode;
 
        /* New file in the index: it might actually be different in
@@ -533,7 +532,7 @@ static int show_modified(struct rev_info *revs,
                         int cached, int match_missing)
 {
        unsigned int mode, oldmode;
-       unsigned char *sha1;
+       const unsigned char *sha1;
 
        if (get_stat_data(new, &sha1, &mode, cached, match_missing) < 0) {
                if (report_missing)
@@ -577,81 +576,6 @@ static int show_modified(struct rev_info *revs,
        return 0;
 }
 
-static int diff_cache(struct rev_info *revs,
-                     struct cache_entry **ac, int entries,
-                     const char **pathspec,
-                     int cached, int match_missing)
-{
-       while (entries) {
-               struct cache_entry *ce = *ac;
-               int same = (entries > 1) && ce_same_name(ce, ac[1]);
-
-               if (DIFF_OPT_TST(&revs->diffopt, QUIET) &&
-                       DIFF_OPT_TST(&revs->diffopt, HAS_CHANGES))
-                       break;
-
-               if (!ce_path_match(ce, pathspec))
-                       goto skip_entry;
-
-               switch (ce_stage(ce)) {
-               case 0:
-                       /* No stage 1 entry? That means it's a new file */
-                       if (!same) {
-                               show_new_file(revs, ce, cached, match_missing);
-                               break;
-                       }
-                       /* Show difference between old and new */
-                       show_modified(revs, ac[1], ce, 1,
-                                     cached, match_missing);
-                       break;
-               case 1:
-                       /* No stage 3 (merge) entry?
-                        * That means it's been deleted.
-                        */
-                       if (!same) {
-                               diff_index_show_file(revs, "-", ce,
-                                                    ce->sha1, ce->ce_mode);
-                               break;
-                       }
-                       /* We come here with ce pointing at stage 1
-                        * (original tree) and ac[1] pointing at stage
-                        * 3 (unmerged).  show-modified with
-                        * report-missing set to false does not say the
-                        * file is deleted but reports true if work
-                        * tree does not have it, in which case we
-                        * fall through to report the unmerged state.
-                        * Otherwise, we show the differences between
-                        * the original tree and the work tree.
-                        */
-                       if (!cached &&
-                           !show_modified(revs, ce, ac[1], 0,
-                                          cached, match_missing))
-                               break;
-                       diff_unmerge(&revs->diffopt, ce->name,
-                                    ce->ce_mode, ce->sha1);
-                       break;
-               case 3:
-                       diff_unmerge(&revs->diffopt, ce->name,
-                                    0, null_sha1);
-                       break;
-
-               default:
-                       die("impossible cache entry stage");
-               }
-
-skip_entry:
-               /*
-                * Ignore all the different stages for this file,
-                * we've handled the relevant cases now.
-                */
-               do {
-                       ac++;
-                       entries--;
-               } while (entries && ce_same_name(ce, ac[0]));
-       }
-       return 0;
-}
-
 /*
  * This turns all merge entries into "stage 3". That guarantees that
  * when we read in the new tree (into "stage 1"), we won't lose sight
@@ -676,8 +600,7 @@ static void mark_merge_entries(void)
  */
 static void do_oneway_diff(struct unpack_trees_options *o,
        struct cache_entry *idx,
-       struct cache_entry *tree,
-       int idx_pos, int idx_nr)
+       struct cache_entry *tree)
 {
        struct rev_info *revs = o->unpack_data;
        int match_missing, cached;
@@ -718,32 +641,19 @@ static void do_oneway_diff(struct unpack_trees_options *o,
        show_modified(revs, tree, idx, 1, cached, match_missing);
 }
 
-/*
- * Count how many index entries go with the first one
- */
-static inline int count_skip(const struct cache_entry *src, int pos)
+static inline void skip_same_name(struct cache_entry *ce, struct unpack_trees_options *o)
 {
-       int skip = 1;
-
-       /* We can only have multiple entries if the first one is not stage-0 */
-       if (ce_stage(src)) {
-               struct cache_entry **p = active_cache + pos;
-               int namelen = ce_namelen(src);
-
-               for (;;) {
-                       const struct cache_entry *ce;
-                       pos++;
-                       if (pos >= active_nr)
-                               break;
-                       ce = *++p;
-                       if (ce_namelen(ce) != namelen)
-                               break;
-                       if (memcmp(ce->name, src->name, namelen))
-                               break;
-                       skip++;
-               }
+       int len = ce_namelen(ce);
+       const struct index_state *index = o->src_index;
+
+       while (o->pos < index->cache_nr) {
+               struct cache_entry *next = index->cache[o->pos];
+               if (len != ce_namelen(next))
+                       break;
+               if (memcmp(ce->name, next->name, len))
+                       break;
+               o->pos++;
        }
-       return skip;
 }
 
 /*
@@ -761,17 +671,14 @@ static inline int count_skip(const struct cache_entry *src, int pos)
  * the fairly complex unpack_trees() semantic requirements, including
  * the skipping, the path matching, the type conflict cases etc.
  */
-static int oneway_diff(struct cache_entry **src,
-       struct unpack_trees_options *o,
-       int index_pos)
+static int oneway_diff(struct cache_entry **src, struct unpack_trees_options *o)
 {
-       int skip = 0;
        struct cache_entry *idx = src[0];
        struct cache_entry *tree = src[1];
        struct rev_info *revs = o->unpack_data;
 
-       if (index_pos >= 0)
-               skip = count_skip(idx, index_pos);
+       if (idx && ce_stage(idx))
+               skip_same_name(idx, o);
 
        /*
         * Unpack-trees generates a DF/conflict entry if
@@ -783,9 +690,9 @@ static int oneway_diff(struct cache_entry **src,
                tree = NULL;
 
        if (ce_path_match(idx ? idx : tree, revs->prune_data))
-               do_oneway_diff(o, idx, tree, index_pos, skip);
+               do_oneway_diff(o, idx, tree);
 
-       return skip;
+       return 0;
 }
 
 int run_diff_index(struct rev_info *revs, int cached)
@@ -810,9 +717,12 @@ int run_diff_index(struct rev_info *revs, int cached)
        opts.merge = 1;
        opts.fn = oneway_diff;
        opts.unpack_data = revs;
+       opts.src_index = &the_index;
+       opts.dst_index = NULL;
 
        init_tree_desc(&t, tree->buffer, tree->size);
-       unpack_trees(1, &t, &opts);
+       if (unpack_trees(1, &t, &opts))
+               exit(128);
 
        diffcore_std(&revs->diffopt);
        diff_flush(&revs->diffopt);
@@ -826,6 +736,8 @@ int do_diff_cache(const unsigned char *tree_sha1, struct diff_options *opt)
        int i;
        struct cache_entry **dst;
        struct cache_entry *last = NULL;
+       struct unpack_trees_options opts;
+       struct tree_desc t;
 
        /*
         * This is used by git-blame to run diff-cache internally;
@@ -853,8 +765,18 @@ int do_diff_cache(const unsigned char *tree_sha1, struct diff_options *opt)
        tree = parse_tree_indirect(tree_sha1);
        if (!tree)
                die("bad tree object %s", sha1_to_hex(tree_sha1));
-       if (read_tree(tree, 1, opt->paths))
-               return error("unable to read tree %s", sha1_to_hex(tree_sha1));
-       return diff_cache(&revs, active_cache, active_nr, revs.prune_data,
-                         1, 0);
+
+       memset(&opts, 0, sizeof(opts));
+       opts.head_idx = 1;
+       opts.index_only = 1;
+       opts.merge = 1;
+       opts.fn = oneway_diff;
+       opts.unpack_data = &revs;
+       opts.src_index = &the_index;
+       opts.dst_index = &the_index;
+
+       init_tree_desc(&t, tree->buffer, tree->size);
+       if (unpack_trees(1, &t, &opts))
+               exit(128);
+       return 0;
 }