]>
Commit | Line | Data |
---|---|---|
1 | #include "cache.h" | |
2 | #include "commit.h" | |
3 | #include "tag.h" | |
4 | #include "merge-recursive.h" | |
5 | ||
6 | static const char *better_branch_name(const char *branch) | |
7 | { | |
8 | static char githead_env[8 + 40 + 1]; | |
9 | char *name; | |
10 | ||
11 | if (strlen(branch) != 40) | |
12 | return branch; | |
13 | sprintf(githead_env, "GITHEAD_%s", branch); | |
14 | name = getenv(githead_env); | |
15 | return name ? name : branch; | |
16 | } | |
17 | ||
18 | static struct commit *get_ref(const char *ref) | |
19 | { | |
20 | unsigned char sha1[20]; | |
21 | struct object *object; | |
22 | ||
23 | if (get_sha1(ref, sha1)) | |
24 | die("Could not resolve ref '%s'", ref); | |
25 | object = deref_tag(parse_object(sha1), ref, strlen(ref)); | |
26 | if (!object) | |
27 | return NULL; | |
28 | if (object->type == OBJ_TREE) | |
29 | return make_virtual_commit((struct tree*)object, | |
30 | better_branch_name(ref)); | |
31 | if (object->type != OBJ_COMMIT) | |
32 | return NULL; | |
33 | if (parse_commit((struct commit *)object)) | |
34 | die("Could not parse commit '%s'", sha1_to_hex(object->sha1)); | |
35 | return (struct commit *)object; | |
36 | } | |
37 | ||
38 | int cmd_merge_recursive(int argc, const char **argv, const char *prefix) | |
39 | { | |
40 | static const char *bases[20]; | |
41 | static unsigned bases_count = 0; | |
42 | int i, clean; | |
43 | const char *branch1, *branch2; | |
44 | struct commit *result, *h1, *h2; | |
45 | struct commit_list *ca = NULL; | |
46 | struct lock_file *lock = xcalloc(1, sizeof(struct lock_file)); | |
47 | int index_fd; | |
48 | int subtree_merge = 0; | |
49 | ||
50 | if (argv[0]) { | |
51 | int namelen = strlen(argv[0]); | |
52 | if (8 < namelen && | |
53 | !strcmp(argv[0] + namelen - 8, "-subtree")) | |
54 | subtree_merge = 1; | |
55 | } | |
56 | ||
57 | git_config(merge_recursive_config, NULL); | |
58 | merge_recursive_setup(subtree_merge); | |
59 | if (argc < 4) | |
60 | die("Usage: %s <base>... -- <head> <remote> ...\n", argv[0]); | |
61 | ||
62 | for (i = 1; i < argc; ++i) { | |
63 | if (!strcmp(argv[i], "--")) | |
64 | break; | |
65 | if (bases_count < sizeof(bases)/sizeof(*bases)) | |
66 | bases[bases_count++] = argv[i]; | |
67 | } | |
68 | if (argc - i != 3) /* "--" "<head>" "<remote>" */ | |
69 | die("Not handling anything other than two heads merge."); | |
70 | ||
71 | branch1 = argv[++i]; | |
72 | branch2 = argv[++i]; | |
73 | ||
74 | h1 = get_ref(branch1); | |
75 | h2 = get_ref(branch2); | |
76 | ||
77 | branch1 = better_branch_name(branch1); | |
78 | branch2 = better_branch_name(branch2); | |
79 | ||
80 | if (merge_recursive_verbosity >= 3) | |
81 | printf("Merging %s with %s\n", branch1, branch2); | |
82 | ||
83 | index_fd = hold_locked_index(lock, 1); | |
84 | ||
85 | for (i = 0; i < bases_count; i++) { | |
86 | struct commit *ancestor = get_ref(bases[i]); | |
87 | ca = commit_list_insert(ancestor, &ca); | |
88 | } | |
89 | clean = merge_recursive(h1, h2, branch1, branch2, ca, &result); | |
90 | ||
91 | if (active_cache_changed && | |
92 | (write_cache(index_fd, active_cache, active_nr) || | |
93 | commit_locked_index(lock))) | |
94 | die ("unable to write %s", get_index_file()); | |
95 | ||
96 | return clean ? 0: 1; | |
97 | } |