Implement automatic fast-forward merge for submodules
[git/mingw.git] / submodule.c
blobdcb4b5da7166c865d06d55014d650a35b4abb998
1 #include "cache.h"
2 #include "submodule.h"
3 #include "dir.h"
4 #include "diff.h"
5 #include "commit.h"
6 #include "revision.h"
7 #include "run-command.h"
8 #include "diffcore.h"
9 #include "refs.h"
11 static int add_submodule_odb(const char *path)
13 struct strbuf objects_directory = STRBUF_INIT;
14 struct alternate_object_database *alt_odb;
15 int ret = 0;
16 const char *git_dir;
18 strbuf_addf(&objects_directory, "%s/.git", path);
19 git_dir = read_gitfile_gently(objects_directory.buf);
20 if (git_dir) {
21 strbuf_reset(&objects_directory);
22 strbuf_addstr(&objects_directory, git_dir);
24 strbuf_addstr(&objects_directory, "/objects/");
25 if (!is_directory(objects_directory.buf)) {
26 ret = -1;
27 goto done;
29 /* avoid adding it twice */
30 for (alt_odb = alt_odb_list; alt_odb; alt_odb = alt_odb->next)
31 if (alt_odb->name - alt_odb->base == objects_directory.len &&
32 !strncmp(alt_odb->base, objects_directory.buf,
33 objects_directory.len))
34 goto done;
36 alt_odb = xmalloc(objects_directory.len + 42 + sizeof(*alt_odb));
37 alt_odb->next = alt_odb_list;
38 strcpy(alt_odb->base, objects_directory.buf);
39 alt_odb->name = alt_odb->base + objects_directory.len;
40 alt_odb->name[2] = '/';
41 alt_odb->name[40] = '\0';
42 alt_odb->name[41] = '\0';
43 alt_odb_list = alt_odb;
44 prepare_alt_odb();
45 done:
46 strbuf_release(&objects_directory);
47 return ret;
50 void handle_ignore_submodules_arg(struct diff_options *diffopt,
51 const char *arg)
53 if (!strcmp(arg, "all"))
54 DIFF_OPT_SET(diffopt, IGNORE_SUBMODULES);
55 else if (!strcmp(arg, "untracked"))
56 DIFF_OPT_SET(diffopt, IGNORE_UNTRACKED_IN_SUBMODULES);
57 else if (!strcmp(arg, "dirty"))
58 DIFF_OPT_SET(diffopt, IGNORE_DIRTY_SUBMODULES);
59 else
60 die("bad --ignore-submodules argument: %s", arg);
63 void show_submodule_summary(FILE *f, const char *path,
64 unsigned char one[20], unsigned char two[20],
65 unsigned dirty_submodule,
66 const char *del, const char *add, const char *reset)
68 struct rev_info rev;
69 struct commit *commit, *left = left, *right = right;
70 struct commit_list *merge_bases, *list;
71 const char *message = NULL;
72 struct strbuf sb = STRBUF_INIT;
73 static const char *format = " %m %s";
74 int fast_forward = 0, fast_backward = 0;
76 if (is_null_sha1(two))
77 message = "(submodule deleted)";
78 else if (add_submodule_odb(path))
79 message = "(not checked out)";
80 else if (is_null_sha1(one))
81 message = "(new submodule)";
82 else if (!(left = lookup_commit_reference(one)) ||
83 !(right = lookup_commit_reference(two)))
84 message = "(commits not present)";
86 if (!message) {
87 init_revisions(&rev, NULL);
88 setup_revisions(0, NULL, &rev, NULL);
89 rev.left_right = 1;
90 rev.first_parent_only = 1;
91 left->object.flags |= SYMMETRIC_LEFT;
92 add_pending_object(&rev, &left->object, path);
93 add_pending_object(&rev, &right->object, path);
94 merge_bases = get_merge_bases(left, right, 1);
95 if (merge_bases) {
96 if (merge_bases->item == left)
97 fast_forward = 1;
98 else if (merge_bases->item == right)
99 fast_backward = 1;
101 for (list = merge_bases; list; list = list->next) {
102 list->item->object.flags |= UNINTERESTING;
103 add_pending_object(&rev, &list->item->object,
104 sha1_to_hex(list->item->object.sha1));
106 if (prepare_revision_walk(&rev))
107 message = "(revision walker failed)";
110 if (dirty_submodule & DIRTY_SUBMODULE_UNTRACKED)
111 fprintf(f, "Submodule %s contains untracked content\n", path);
112 if (dirty_submodule & DIRTY_SUBMODULE_MODIFIED)
113 fprintf(f, "Submodule %s contains modified content\n", path);
115 if (!hashcmp(one, two)) {
116 strbuf_release(&sb);
117 return;
120 strbuf_addf(&sb, "Submodule %s %s..", path,
121 find_unique_abbrev(one, DEFAULT_ABBREV));
122 if (!fast_backward && !fast_forward)
123 strbuf_addch(&sb, '.');
124 strbuf_addf(&sb, "%s", find_unique_abbrev(two, DEFAULT_ABBREV));
125 if (message)
126 strbuf_addf(&sb, " %s\n", message);
127 else
128 strbuf_addf(&sb, "%s:\n", fast_backward ? " (rewind)" : "");
129 fwrite(sb.buf, sb.len, 1, f);
131 if (!message) {
132 while ((commit = get_revision(&rev))) {
133 struct pretty_print_context ctx = {0};
134 ctx.date_mode = rev.date_mode;
135 strbuf_setlen(&sb, 0);
136 if (commit->object.flags & SYMMETRIC_LEFT) {
137 if (del)
138 strbuf_addstr(&sb, del);
140 else if (add)
141 strbuf_addstr(&sb, add);
142 format_commit_message(commit, format, &sb, &ctx);
143 if (reset)
144 strbuf_addstr(&sb, reset);
145 strbuf_addch(&sb, '\n');
146 fprintf(f, "%s", sb.buf);
148 clear_commit_marks(left, ~0);
149 clear_commit_marks(right, ~0);
151 strbuf_release(&sb);
154 unsigned is_submodule_modified(const char *path, int ignore_untracked)
156 ssize_t len;
157 struct child_process cp;
158 const char *argv[] = {
159 "status",
160 "--porcelain",
161 NULL,
162 NULL,
164 struct strbuf buf = STRBUF_INIT;
165 unsigned dirty_submodule = 0;
166 const char *line, *next_line;
167 const char *git_dir;
169 strbuf_addf(&buf, "%s/.git", path);
170 git_dir = read_gitfile_gently(buf.buf);
171 if (!git_dir)
172 git_dir = buf.buf;
173 if (!is_directory(git_dir)) {
174 strbuf_release(&buf);
175 /* The submodule is not checked out, so it is not modified */
176 return 0;
179 strbuf_reset(&buf);
181 if (ignore_untracked)
182 argv[2] = "-uno";
184 memset(&cp, 0, sizeof(cp));
185 cp.argv = argv;
186 cp.env = local_repo_env;
187 cp.git_cmd = 1;
188 cp.no_stdin = 1;
189 cp.out = -1;
190 cp.dir = path;
191 if (start_command(&cp))
192 die("Could not run git status --porcelain");
194 len = strbuf_read(&buf, cp.out, 1024);
195 line = buf.buf;
196 while (len > 2) {
197 if ((line[0] == '?') && (line[1] == '?')) {
198 dirty_submodule |= DIRTY_SUBMODULE_UNTRACKED;
199 if (dirty_submodule & DIRTY_SUBMODULE_MODIFIED)
200 break;
201 } else {
202 dirty_submodule |= DIRTY_SUBMODULE_MODIFIED;
203 if (ignore_untracked ||
204 (dirty_submodule & DIRTY_SUBMODULE_UNTRACKED))
205 break;
207 next_line = strchr(line, '\n');
208 if (!next_line)
209 break;
210 next_line++;
211 len -= (next_line - line);
212 line = next_line;
214 close(cp.out);
216 if (finish_command(&cp))
217 die("git status --porcelain failed");
219 strbuf_release(&buf);
220 return dirty_submodule;
223 static int find_first_merges(struct object_array *result, const char *path,
224 struct commit *a, struct commit *b)
226 int i, j;
227 struct object_array merges;
228 struct commit *commit;
229 int contains_another;
231 char merged_revision[42];
232 const char *rev_args[] = { "rev-list", "--merges", "--ancestry-path",
233 "--all", merged_revision, NULL };
234 struct rev_info revs;
235 struct setup_revision_opt rev_opts;
237 memset(&merges, 0, sizeof(merges));
238 memset(result, 0, sizeof(struct object_array));
239 memset(&rev_opts, 0, sizeof(rev_opts));
241 /* get all revisions that merge commit a */
242 snprintf(merged_revision, sizeof(merged_revision), "^%s",
243 sha1_to_hex(a->object.sha1));
244 init_revisions(&revs, NULL);
245 rev_opts.submodule = path;
246 setup_revisions(sizeof(rev_args)/sizeof(char *)-1, rev_args, &revs, &rev_opts);
248 /* save all revisions from the above list that contain b */
249 if (prepare_revision_walk(&revs))
250 die("revision walk setup failed");
251 while ((commit = get_revision(&revs)) != NULL) {
252 struct object *o = &(commit->object);
253 if (in_merge_bases(b, &commit, 1))
254 add_object_array(o, NULL, &merges);
257 /* Now we've got all merges that contain a and b. Prune all
258 * merges that contain another found merge and save them in
259 * result.
261 for (i = 0; i < merges.nr; i++) {
262 struct commit *m1 = (struct commit *) merges.objects[i].item;
264 contains_another = 0;
265 for (j = 0; j < merges.nr; j++) {
266 struct commit *m2 = (struct commit *) merges.objects[j].item;
267 if (i != j && in_merge_bases(m2, &m1, 1)) {
268 contains_another = 1;
269 break;
273 if (!contains_another)
274 add_object_array(merges.objects[i].item,
275 merges.objects[i].name, result);
278 free(merges.objects);
279 return result->nr;
282 static void print_commit(struct commit *commit)
284 struct strbuf sb = STRBUF_INIT;
285 struct pretty_print_context ctx = {0};
286 ctx.date_mode = DATE_NORMAL;
287 format_commit_message(commit, " %h: %m %s", &sb, &ctx);
288 fprintf(stderr, "%s\n", sb.buf);
289 strbuf_release(&sb);
292 #define MERGE_WARNING(path, msg) \
293 warning("Failed to merge submodule %s (%s)", path, msg);
295 int merge_submodule(unsigned char result[20], const char *path,
296 const unsigned char base[20], const unsigned char a[20],
297 const unsigned char b[20])
299 struct commit *commit_base, *commit_a, *commit_b;
300 int parent_count;
301 struct object_array merges;
303 int i;
305 /* store a in result in case we fail */
306 hashcpy(result, a);
308 /* we can not handle deletion conflicts */
309 if (is_null_sha1(base))
310 return 0;
311 if (is_null_sha1(a))
312 return 0;
313 if (is_null_sha1(b))
314 return 0;
316 if (add_submodule_odb(path)) {
317 MERGE_WARNING(path, "not checked out");
318 return 0;
321 if (!(commit_base = lookup_commit_reference(base)) ||
322 !(commit_a = lookup_commit_reference(a)) ||
323 !(commit_b = lookup_commit_reference(b))) {
324 MERGE_WARNING(path, "commits not present");
325 return 0;
328 /* check whether both changes are forward */
329 if (!in_merge_bases(commit_base, &commit_a, 1) ||
330 !in_merge_bases(commit_base, &commit_b, 1)) {
331 MERGE_WARNING(path, "commits don't follow merge-base");
332 return 0;
335 /* Case #1: a is contained in b or vice versa */
336 if (in_merge_bases(commit_a, &commit_b, 1)) {
337 hashcpy(result, b);
338 return 1;
340 if (in_merge_bases(commit_b, &commit_a, 1)) {
341 hashcpy(result, a);
342 return 1;
346 * Case #2: There are one or more merges that contain a and b in
347 * the submodule. If there is only one, then present it as a
348 * suggestion to the user, but leave it marked unmerged so the
349 * user needs to confirm the resolution.
352 /* find commit which merges them */
353 parent_count = find_first_merges(&merges, path, commit_a, commit_b);
354 switch (parent_count) {
355 case 0:
356 MERGE_WARNING(path, "merge following commits not found");
357 break;
359 case 1:
360 MERGE_WARNING(path, "not fast-forward");
361 fprintf(stderr, "Found a possible merge resolution "
362 "for the submodule:\n");
363 print_commit((struct commit *) merges.objects[0].item);
364 fprintf(stderr,
365 "If this is correct simply add it to the index "
366 "for example\n"
367 "by using:\n\n"
368 " git update-index --cacheinfo 160000 %s \"%s\"\n\n"
369 "which will accept this suggestion.\n",
370 sha1_to_hex(merges.objects[0].item->sha1), path);
371 break;
373 default:
374 MERGE_WARNING(path, "multiple merges found");
375 for (i = 0; i < merges.nr; i++)
376 print_commit((struct commit *) merges.objects[i].item);
379 free(merges.objects);
380 return 0;