]>
Commit | Line | Data |
---|---|---|
8bc9a0c7 LT |
1 | /* |
2 | * GIT - The information manager from hell | |
3 | * | |
4 | * Copyright (C) Linus Torvalds, 2005 | |
5 | */ | |
e83c5163 LT |
6 | #include "cache.h" |
7 | ||
d99082e0 LT |
8 | static int stage = 0; |
9 | ||
94537c78 | 10 | static int unpack_tree(unsigned char *sha1) |
b12ec373 JH |
11 | { |
12 | void *buffer; | |
13 | unsigned long size; | |
14 | ||
15 | buffer = read_tree_with_tree_or_commit_sha1(sha1, &size, 0); | |
aba06682 LT |
16 | if (!buffer) |
17 | return -1; | |
94537c78 | 18 | return read_tree(buffer, size, stage); |
b12ec373 JH |
19 | } |
20 | ||
bb233d69 | 21 | static char *lockfile_name; |
9614b8dc LT |
22 | |
23 | static void remove_lock_file(void) | |
24 | { | |
bb233d69 LT |
25 | if (lockfile_name) |
26 | unlink(lockfile_name); | |
9614b8dc LT |
27 | } |
28 | ||
ca016f0e LT |
29 | static int path_matches(struct cache_entry *a, struct cache_entry *b) |
30 | { | |
31 | int len = ce_namelen(a); | |
32 | return ce_namelen(b) == len && | |
33 | !memcmp(a->name, b->name, len); | |
34 | } | |
35 | ||
43f91266 LT |
36 | static int same(struct cache_entry *a, struct cache_entry *b) |
37 | { | |
38 | return a->ce_mode == b->ce_mode && | |
39 | !memcmp(a->sha1, b->sha1, 20); | |
40 | } | |
41 | ||
42 | ||
d99082e0 | 43 | /* |
43f91266 LT |
44 | * This removes all trivial merges that don't change the tree |
45 | * and collapses them to state 0. | |
d99082e0 | 46 | * |
43f91266 LT |
47 | * _Any_ other merge is left to user policy. That includes "both |
48 | * created the same file", and "both removed the same file" - which are | |
49 | * trivial, but the user might still want to _note_ it. | |
d99082e0 | 50 | */ |
43f91266 LT |
51 | static struct cache_entry *merge_entries(struct cache_entry *a, |
52 | struct cache_entry *b, | |
53 | struct cache_entry *c) | |
d99082e0 LT |
54 | { |
55 | int len = ce_namelen(a); | |
43f91266 LT |
56 | |
57 | /* | |
58 | * Are they all the same filename? We won't do | |
59 | * any name merging | |
60 | */ | |
61 | if (ce_namelen(b) != len || | |
62 | ce_namelen(c) != len || | |
63 | memcmp(a->name, b->name, len) || | |
64 | memcmp(a->name, c->name, len)) | |
65 | return NULL; | |
66 | ||
67 | /* | |
68 | * Ok, all three entries describe the same | |
69 | * filename, but maybe the contents or file | |
70 | * mode have changed? | |
71 | * | |
72 | * The trivial cases end up being the ones where two | |
73 | * out of three files are the same: | |
74 | * - both destinations the same, trivially take either | |
75 | * - one of the destination versions hasn't changed, | |
76 | * take the other. | |
77 | * | |
78 | * The "all entries exactly the same" case falls out as | |
79 | * a special case of any of the "two same" cases. | |
80 | * | |
81 | * Here "a" is "original", and "b" and "c" are the two | |
82 | * trees we are merging. | |
83 | */ | |
84 | if (same(b,c)) | |
85 | return c; | |
86 | if (same(a,b)) | |
87 | return c; | |
88 | if (same(a,c)) | |
89 | return b; | |
90 | return NULL; | |
d99082e0 LT |
91 | } |
92 | ||
93 | static void trivially_merge_cache(struct cache_entry **src, int nr) | |
94 | { | |
ca016f0e | 95 | static struct cache_entry null_entry; |
d99082e0 | 96 | struct cache_entry **dst = src; |
ca016f0e | 97 | struct cache_entry *old = &null_entry; |
d99082e0 LT |
98 | |
99 | while (nr) { | |
43f91266 | 100 | struct cache_entry *ce, *result; |
d99082e0 LT |
101 | |
102 | ce = src[0]; | |
ca016f0e LT |
103 | |
104 | /* We throw away original cache entries except for the stat information */ | |
105 | if (!ce_stage(ce)) { | |
106 | old = ce; | |
107 | src++; | |
108 | nr--; | |
109 | active_nr--; | |
110 | continue; | |
111 | } | |
43f91266 | 112 | if (nr > 2 && (result = merge_entries(ce, src[1], src[2])) != NULL) { |
ca016f0e LT |
113 | /* |
114 | * See if we can re-use the old CE directly? | |
115 | * That way we get the uptodate stat info. | |
116 | */ | |
117 | if (path_matches(result, old) && same(result, old)) | |
118 | *result = *old; | |
43f91266 | 119 | ce = result; |
d99082e0 LT |
120 | ce->ce_flags &= ~htons(CE_STAGEMASK); |
121 | src += 2; | |
122 | nr -= 2; | |
123 | active_nr -= 2; | |
124 | } | |
a3a65234 LT |
125 | *dst++ = ce; |
126 | src++; | |
127 | nr--; | |
128 | } | |
129 | } | |
130 | ||
131 | static void merge_stat_info(struct cache_entry **src, int nr) | |
132 | { | |
133 | static struct cache_entry null_entry; | |
134 | struct cache_entry **dst = src; | |
135 | struct cache_entry *old = &null_entry; | |
136 | ||
137 | while (nr) { | |
138 | struct cache_entry *ce; | |
139 | ||
140 | ce = src[0]; | |
141 | ||
142 | /* We throw away original cache entries except for the stat information */ | |
143 | if (!ce_stage(ce)) { | |
144 | old = ce; | |
145 | src++; | |
146 | nr--; | |
147 | active_nr--; | |
148 | continue; | |
149 | } | |
150 | if (path_matches(ce, old) && same(ce, old)) | |
151 | *ce = *old; | |
152 | ce->ce_flags &= ~htons(CE_STAGEMASK); | |
153 | *dst++ = ce; | |
d99082e0 | 154 | src++; |
d99082e0 LT |
155 | nr--; |
156 | } | |
157 | } | |
158 | ||
c5bac17a JH |
159 | static char *read_tree_usage = "read-tree (<sha> | -m <sha1> [<sha2> <sha3>])"; |
160 | ||
e83c5163 LT |
161 | int main(int argc, char **argv) |
162 | { | |
ca016f0e | 163 | int i, newfd, merge; |
e83c5163 | 164 | unsigned char sha1[20]; |
bb233d69 LT |
165 | static char lockfile[MAXPATHLEN+1]; |
166 | const char *indexfile = get_index_file(); | |
e83c5163 | 167 | |
bb233d69 LT |
168 | snprintf(lockfile, sizeof(lockfile), "%s.lock", indexfile); |
169 | ||
170 | newfd = open(lockfile, O_RDWR | O_CREAT | O_EXCL, 0600); | |
83adac3c | 171 | if (newfd < 0) |
2de381f9 | 172 | die("unable to create new cachefile"); |
9614b8dc | 173 | atexit(remove_lock_file); |
bb233d69 | 174 | lockfile_name = lockfile; |
83adac3c | 175 | |
ca016f0e | 176 | merge = 0; |
83adac3c LT |
177 | for (i = 1; i < argc; i++) { |
178 | const char *arg = argv[i]; | |
179 | ||
d99082e0 | 180 | /* "-m" stands for "merge", meaning we start in stage 1 */ |
83adac3c | 181 | if (!strcmp(arg, "-m")) { |
ca016f0e LT |
182 | int i; |
183 | if (stage) | |
c5bac17a | 184 | die("-m needs to come first"); |
ca016f0e LT |
185 | read_cache(); |
186 | for (i = 0; i < active_nr; i++) { | |
187 | if (ce_stage(active_cache[i])) | |
c5bac17a | 188 | die("you need to resolve your current index first"); |
ca016f0e | 189 | } |
d99082e0 | 190 | stage = 1; |
ca016f0e | 191 | merge = 1; |
83adac3c LT |
192 | continue; |
193 | } | |
9614b8dc | 194 | if (get_sha1_hex(arg, sha1) < 0) |
c5bac17a | 195 | usage(read_tree_usage); |
d99082e0 | 196 | if (stage > 3) |
c5bac17a | 197 | usage(read_tree_usage); |
94537c78 | 198 | if (unpack_tree(sha1) < 0) |
2de381f9 | 199 | die("failed to unpack tree object %s", arg); |
d99082e0 | 200 | stage++; |
83adac3c | 201 | } |
ca016f0e | 202 | if (merge) { |
a3a65234 LT |
203 | switch (stage) { |
204 | case 4: /* Three-way merge */ | |
205 | trivially_merge_cache(active_cache, active_nr); | |
206 | break; | |
207 | case 2: /* Just read a tree, merge with old cache contents */ | |
208 | merge_stat_info(active_cache, active_nr); | |
209 | break; | |
210 | default: | |
211 | die("just how do you expect me to merge %d trees?", stage-1); | |
212 | } | |
ca016f0e | 213 | } |
bb233d69 | 214 | if (write_cache(newfd, active_cache, active_nr) || rename(lockfile, indexfile)) |
2de381f9 | 215 | die("unable to write new index file"); |
bb233d69 | 216 | lockfile_name = NULL; |
9614b8dc | 217 | return 0; |
e83c5163 | 218 | } |