Libify diff-files.
[git/git.git] / diff-lib.c
CommitLineData
be3cfa85
JH
1/*
2 * Copyright (C) 2005 Junio C Hamano
3 */
86436c28 4#include "cache.h"
6fb737be 5#include "quote.h"
6973dcae 6#include "commit.h"
86436c28 7#include "diff.h"
427dcb4b 8#include "diffcore.h"
6973dcae 9#include "revision.h"
427dcb4b 10
b46f0b6d 11/*
6973dcae 12 * diff-files
b46f0b6d 13 */
f0c6b2a2 14
6973dcae 15int run_diff_files(struct rev_info *revs, int silent_on_removed)
f0c6b2a2 16{
6973dcae
JH
17 int entries, i;
18 int diff_unmerged_stage = revs->max_count;
f0c6b2a2 19
6973dcae
JH
20 if (diff_unmerged_stage < 0)
21 diff_unmerged_stage = 2;
22 entries = read_cache();
23 if (entries < 0) {
24 perror("read_cache");
427dcb4b 25 return -1;
427dcb4b 26 }
6973dcae 27 for (i = 0; i < entries; i++) {
be3cfa85 28 struct stat st;
6973dcae
JH
29 unsigned int oldmode, newmode;
30 struct cache_entry *ce = active_cache[i];
31 int changed;
8676eb43 32
6973dcae 33 if (!ce_path_match(ce, revs->prune_data))
8676eb43 34 continue;
be3cfa85 35
6973dcae
JH
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
f0c6b2a2 82 */
6973dcae 83 i--;
6b5ee137 84
6973dcae
JH
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;
1b1480ff 91 }
6973dcae 92 free(combine.p.path);
0e3994fa 93
6973dcae
JH
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;
eeaa4603 101 }
6b14d7fa 102
6973dcae
JH
103 if (lstat(ce->name, &st) < 0) {
104 if (errno != ENOENT && errno != ENOTDIR) {
105 perror(ce->name);
15d061b4
JH
106 continue;
107 }
6973dcae
JH
108 if (silent_on_removed)
109 continue;
110 diff_addremove(&revs->diffopt, '-', ntohl(ce->ce_mode),
111 ce->sha1, ce->name, NULL);
112 continue;
f2ce9fde 113 }
6973dcae
JH
114 changed = ce_match_stat(ce, &st, 0);
115 if (!changed && !revs->diffopt.find_copies_harder)
116 continue;
117 oldmode = ntohl(ce->ce_mode);
be3cfa85 118
6973dcae
JH
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);
77eb2720 127
7ca45252 128 }
6973dcae
JH
129 diffcore_std(&revs->diffopt);
130 diff_flush(&revs->diffopt);
131 return 0;
77eb2720 132}
be3cfa85 133