MinGW: Add missing file mode bit defines
[git/dscho.git] / submodule.c
blob23806383fdd46f901eb2cb51173afbb913d68fde
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"
10 #include "string-list.h"
12 struct string_list config_name_for_path;
13 struct string_list config_fetch_for_name;
14 struct string_list config_ignore_for_name;
16 static int add_submodule_odb(const char *path)
18 struct strbuf objects_directory = STRBUF_INIT;
19 struct alternate_object_database *alt_odb;
20 int ret = 0;
21 const char *git_dir;
23 strbuf_addf(&objects_directory, "%s/.git", path);
24 git_dir = read_gitfile_gently(objects_directory.buf);
25 if (git_dir) {
26 strbuf_reset(&objects_directory);
27 strbuf_addstr(&objects_directory, git_dir);
29 strbuf_addstr(&objects_directory, "/objects/");
30 if (!is_directory(objects_directory.buf)) {
31 ret = -1;
32 goto done;
34 /* avoid adding it twice */
35 for (alt_odb = alt_odb_list; alt_odb; alt_odb = alt_odb->next)
36 if (alt_odb->name - alt_odb->base == objects_directory.len &&
37 !strncmp(alt_odb->base, objects_directory.buf,
38 objects_directory.len))
39 goto done;
41 alt_odb = xmalloc(objects_directory.len + 42 + sizeof(*alt_odb));
42 alt_odb->next = alt_odb_list;
43 strcpy(alt_odb->base, objects_directory.buf);
44 alt_odb->name = alt_odb->base + objects_directory.len;
45 alt_odb->name[2] = '/';
46 alt_odb->name[40] = '\0';
47 alt_odb->name[41] = '\0';
48 alt_odb_list = alt_odb;
49 prepare_alt_odb();
50 done:
51 strbuf_release(&objects_directory);
52 return ret;
55 void set_diffopt_flags_from_submodule_config(struct diff_options *diffopt,
56 const char *path)
58 struct string_list_item *path_option, *ignore_option;
59 path_option = unsorted_string_list_lookup(&config_name_for_path, path);
60 if (path_option) {
61 ignore_option = unsorted_string_list_lookup(&config_ignore_for_name, path_option->util);
62 if (ignore_option)
63 handle_ignore_submodules_arg(diffopt, ignore_option->util);
67 int submodule_config(const char *var, const char *value, void *cb)
69 if (!prefixcmp(var, "submodule."))
70 return parse_submodule_config_option(var, value);
71 return 0;
74 void gitmodules_config(void)
76 const char *work_tree = get_git_work_tree();
77 if (work_tree) {
78 struct strbuf gitmodules_path = STRBUF_INIT;
79 strbuf_addstr(&gitmodules_path, work_tree);
80 strbuf_addstr(&gitmodules_path, "/.gitmodules");
81 git_config_from_file(submodule_config, gitmodules_path.buf, NULL);
82 strbuf_release(&gitmodules_path);
86 int parse_submodule_config_option(const char *var, const char *value)
88 int len;
89 struct string_list_item *config;
90 struct strbuf submodname = STRBUF_INIT;
92 var += 10; /* Skip "submodule." */
94 len = strlen(var);
95 if ((len > 5) && !strcmp(var + len - 5, ".path")) {
96 strbuf_add(&submodname, var, len - 5);
97 config = unsorted_string_list_lookup(&config_name_for_path, value);
98 if (config)
99 free(config->util);
100 else
101 config = string_list_append(&config_name_for_path, xstrdup(value));
102 config->util = strbuf_detach(&submodname, NULL);
103 strbuf_release(&submodname);
104 } else if ((len > 5) && !strcmp(var + len - 6, ".fetch")) {
105 strbuf_add(&submodname, var, len - 6);
106 config = unsorted_string_list_lookup(&config_fetch_for_name, submodname.buf);
107 if (!config)
108 config = string_list_append(&config_fetch_for_name,
109 strbuf_detach(&submodname, NULL));
110 config->util = git_config_bool(var, value) ? (void *)1 : NULL;
111 strbuf_release(&submodname);
112 } else if ((len > 7) && !strcmp(var + len - 7, ".ignore")) {
113 if (strcmp(value, "untracked") && strcmp(value, "dirty") &&
114 strcmp(value, "all") && strcmp(value, "none")) {
115 warning("Invalid parameter \"%s\" for config option \"submodule.%s.ignore\"", value, var);
116 return 0;
119 strbuf_add(&submodname, var, len - 7);
120 config = unsorted_string_list_lookup(&config_ignore_for_name, submodname.buf);
121 if (config)
122 free(config->util);
123 else
124 config = string_list_append(&config_ignore_for_name,
125 strbuf_detach(&submodname, NULL));
126 strbuf_release(&submodname);
127 config->util = xstrdup(value);
128 return 0;
130 return 0;
133 void handle_ignore_submodules_arg(struct diff_options *diffopt,
134 const char *arg)
136 DIFF_OPT_CLR(diffopt, IGNORE_SUBMODULES);
137 DIFF_OPT_CLR(diffopt, IGNORE_UNTRACKED_IN_SUBMODULES);
138 DIFF_OPT_CLR(diffopt, IGNORE_DIRTY_SUBMODULES);
140 if (!strcmp(arg, "all"))
141 DIFF_OPT_SET(diffopt, IGNORE_SUBMODULES);
142 else if (!strcmp(arg, "untracked"))
143 DIFF_OPT_SET(diffopt, IGNORE_UNTRACKED_IN_SUBMODULES);
144 else if (!strcmp(arg, "dirty"))
145 DIFF_OPT_SET(diffopt, IGNORE_DIRTY_SUBMODULES);
146 else if (strcmp(arg, "none"))
147 die("bad --ignore-submodules argument: %s", arg);
150 void show_submodule_summary(FILE *f, const char *path,
151 unsigned char one[20], unsigned char two[20],
152 unsigned dirty_submodule,
153 const char *del, const char *add, const char *reset)
155 struct rev_info rev;
156 struct commit *commit, *left = left, *right = right;
157 struct commit_list *merge_bases, *list;
158 const char *message = NULL;
159 struct strbuf sb = STRBUF_INIT;
160 static const char *format = " %m %s";
161 int fast_forward = 0, fast_backward = 0;
163 if (is_null_sha1(two))
164 message = "(submodule deleted)";
165 else if (add_submodule_odb(path))
166 message = "(not checked out)";
167 else if (is_null_sha1(one))
168 message = "(new submodule)";
169 else if (!(left = lookup_commit_reference(one)) ||
170 !(right = lookup_commit_reference(two)))
171 message = "(commits not present)";
173 if (!message) {
174 init_revisions(&rev, NULL);
175 setup_revisions(0, NULL, &rev, NULL);
176 rev.left_right = 1;
177 rev.first_parent_only = 1;
178 left->object.flags |= SYMMETRIC_LEFT;
179 add_pending_object(&rev, &left->object, path);
180 add_pending_object(&rev, &right->object, path);
181 merge_bases = get_merge_bases(left, right, 1);
182 if (merge_bases) {
183 if (merge_bases->item == left)
184 fast_forward = 1;
185 else if (merge_bases->item == right)
186 fast_backward = 1;
188 for (list = merge_bases; list; list = list->next) {
189 list->item->object.flags |= UNINTERESTING;
190 add_pending_object(&rev, &list->item->object,
191 sha1_to_hex(list->item->object.sha1));
193 if (prepare_revision_walk(&rev))
194 message = "(revision walker failed)";
197 if (dirty_submodule & DIRTY_SUBMODULE_UNTRACKED)
198 fprintf(f, "Submodule %s contains untracked content\n", path);
199 if (dirty_submodule & DIRTY_SUBMODULE_MODIFIED)
200 fprintf(f, "Submodule %s contains modified content\n", path);
202 if (!hashcmp(one, two)) {
203 strbuf_release(&sb);
204 return;
207 strbuf_addf(&sb, "Submodule %s %s..", path,
208 find_unique_abbrev(one, DEFAULT_ABBREV));
209 if (!fast_backward && !fast_forward)
210 strbuf_addch(&sb, '.');
211 strbuf_addf(&sb, "%s", find_unique_abbrev(two, DEFAULT_ABBREV));
212 if (message)
213 strbuf_addf(&sb, " %s\n", message);
214 else
215 strbuf_addf(&sb, "%s:\n", fast_backward ? " (rewind)" : "");
216 fwrite(sb.buf, sb.len, 1, f);
218 if (!message) {
219 while ((commit = get_revision(&rev))) {
220 struct pretty_print_context ctx = {0};
221 ctx.date_mode = rev.date_mode;
222 strbuf_setlen(&sb, 0);
223 if (commit->object.flags & SYMMETRIC_LEFT) {
224 if (del)
225 strbuf_addstr(&sb, del);
227 else if (add)
228 strbuf_addstr(&sb, add);
229 format_commit_message(commit, format, &sb, &ctx);
230 if (reset)
231 strbuf_addstr(&sb, reset);
232 strbuf_addch(&sb, '\n');
233 fprintf(f, "%s", sb.buf);
235 clear_commit_marks(left, ~0);
236 clear_commit_marks(right, ~0);
238 strbuf_release(&sb);
241 int fetch_populated_submodules(int forced)
243 int result = 0;
244 struct child_process cp;
245 const char *argv[] = {
246 "fetch",
247 NULL,
249 struct string_list_item *name_for_path;
250 const char *work_tree = get_git_work_tree();
251 if (!work_tree)
252 return 0;
254 memset(&cp, 0, sizeof(cp));
255 cp.argv = argv;
256 cp.env = local_repo_env;
257 cp.git_cmd = 1;
258 cp.no_stdin = 1;
259 cp.out = -1;
261 for_each_string_list_item(name_for_path, &config_name_for_path) {
262 struct strbuf submodule_path = STRBUF_INIT;
263 struct strbuf submodule_git_dir = STRBUF_INIT;
264 const char *git_dir;
266 if (!forced) {
267 struct string_list_item *fetch_option;
268 fetch_option = unsorted_string_list_lookup(&config_fetch_for_name, name_for_path->util);
269 if (fetch_option && !fetch_option->util)
270 continue;
273 strbuf_addf(&submodule_path, "%s/%s", work_tree, name_for_path->string);
274 strbuf_addf(&submodule_git_dir, "%s/.git", submodule_path.buf);
275 git_dir = read_gitfile_gently(submodule_git_dir.buf);
276 if (!git_dir)
277 git_dir = submodule_git_dir.buf;
278 if (is_directory(git_dir)) {
279 printf("Fetching submodule %s\n", name_for_path->string);
280 cp.dir = submodule_path.buf;
281 if (run_command(&cp))
282 result = 1;
284 strbuf_release(&submodule_path);
285 strbuf_release(&submodule_git_dir);
287 return result;
290 unsigned is_submodule_modified(const char *path, int ignore_untracked)
292 ssize_t len;
293 struct child_process cp;
294 const char *argv[] = {
295 "status",
296 "--porcelain",
297 NULL,
298 NULL,
300 struct strbuf buf = STRBUF_INIT;
301 unsigned dirty_submodule = 0;
302 const char *line, *next_line;
303 const char *git_dir;
305 strbuf_addf(&buf, "%s/.git", path);
306 git_dir = read_gitfile_gently(buf.buf);
307 if (!git_dir)
308 git_dir = buf.buf;
309 if (!is_directory(git_dir)) {
310 strbuf_release(&buf);
311 /* The submodule is not checked out, so it is not modified */
312 return 0;
315 strbuf_reset(&buf);
317 if (ignore_untracked)
318 argv[2] = "-uno";
320 memset(&cp, 0, sizeof(cp));
321 cp.argv = argv;
322 cp.env = local_repo_env;
323 cp.git_cmd = 1;
324 cp.no_stdin = 1;
325 cp.out = -1;
326 cp.dir = path;
327 if (start_command(&cp))
328 die("Could not run git status --porcelain");
330 len = strbuf_read(&buf, cp.out, 1024);
331 line = buf.buf;
332 while (len > 2) {
333 if ((line[0] == '?') && (line[1] == '?')) {
334 dirty_submodule |= DIRTY_SUBMODULE_UNTRACKED;
335 if (dirty_submodule & DIRTY_SUBMODULE_MODIFIED)
336 break;
337 } else {
338 dirty_submodule |= DIRTY_SUBMODULE_MODIFIED;
339 if (ignore_untracked ||
340 (dirty_submodule & DIRTY_SUBMODULE_UNTRACKED))
341 break;
343 next_line = strchr(line, '\n');
344 if (!next_line)
345 break;
346 next_line++;
347 len -= (next_line - line);
348 line = next_line;
350 close(cp.out);
352 if (finish_command(&cp))
353 die("git status --porcelain failed");
355 strbuf_release(&buf);
356 return dirty_submodule;
359 static int find_first_merges(struct object_array *result, const char *path,
360 struct commit *a, struct commit *b)
362 int i, j;
363 struct object_array merges;
364 struct commit *commit;
365 int contains_another;
367 char merged_revision[42];
368 const char *rev_args[] = { "rev-list", "--merges", "--ancestry-path",
369 "--all", merged_revision, NULL };
370 struct rev_info revs;
371 struct setup_revision_opt rev_opts;
373 memset(&merges, 0, sizeof(merges));
374 memset(result, 0, sizeof(struct object_array));
375 memset(&rev_opts, 0, sizeof(rev_opts));
377 /* get all revisions that merge commit a */
378 snprintf(merged_revision, sizeof(merged_revision), "^%s",
379 sha1_to_hex(a->object.sha1));
380 init_revisions(&revs, NULL);
381 rev_opts.submodule = path;
382 setup_revisions(sizeof(rev_args)/sizeof(char *)-1, rev_args, &revs, &rev_opts);
384 /* save all revisions from the above list that contain b */
385 if (prepare_revision_walk(&revs))
386 die("revision walk setup failed");
387 while ((commit = get_revision(&revs)) != NULL) {
388 struct object *o = &(commit->object);
389 if (in_merge_bases(b, &commit, 1))
390 add_object_array(o, NULL, &merges);
393 /* Now we've got all merges that contain a and b. Prune all
394 * merges that contain another found merge and save them in
395 * result.
397 for (i = 0; i < merges.nr; i++) {
398 struct commit *m1 = (struct commit *) merges.objects[i].item;
400 contains_another = 0;
401 for (j = 0; j < merges.nr; j++) {
402 struct commit *m2 = (struct commit *) merges.objects[j].item;
403 if (i != j && in_merge_bases(m2, &m1, 1)) {
404 contains_another = 1;
405 break;
409 if (!contains_another)
410 add_object_array(merges.objects[i].item,
411 merges.objects[i].name, result);
414 free(merges.objects);
415 return result->nr;
418 static void print_commit(struct commit *commit)
420 struct strbuf sb = STRBUF_INIT;
421 struct pretty_print_context ctx = {0};
422 ctx.date_mode = DATE_NORMAL;
423 format_commit_message(commit, " %h: %m %s", &sb, &ctx);
424 fprintf(stderr, "%s\n", sb.buf);
425 strbuf_release(&sb);
428 #define MERGE_WARNING(path, msg) \
429 warning("Failed to merge submodule %s (%s)", path, msg);
431 int merge_submodule(unsigned char result[20], const char *path,
432 const unsigned char base[20], const unsigned char a[20],
433 const unsigned char b[20])
435 struct commit *commit_base, *commit_a, *commit_b;
436 int parent_count;
437 struct object_array merges;
439 int i;
441 /* store a in result in case we fail */
442 hashcpy(result, a);
444 /* we can not handle deletion conflicts */
445 if (is_null_sha1(base))
446 return 0;
447 if (is_null_sha1(a))
448 return 0;
449 if (is_null_sha1(b))
450 return 0;
452 if (add_submodule_odb(path)) {
453 MERGE_WARNING(path, "not checked out");
454 return 0;
457 if (!(commit_base = lookup_commit_reference(base)) ||
458 !(commit_a = lookup_commit_reference(a)) ||
459 !(commit_b = lookup_commit_reference(b))) {
460 MERGE_WARNING(path, "commits not present");
461 return 0;
464 /* check whether both changes are forward */
465 if (!in_merge_bases(commit_base, &commit_a, 1) ||
466 !in_merge_bases(commit_base, &commit_b, 1)) {
467 MERGE_WARNING(path, "commits don't follow merge-base");
468 return 0;
471 /* Case #1: a is contained in b or vice versa */
472 if (in_merge_bases(commit_a, &commit_b, 1)) {
473 hashcpy(result, b);
474 return 1;
476 if (in_merge_bases(commit_b, &commit_a, 1)) {
477 hashcpy(result, a);
478 return 1;
482 * Case #2: There are one or more merges that contain a and b in
483 * the submodule. If there is only one, then present it as a
484 * suggestion to the user, but leave it marked unmerged so the
485 * user needs to confirm the resolution.
488 /* find commit which merges them */
489 parent_count = find_first_merges(&merges, path, commit_a, commit_b);
490 switch (parent_count) {
491 case 0:
492 MERGE_WARNING(path, "merge following commits not found");
493 break;
495 case 1:
496 MERGE_WARNING(path, "not fast-forward");
497 fprintf(stderr, "Found a possible merge resolution "
498 "for the submodule:\n");
499 print_commit((struct commit *) merges.objects[0].item);
500 fprintf(stderr,
501 "If this is correct simply add it to the index "
502 "for example\n"
503 "by using:\n\n"
504 " git update-index --cacheinfo 160000 %s \"%s\"\n\n"
505 "which will accept this suggestion.\n",
506 sha1_to_hex(merges.objects[0].item->sha1), path);
507 break;
509 default:
510 MERGE_WARNING(path, "multiple merges found");
511 for (i = 0; i < merges.nr; i++)
512 print_commit((struct commit *) merges.objects[i].item);
515 free(merges.objects);
516 return 0;