a28dd3dca79ab93f45cb0be0ea6e662ab28447f1
   1/*
   2 * Copyright (C) 2005 Junio C Hamano
   3 */
   4#include "cache.h"
   5#include "quote.h"
   6#include "commit.h"
   7#include "diff.h"
   8#include "diffcore.h"
   9#include "revision.h"
  10
  11/*
  12 * diff-files
  13 */
  14
  15int run_diff_files(struct rev_info *revs, int silent_on_removed)
  16{
  17        int entries, i;
  18        int diff_unmerged_stage = revs->max_count;
  19
  20        if (diff_unmerged_stage < 0)
  21                diff_unmerged_stage = 2;
  22        entries = read_cache();
  23        if (entries < 0) {
  24                perror("read_cache");
  25                return -1;
  26        }
  27        for (i = 0; i < entries; i++) {
  28                struct stat st;
  29                unsigned int oldmode, newmode;
  30                struct cache_entry *ce = active_cache[i];
  31                int changed;
  32
  33                if (!ce_path_match(ce, revs->prune_data))
  34                        continue;
  35
  36                if (ce_stage(ce)) {
  37                        struct {
  38                                struct combine_diff_path p;
  39                                struct combine_diff_parent filler[5];
  40                        } combine;
  41                        int num_compare_stages = 0;
  42
  43                        combine.p.next = NULL;
  44                        combine.p.len = ce_namelen(ce);
  45                        combine.p.path = xmalloc(combine.p.len + 1);
  46                        memcpy(combine.p.path, ce->name, combine.p.len);
  47                        combine.p.path[combine.p.len] = 0;
  48                        combine.p.mode = 0;
  49                        memset(combine.p.sha1, 0, 20);
  50                        memset(&combine.p.parent[0], 0,
  51                               sizeof(combine.filler));
  52
  53                        while (i < entries) {
  54                                struct cache_entry *nce = active_cache[i];
  55                                int stage;
  56
  57                                if (strcmp(ce->name, nce->name))
  58                                        break;
  59
  60                                /* Stage #2 (ours) is the first parent,
  61                                 * stage #3 (theirs) is the second.
  62                                 */
  63                                stage = ce_stage(nce);
  64                                if (2 <= stage) {
  65                                        int mode = ntohl(nce->ce_mode);
  66                                        num_compare_stages++;
  67                                        memcpy(combine.p.parent[stage-2].sha1,
  68                                               nce->sha1, 20);
  69                                        combine.p.parent[stage-2].mode =
  70                                                canon_mode(mode);
  71                                        combine.p.parent[stage-2].status =
  72                                                DIFF_STATUS_MODIFIED;
  73                                }
  74
  75                                /* diff against the proper unmerged stage */
  76                                if (stage == diff_unmerged_stage)
  77                                        ce = nce;
  78                                i++;
  79                        }
  80                        /*
  81                         * Compensate for loop update
  82                         */
  83                        i--;
  84
  85                        if (revs->combine_merges && num_compare_stages == 2) {
  86                                show_combined_diff(&combine.p, 2,
  87                                                   revs->dense_combined_merges,
  88                                                   revs);
  89                                free(combine.p.path);
  90                                continue;
  91                        }
  92                        free(combine.p.path);
  93
  94                        /*
  95                         * Show the diff for the 'ce' if we found the one
  96                         * from the desired stage.
  97                         */
  98                        diff_unmerge(&revs->diffopt, ce->name);
  99                        if (ce_stage(ce) != diff_unmerged_stage)
 100                                continue;
 101                }
 102
 103                if (lstat(ce->name, &st) < 0) {
 104                        if (errno != ENOENT && errno != ENOTDIR) {
 105                                perror(ce->name);
 106                                continue;
 107                        }
 108                        if (silent_on_removed)
 109                                continue;
 110                        diff_addremove(&revs->diffopt, '-', ntohl(ce->ce_mode),
 111                                       ce->sha1, ce->name, NULL);
 112                        continue;
 113                }
 114                changed = ce_match_stat(ce, &st, 0);
 115                if (!changed && !revs->diffopt.find_copies_harder)
 116                        continue;
 117                oldmode = ntohl(ce->ce_mode);
 118
 119                newmode = canon_mode(st.st_mode);
 120                if (!trust_executable_bit &&
 121                    S_ISREG(newmode) && S_ISREG(oldmode) &&
 122                    ((newmode ^ oldmode) == 0111))
 123                        newmode = oldmode;
 124                diff_change(&revs->diffopt, oldmode, newmode,
 125                            ce->sha1, (changed ? null_sha1 : ce->sha1),
 126                            ce->name, NULL);
 127
 128        }
 129        diffcore_std(&revs->diffopt);
 130        diff_flush(&revs->diffopt);
 131        return 0;
 132}
 133