Code

Implement automatic fast-forward merge for submodules
[git.git] / submodule.c
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)
12 {
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);
23         }
24         strbuf_addstr(&objects_directory, "/objects/");
25         if (!is_directory(objects_directory.buf)) {
26                 ret = -1;
27                 goto done;
28         }
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;
48 }
50 void handle_ignore_submodules_arg(struct diff_options *diffopt,
51                                   const char *arg)
52 {
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);
61 }
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)
67 {
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;
100                 }
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));
105                 }
106                 if (prepare_revision_walk(&rev))
107                         message = "(revision walker failed)";
108         }
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;
118         }
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);
139                         }
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);
147                 }
148                 clear_commit_marks(left, ~0);
149                 clear_commit_marks(right, ~0);
150         }
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,
163         };
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;
178         }
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;
206                 }
207                 next_line = strchr(line, '\n');
208                 if (!next_line)
209                         break;
210                 next_line++;
211                 len -= (next_line - line);
212                 line = next_line;
213         }
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);
255         }
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.
260          */
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;
270                         }
271                 }
273                 if (!contains_another)
274                         add_object_array(merges.objects[i].item,
275                                          merges.objects[i].name, result);
276         }
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;
319         }
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;
326         }
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;
333         }
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;
339         }
340         if (in_merge_bases(commit_b, &commit_a, 1)) {
341                 hashcpy(result, a);
342                 return 1;
343         }
345         /*
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.
350          */
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);
377         }
379         free(merges.objects);
380         return 0;