]>
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 | ||
f768846e | 10 | static int read_one_entry(unsigned char *sha1, const char *base, int baselen, const char *pathname, unsigned mode) |
e497ea2a | 11 | { |
83adac3c | 12 | int len = strlen(pathname); |
f768846e | 13 | unsigned int size = cache_entry_size(baselen + len); |
83adac3c | 14 | struct cache_entry *ce = malloc(size); |
e497ea2a | 15 | |
83adac3c | 16 | memset(ce, 0, size); |
e497ea2a | 17 | |
e4479470 | 18 | ce->ce_mode = create_ce_mode(mode); |
d99082e0 | 19 | ce->ce_flags = create_ce_flags(baselen + len, stage); |
f768846e LT |
20 | memcpy(ce->name, base, baselen); |
21 | memcpy(ce->name + baselen, pathname, len+1); | |
83adac3c | 22 | memcpy(ce->sha1, sha1, 20); |
121481ab | 23 | return add_cache_entry(ce, 1); |
e497ea2a LT |
24 | } |
25 | ||
b12ec373 JH |
26 | static int read_tree_recursive(void *buffer, const char *type, |
27 | unsigned long size, | |
28 | const char *base, int baselen) | |
e83c5163 | 29 | { |
b12ec373 | 30 | if (!buffer || strcmp(type, "tree")) |
83adac3c | 31 | return -1; |
e83c5163 LT |
32 | while (size) { |
33 | int len = strlen(buffer)+1; | |
34 | unsigned char *sha1 = buffer + len; | |
35 | char *path = strchr(buffer, ' ')+1; | |
36 | unsigned int mode; | |
e497ea2a | 37 | |
e83c5163 | 38 | if (size < len + 20 || sscanf(buffer, "%o", &mode) != 1) |
83adac3c LT |
39 | return -1; |
40 | ||
e83c5163 LT |
41 | buffer = sha1 + 20; |
42 | size -= len + 20; | |
83adac3c | 43 | |
f768846e LT |
44 | if (S_ISDIR(mode)) { |
45 | int retval; | |
46 | int pathlen = strlen(path); | |
47 | char *newbase = malloc(baselen + 1 + pathlen); | |
b12ec373 JH |
48 | void *eltbuf; |
49 | char elttype[20]; | |
50 | unsigned long eltsize; | |
51 | ||
52 | eltbuf = read_sha1_file(sha1, elttype, &eltsize); | |
53 | if (!eltbuf) | |
54 | return -1; | |
f768846e LT |
55 | memcpy(newbase, base, baselen); |
56 | memcpy(newbase + baselen, path, pathlen); | |
57 | newbase[baselen + pathlen] = '/'; | |
b12ec373 JH |
58 | retval = read_tree_recursive(eltbuf, elttype, eltsize, |
59 | newbase, | |
60 | baselen + pathlen + 1); | |
61 | free(eltbuf); | |
f768846e LT |
62 | free(newbase); |
63 | if (retval) | |
64 | return -1; | |
65 | continue; | |
66 | } | |
67 | if (read_one_entry(sha1, base, baselen, path, mode) < 0) | |
83adac3c | 68 | return -1; |
e83c5163 LT |
69 | } |
70 | return 0; | |
71 | } | |
72 | ||
b12ec373 JH |
73 | static int read_tree(unsigned char *sha1, const char *base, int baselen) |
74 | { | |
75 | void *buffer; | |
76 | unsigned long size; | |
77 | ||
78 | buffer = read_tree_with_tree_or_commit_sha1(sha1, &size, 0); | |
79 | return read_tree_recursive(buffer, "tree", size, base, baselen); | |
80 | } | |
81 | ||
bb233d69 | 82 | static char *lockfile_name; |
9614b8dc LT |
83 | |
84 | static void remove_lock_file(void) | |
85 | { | |
bb233d69 LT |
86 | if (lockfile_name) |
87 | unlink(lockfile_name); | |
9614b8dc LT |
88 | } |
89 | ||
ca016f0e LT |
90 | static int path_matches(struct cache_entry *a, struct cache_entry *b) |
91 | { | |
92 | int len = ce_namelen(a); | |
93 | return ce_namelen(b) == len && | |
94 | !memcmp(a->name, b->name, len); | |
95 | } | |
96 | ||
43f91266 LT |
97 | static int same(struct cache_entry *a, struct cache_entry *b) |
98 | { | |
99 | return a->ce_mode == b->ce_mode && | |
100 | !memcmp(a->sha1, b->sha1, 20); | |
101 | } | |
102 | ||
103 | ||
d99082e0 | 104 | /* |
43f91266 LT |
105 | * This removes all trivial merges that don't change the tree |
106 | * and collapses them to state 0. | |
d99082e0 | 107 | * |
43f91266 LT |
108 | * _Any_ other merge is left to user policy. That includes "both |
109 | * created the same file", and "both removed the same file" - which are | |
110 | * trivial, but the user might still want to _note_ it. | |
d99082e0 | 111 | */ |
43f91266 LT |
112 | static struct cache_entry *merge_entries(struct cache_entry *a, |
113 | struct cache_entry *b, | |
114 | struct cache_entry *c) | |
d99082e0 LT |
115 | { |
116 | int len = ce_namelen(a); | |
43f91266 LT |
117 | |
118 | /* | |
119 | * Are they all the same filename? We won't do | |
120 | * any name merging | |
121 | */ | |
122 | if (ce_namelen(b) != len || | |
123 | ce_namelen(c) != len || | |
124 | memcmp(a->name, b->name, len) || | |
125 | memcmp(a->name, c->name, len)) | |
126 | return NULL; | |
127 | ||
128 | /* | |
129 | * Ok, all three entries describe the same | |
130 | * filename, but maybe the contents or file | |
131 | * mode have changed? | |
132 | * | |
133 | * The trivial cases end up being the ones where two | |
134 | * out of three files are the same: | |
135 | * - both destinations the same, trivially take either | |
136 | * - one of the destination versions hasn't changed, | |
137 | * take the other. | |
138 | * | |
139 | * The "all entries exactly the same" case falls out as | |
140 | * a special case of any of the "two same" cases. | |
141 | * | |
142 | * Here "a" is "original", and "b" and "c" are the two | |
143 | * trees we are merging. | |
144 | */ | |
145 | if (same(b,c)) | |
146 | return c; | |
147 | if (same(a,b)) | |
148 | return c; | |
149 | if (same(a,c)) | |
150 | return b; | |
151 | return NULL; | |
d99082e0 LT |
152 | } |
153 | ||
154 | static void trivially_merge_cache(struct cache_entry **src, int nr) | |
155 | { | |
ca016f0e | 156 | static struct cache_entry null_entry; |
d99082e0 | 157 | struct cache_entry **dst = src; |
ca016f0e | 158 | struct cache_entry *old = &null_entry; |
d99082e0 LT |
159 | |
160 | while (nr) { | |
43f91266 | 161 | struct cache_entry *ce, *result; |
d99082e0 LT |
162 | |
163 | ce = src[0]; | |
ca016f0e LT |
164 | |
165 | /* We throw away original cache entries except for the stat information */ | |
166 | if (!ce_stage(ce)) { | |
167 | old = ce; | |
168 | src++; | |
169 | nr--; | |
170 | active_nr--; | |
171 | continue; | |
172 | } | |
43f91266 | 173 | if (nr > 2 && (result = merge_entries(ce, src[1], src[2])) != NULL) { |
ca016f0e LT |
174 | /* |
175 | * See if we can re-use the old CE directly? | |
176 | * That way we get the uptodate stat info. | |
177 | */ | |
178 | if (path_matches(result, old) && same(result, old)) | |
179 | *result = *old; | |
43f91266 | 180 | ce = result; |
d99082e0 LT |
181 | ce->ce_flags &= ~htons(CE_STAGEMASK); |
182 | src += 2; | |
183 | nr -= 2; | |
184 | active_nr -= 2; | |
185 | } | |
a3a65234 LT |
186 | *dst++ = ce; |
187 | src++; | |
188 | nr--; | |
189 | } | |
190 | } | |
191 | ||
192 | static void merge_stat_info(struct cache_entry **src, int nr) | |
193 | { | |
194 | static struct cache_entry null_entry; | |
195 | struct cache_entry **dst = src; | |
196 | struct cache_entry *old = &null_entry; | |
197 | ||
198 | while (nr) { | |
199 | struct cache_entry *ce; | |
200 | ||
201 | ce = src[0]; | |
202 | ||
203 | /* We throw away original cache entries except for the stat information */ | |
204 | if (!ce_stage(ce)) { | |
205 | old = ce; | |
206 | src++; | |
207 | nr--; | |
208 | active_nr--; | |
209 | continue; | |
210 | } | |
211 | if (path_matches(ce, old) && same(ce, old)) | |
212 | *ce = *old; | |
213 | ce->ce_flags &= ~htons(CE_STAGEMASK); | |
214 | *dst++ = ce; | |
d99082e0 | 215 | src++; |
d99082e0 LT |
216 | nr--; |
217 | } | |
218 | } | |
219 | ||
c5bac17a JH |
220 | static char *read_tree_usage = "read-tree (<sha> | -m <sha1> [<sha2> <sha3>])"; |
221 | ||
e83c5163 LT |
222 | int main(int argc, char **argv) |
223 | { | |
ca016f0e | 224 | int i, newfd, merge; |
e83c5163 | 225 | unsigned char sha1[20]; |
bb233d69 LT |
226 | static char lockfile[MAXPATHLEN+1]; |
227 | const char *indexfile = get_index_file(); | |
e83c5163 | 228 | |
bb233d69 LT |
229 | snprintf(lockfile, sizeof(lockfile), "%s.lock", indexfile); |
230 | ||
231 | newfd = open(lockfile, O_RDWR | O_CREAT | O_EXCL, 0600); | |
83adac3c | 232 | if (newfd < 0) |
2de381f9 | 233 | die("unable to create new cachefile"); |
9614b8dc | 234 | atexit(remove_lock_file); |
bb233d69 | 235 | lockfile_name = lockfile; |
83adac3c | 236 | |
ca016f0e | 237 | merge = 0; |
83adac3c LT |
238 | for (i = 1; i < argc; i++) { |
239 | const char *arg = argv[i]; | |
240 | ||
d99082e0 | 241 | /* "-m" stands for "merge", meaning we start in stage 1 */ |
83adac3c | 242 | if (!strcmp(arg, "-m")) { |
ca016f0e LT |
243 | int i; |
244 | if (stage) | |
c5bac17a | 245 | die("-m needs to come first"); |
ca016f0e LT |
246 | read_cache(); |
247 | for (i = 0; i < active_nr; i++) { | |
248 | if (ce_stage(active_cache[i])) | |
c5bac17a | 249 | die("you need to resolve your current index first"); |
ca016f0e | 250 | } |
d99082e0 | 251 | stage = 1; |
ca016f0e | 252 | merge = 1; |
83adac3c LT |
253 | continue; |
254 | } | |
9614b8dc | 255 | if (get_sha1_hex(arg, sha1) < 0) |
c5bac17a | 256 | usage(read_tree_usage); |
d99082e0 | 257 | if (stage > 3) |
c5bac17a | 258 | usage(read_tree_usage); |
9614b8dc | 259 | if (read_tree(sha1, "", 0) < 0) |
2de381f9 | 260 | die("failed to unpack tree object %s", arg); |
d99082e0 | 261 | stage++; |
83adac3c | 262 | } |
ca016f0e | 263 | if (merge) { |
a3a65234 LT |
264 | switch (stage) { |
265 | case 4: /* Three-way merge */ | |
266 | trivially_merge_cache(active_cache, active_nr); | |
267 | break; | |
268 | case 2: /* Just read a tree, merge with old cache contents */ | |
269 | merge_stat_info(active_cache, active_nr); | |
270 | break; | |
271 | default: | |
272 | die("just how do you expect me to merge %d trees?", stage-1); | |
273 | } | |
ca016f0e | 274 | } |
bb233d69 | 275 | if (write_cache(newfd, active_cache, active_nr) || rename(lockfile, indexfile)) |
2de381f9 | 276 | die("unable to write new index file"); |
bb233d69 | 277 | lockfile_name = NULL; |
9614b8dc | 278 | return 0; |
e83c5163 | 279 | } |