@matheusbsbs / matheus-bagliano / commits / 8a2fce1895
Fork 0

merge-recursive: introduce merge_options

This makes it possible to avoid passing the labels of branches as arguments to merge_recursive(), merge_trees() and merge_recursive_generic(). It also takes care of subtree merge, output buffering, verbosity, and rename limits - these were global variables till now in merge-recursive.c. A new function, named init_merge_options(), is introduced as well, it clears the struct merge_info, then initializes with default values, finally updates the default values based on the config and environment variables. Signed-off-by: Miklos Vajna <vmiklos@frugalware.org> Signed-off-by: Junio C Hamano <gitster@pobox.com>

Miklos Vajna committed Aug 25, 2008 at 16:25 UTC 8a2fce1895c058945d8e2dbd8cb7456cc7450ad8
4 files changed +192 -169
builtin-checkout.c
+8 -3
@@ -264,6 +264,7 @@ static int merge_working_tree(struct checkout_opts *opts,
264 */
265 struct tree *result;
266 struct tree *work;
267 + struct merge_options o;
268 if (!opts->merge)
269 return 1;
270 parse_commit(old->commit);
@@ -282,13 +283,17 @@ static int merge_working_tree(struct checkout_opts *opts,
283 */
284
285 add_files_to_cache(NULL, NULL, 0);
285 - work = write_tree_from_memory();
286 + init_merge_options(&o);
287 + o.verbosity = 0;
288 + work = write_tree_from_memory(&o);
289
290 ret = reset_tree(new->commit->tree, opts, 1);
291 if (ret)
292 return ret;
290 - merge_trees(new->commit->tree, work, old->commit->tree,
291 - new->name, "local", &result);
293 + o.branch1 = new->name;
294 + o.branch2 = "local";
295 + merge_trees(&o, new->commit->tree, work,
296 + old->commit->tree, &result);
297 ret = reset_tree(new->commit->tree, opts, 0);
298 if (ret)
299 return ret;
builtin-merge-recursive.c
+22 -21
@@ -17,32 +17,33 @@ static const char *better_branch_name(const char *branch)
17
18 int cmd_merge_recursive(int argc, const char **argv, const char *prefix)
19 {
20 - const char *bases[21];
20 + const unsigned char *bases[21];
21 unsigned bases_count = 0;
22 int i, failed;
23 - const char *branch1, *branch2;
23 unsigned char h1[20], h2[20];
25 - int subtree_merge = 0;
24 + struct merge_options o;
25 + struct commit *result;
26
27 + init_merge_options(&o);
28 if (argv[0]) {
29 int namelen = strlen(argv[0]);
30 if (8 < namelen &&
31 !strcmp(argv[0] + namelen - 8, "-subtree"))
31 - subtree_merge = 1;
32 + o.subtree_merge = 1;
33 }
34
34 - git_config(merge_recursive_config, NULL);
35 - merge_recursive_setup(subtree_merge);
35 if (argc < 4)
36 die("Usage: %s <base>... -- <head> <remote> ...\n", argv[0]);
37
38 for (i = 1; i < argc; ++i) {
40 - if (!strcmp(argv[i], "--")) {
41 - bases[bases_count] = NULL;
39 + if (!strcmp(argv[i], "--"))
40 break;
41 + if (bases_count < ARRAY_SIZE(bases)-1) {
42 + unsigned char *sha = xmalloc(20);
43 + if (get_sha1(argv[i], sha))
44 + die("Could not parse object '%s'", argv[i]);
45 + bases[bases_count++] = sha;
46 }
44 - if (bases_count < ARRAY_SIZE(bases)-1)
45 - bases[bases_count++] = argv[i];
47 else
48 warning("Cannot handle more than %zu bases. "
49 "Ignoring %s.", ARRAY_SIZE(bases)-1, argv[i]);
@@ -50,21 +51,21 @@ int cmd_merge_recursive(int argc, const char **argv, const char *prefix)
51 if (argc - i != 3) /* "--" "<head>" "<remote>" */
52 die("Not handling anything other than two heads merge.");
53
53 - branch1 = argv[++i];
54 - branch2 = argv[++i];
54 + o.branch1 = argv[++i];
55 + o.branch2 = argv[++i];
56
56 - if (get_sha1(branch1, h1))
57 - die("Could not resolve ref '%s'", branch1);
58 - if (get_sha1(branch2, h2))
59 - die("Could not resolve ref '%s'", branch2);
57 + if (get_sha1(o.branch1, h1))
58 + die("Could not resolve ref '%s'", o.branch1);
59 + if (get_sha1(o.branch2, h2))
60 + die("Could not resolve ref '%s'", o.branch2);
61
61 - branch1 = better_branch_name(branch1);
62 - branch2 = better_branch_name(branch2);
62 + o.branch1 = better_branch_name(o.branch1);
63 + o.branch2 = better_branch_name(o.branch2);
64
64 - if (merge_recursive_verbosity >= 3)
65 - printf("Merging %s with %s\n", branch1, branch2);
65 + if (o.verbosity >= 3)
66 + printf("Merging %s with %s\n", o.branch1, o.branch2);
67
67 - failed = merge_recursive_generic(bases, h1, branch1, h2, branch2);
68 + failed = merge_recursive_generic(&o, h1, h2, bases_count, bases, &result);
69 if (failed < 0)
70 return 128; /* die() error code */
71 return failed;
merge-recursive.c
+133 -132
@@ -20,8 +20,6 @@
20 #include "attr.h"
21 #include "merge-recursive.h"
22
23 -static int subtree_merge;
24 -
23 static struct tree *shift_tree_object(struct tree *one, struct tree *two)
24 {
25 unsigned char shifted[20];
@@ -83,16 +81,11 @@ static struct string_list current_file_set = {NULL, 0, 0, 1};
81 static struct string_list current_directory_set = {NULL, 0, 0, 1};
82
83 static int call_depth = 0;
86 -int merge_recursive_verbosity = 2;
87 -static int diff_rename_limit = -1;
88 -static int merge_rename_limit = -1;
89 -static int buffer_output = 1;
84 static struct strbuf obuf = STRBUF_INIT;
85
92 -static int show(int v)
86 +static int show(struct merge_options *o, int v)
87 {
94 - return (!call_depth && merge_recursive_verbosity >= v) ||
95 - merge_recursive_verbosity >= 5;
88 + return (!call_depth && o->verbosity >= v) || o->verbosity >= 5;
89 }
90
91 static void flush_output(void)
@@ -103,12 +96,12 @@ static void flush_output(void)
96 }
97 }
98
106 -static void output(int v, const char *fmt, ...)
99 +static void output(struct merge_options *o, int v, const char *fmt, ...)
100 {
101 int len;
102 va_list ap;
103
111 - if (!show(v))
104 + if (!show(o, v))
105 return;
106
107 strbuf_grow(&obuf, call_depth * 2 + 2);
@@ -132,7 +125,7 @@ static void output(int v, const char *fmt, ...)
125 }
126 strbuf_setlen(&obuf, obuf.len + len);
127 strbuf_add(&obuf, "\n", 1);
135 - if (!buffer_output)
128 + if (!o->buffer_output)
129 flush_output();
130 }
131
@@ -219,17 +212,17 @@ static int git_merge_trees(int index_only,
212 return rc;
213 }
214
222 -struct tree *write_tree_from_memory(void)
215 +struct tree *write_tree_from_memory(struct merge_options *o)
216 {
217 struct tree *result = NULL;
218
219 if (unmerged_cache()) {
220 int i;
228 - output(0, "There are unmerged index entries:");
221 + output(o, 0, "There are unmerged index entries:");
222 for (i = 0; i < active_nr; i++) {
223 struct cache_entry *ce = active_cache[i];
224 if (ce_stage(ce))
232 - output(0, "%d %.*s", ce_stage(ce), ce_namelen(ce), ce->name);
225 + output(o, 0, "%d %.*s", ce_stage(ce), ce_namelen(ce), ce->name);
226 }
227 return NULL;
228 }
@@ -341,11 +334,12 @@ struct rename
334 * 'b_tree') to be able to associate the correct cache entries with
335 * the rename information. 'tree' is always equal to either a_tree or b_tree.
336 */
344 -static struct string_list *get_renames(struct tree *tree,
345 - struct tree *o_tree,
346 - struct tree *a_tree,
347 - struct tree *b_tree,
348 - struct string_list *entries)
337 +static struct string_list *get_renames(struct merge_options *o,
338 + struct tree *tree,
339 + struct tree *o_tree,
340 + struct tree *a_tree,
341 + struct tree *b_tree,
342 + struct string_list *entries)
343 {
344 int i;
345 struct string_list *renames;
@@ -355,8 +349,8 @@ static struct string_list *get_renames(struct tree *tree,
349 diff_setup(&opts);
350 DIFF_OPT_SET(&opts, RECURSIVE);
351 opts.detect_rename = DIFF_DETECT_RENAME;
358 - opts.rename_limit = merge_rename_limit >= 0 ? merge_rename_limit :
359 - diff_rename_limit >= 0 ? diff_rename_limit :
352 + opts.rename_limit = o->merge_rename_limit >= 0 ? o->merge_rename_limit :
353 + o->diff_rename_limit >= 0 ? o->diff_rename_limit :
354 500;
355 opts.warn_on_too_large_rename = 1;
356 opts.output_format = DIFF_FORMAT_NO_OUTPUT;
@@ -717,7 +711,8 @@ static struct merge_file_info merge_file(struct diff_filespec *o,
711 return result;
712 }
713
720 -static void conflict_rename_rename(struct rename *ren1,
714 +static void conflict_rename_rename(struct merge_options *o,
715 + struct rename *ren1,
716 const char *branch1,
717 struct rename *ren2,
718 const char *branch2)
@@ -730,13 +725,13 @@ static void conflict_rename_rename(struct rename *ren1,
725 const char *dst_name2 = ren2_dst;
726 if (string_list_has_string(&current_directory_set, ren1_dst)) {
727 dst_name1 = del[delp++] = unique_path(ren1_dst, branch1);
733 - output(1, "%s is a directory in %s adding as %s instead",
728 + output(o, 1, "%s is a directory in %s adding as %s instead",
729 ren1_dst, branch2, dst_name1);
730 remove_file(0, ren1_dst, 0);
731 }
732 if (string_list_has_string(&current_directory_set, ren2_dst)) {
733 dst_name2 = del[delp++] = unique_path(ren2_dst, branch2);
739 - output(1, "%s is a directory in %s adding as %s instead",
734 + output(o, 1, "%s is a directory in %s adding as %s instead",
735 ren2_dst, branch1, dst_name2);
736 remove_file(0, ren2_dst, 0);
737 }
@@ -757,24 +752,26 @@ static void conflict_rename_rename(struct rename *ren1,
752 free(del[delp]);
753 }
754
760 -static void conflict_rename_dir(struct rename *ren1,
755 +static void conflict_rename_dir(struct merge_options *o,
756 + struct rename *ren1,
757 const char *branch1)
758 {
759 char *new_path = unique_path(ren1->pair->two->path, branch1);
764 - output(1, "Renaming %s to %s instead", ren1->pair->one->path, new_path);
760 + output(o, 1, "Renaming %s to %s instead", ren1->pair->one->path, new_path);
761 remove_file(0, ren1->pair->two->path, 0);
762 update_file(0, ren1->pair->two->sha1, ren1->pair->two->mode, new_path);
763 free(new_path);
764 }
765
770 -static void conflict_rename_rename_2(struct rename *ren1,
766 +static void conflict_rename_rename_2(struct merge_options *o,
767 + struct rename *ren1,
768 const char *branch1,
769 struct rename *ren2,
770 const char *branch2)
771 {
772 char *new_path1 = unique_path(ren1->pair->two->path, branch1);
773 char *new_path2 = unique_path(ren2->pair->two->path, branch2);
777 - output(1, "Renaming %s to %s and %s to %s instead",
774 + output(o, 1, "Renaming %s to %s and %s to %s instead",
775 ren1->pair->one->path, new_path1,
776 ren2->pair->one->path, new_path2);
777 remove_file(0, ren1->pair->two->path, 0);
@@ -784,10 +781,9 @@ static void conflict_rename_rename_2(struct rename *ren1,
781 free(new_path1);
782 }
783
787 -static int process_renames(struct string_list *a_renames,
788 - struct string_list *b_renames,
789 - const char *a_branch,
790 - const char *b_branch)
784 +static int process_renames(struct merge_options *o,
785 + struct string_list *a_renames,
786 + struct string_list *b_renames)
787 {
788 int clean_merge = 1, i, j;
789 struct string_list a_by_dst = {NULL, 0, 0, 0}, b_by_dst = {NULL, 0, 0, 0};
@@ -832,15 +828,15 @@ static int process_renames(struct string_list *a_renames,
828 renames1 = a_renames;
829 renames2 = b_renames;
830 renames2Dst = &b_by_dst;
835 - branch1 = a_branch;
836 - branch2 = b_branch;
831 + branch1 = o->branch1;
832 + branch2 = o->branch2;
833 } else {
834 struct rename *tmp;
835 renames1 = b_renames;
836 renames2 = a_renames;
837 renames2Dst = &a_by_dst;
842 - branch1 = b_branch;
843 - branch2 = a_branch;
838 + branch1 = o->branch2;
839 + branch2 = o->branch1;
840 tmp = ren2;
841 ren2 = ren1;
842 ren1 = tmp;
@@ -867,7 +863,7 @@ static int process_renames(struct string_list *a_renames,
863 ren2->processed = 1;
864 if (strcmp(ren1_dst, ren2_dst) != 0) {
865 clean_merge = 0;
870 - output(1, "CONFLICT (rename/rename): "
866 + output(o, 1, "CONFLICT (rename/rename): "
867 "Rename \"%s\"->\"%s\" in branch \"%s\" "
868 "rename \"%s\"->\"%s\" in \"%s\"%s",
869 src, ren1_dst, branch1,
@@ -878,7 +874,7 @@ static int process_renames(struct string_list *a_renames,
874 update_file(0, ren1->pair->one->sha1,
875 ren1->pair->one->mode, src);
876 }
881 - conflict_rename_rename(ren1, branch1, ren2, branch2);
877 + conflict_rename_rename(o, ren1, branch1, ren2, branch2);
878 } else {
879 struct merge_file_info mfi;
880 remove_file(1, ren1_src, 1);
@@ -888,13 +884,13 @@ static int process_renames(struct string_list *a_renames,
884 branch1,
885 branch2);
886 if (mfi.merge || !mfi.clean)
891 - output(1, "Renaming %s->%s", src, ren1_dst);
887 + output(o, 1, "Renaming %s->%s", src, ren1_dst);
888
889 if (mfi.merge)
894 - output(2, "Auto-merging %s", ren1_dst);
890 + output(o, 2, "Auto-merging %s", ren1_dst);
891
892 if (!mfi.clean) {
897 - output(1, "CONFLICT (content): merge conflict in %s",
893 + output(o, 1, "CONFLICT (content): merge conflict in %s",
894 ren1_dst);
895 clean_merge = 0;
896
@@ -925,14 +921,14 @@ static int process_renames(struct string_list *a_renames,
921
922 if (string_list_has_string(&current_directory_set, ren1_dst)) {
923 clean_merge = 0;
928 - output(1, "CONFLICT (rename/directory): Rename %s->%s in %s "
924 + output(o, 1, "CONFLICT (rename/directory): Rename %s->%s in %s "
925 " directory %s added in %s",
926 ren1_src, ren1_dst, branch1,
927 ren1_dst, branch2);
932 - conflict_rename_dir(ren1, branch1);
928 + conflict_rename_dir(o, ren1, branch1);
929 } else if (sha_eq(src_other.sha1, null_sha1)) {
930 clean_merge = 0;
935 - output(1, "CONFLICT (rename/delete): Rename %s->%s in %s "
931 + output(o, 1, "CONFLICT (rename/delete): Rename %s->%s in %s "
932 "and deleted in %s",
933 ren1_src, ren1_dst, branch1,
934 branch2);
@@ -941,31 +937,32 @@ static int process_renames(struct string_list *a_renames,
937 const char *new_path;
938 clean_merge = 0;
939 try_merge = 1;
944 - output(1, "CONFLICT (rename/add): Rename %s->%s in %s. "
940 + output(o, 1, "CONFLICT (rename/add): Rename %s->%s in %s. "
941 "%s added in %s",
942 ren1_src, ren1_dst, branch1,
943 ren1_dst, branch2);
944 new_path = unique_path(ren1_dst, branch2);
949 - output(1, "Adding as %s instead", new_path);
945 + output(o, 1, "Adding as %s instead", new_path);
946 update_file(0, dst_other.sha1, dst_other.mode, new_path);
947 } else if ((item = string_list_lookup(ren1_dst, renames2Dst))) {
948 ren2 = item->util;
949 clean_merge = 0;
950 ren2->processed = 1;
955 - output(1, "CONFLICT (rename/rename): Rename %s->%s in %s. "
951 + output(o, 1, "CONFLICT (rename/rename): "
952 + "Rename %s->%s in %s. "
953 "Rename %s->%s in %s",
954 ren1_src, ren1_dst, branch1,
955 ren2->pair->one->path, ren2->pair->two->path, branch2);
959 - conflict_rename_rename_2(ren1, branch1, ren2, branch2);
956 + conflict_rename_rename_2(o, ren1, branch1, ren2, branch2);
957 } else
958 try_merge = 1;
959
960 if (try_merge) {
964 - struct diff_filespec *o, *a, *b;
961 + struct diff_filespec *one, *a, *b;
962 struct merge_file_info mfi;
963 src_other.path = (char *)ren1_src;
964
968 - o = ren1->pair->one;
965 + one = ren1->pair->one;
966 if (a_renames == renames1) {
967 a = ren1->pair->two;
968 b = &src_other;
@@ -973,8 +970,8 @@ static int process_renames(struct string_list *a_renames,
970 b = ren1->pair->two;
971 a = &src_other;
972 }
976 - mfi = merge_file(o, a, b,
977 - a_branch, b_branch);
973 + mfi = merge_file(one, a, b,
974 + o->branch1, o->branch2);
975
976 if (mfi.clean &&
977 sha_eq(mfi.sha, ren1->pair->two->sha1) &&
@@ -984,20 +981,20 @@ static int process_renames(struct string_list *a_renames,
981 * t6022 test. If you change
982 * it update the test too.
983 */
987 - output(3, "Skipped %s (merged same as existing)", ren1_dst);
984 + output(o, 3, "Skipped %s (merged same as existing)", ren1_dst);
985 else {
986 if (mfi.merge || !mfi.clean)
990 - output(1, "Renaming %s => %s", ren1_src, ren1_dst);
987 + output(o, 1, "Renaming %s => %s", ren1_src, ren1_dst);
988 if (mfi.merge)
992 - output(2, "Auto-merging %s", ren1_dst);
989 + output(o, 2, "Auto-merging %s", ren1_dst);
990 if (!mfi.clean) {
994 - output(1, "CONFLICT (rename/modify): Merge conflict in %s",
991 + output(o, 1, "CONFLICT (rename/modify): Merge conflict in %s",
992 ren1_dst);
993 clean_merge = 0;
994
995 if (!index_only)
996 update_stages(ren1_dst,
1000 - o, a, b, 1);
997 + one, a, b, 1);
998 }
999 update_file(mfi.clean, mfi.sha, mfi.mode, ren1_dst);
1000 }
@@ -1016,9 +1013,8 @@ static unsigned char *stage_sha(const unsigned char *sha, unsigned mode)
1013 }
1014
1015 /* Per entry merge function */
1019 -static int process_entry(const char *path, struct stage_data *entry,
1020 - const char *branch1,
1021 - const char *branch2)
1016 +static int process_entry(struct merge_options *o,
1017 + const char *path, struct stage_data *entry)
1018 {
1019 /*
1020 printf("processing entry, clean cache: %s\n", index_only ? "yes": "no");
@@ -1040,23 +1036,23 @@ static int process_entry(const char *path, struct stage_data *entry,
1036 /* Deleted in both or deleted in one and
1037 * unchanged in the other */
1038 if (a_sha)
1043 - output(2, "Removing %s", path);
1039 + output(o, 2, "Removing %s", path);
1040 /* do not touch working file if it did not exist */
1041 remove_file(1, path, !a_sha);
1042 } else {
1043 /* Deleted in one and changed in the other */
1044 clean_merge = 0;
1045 if (!a_sha) {
1050 - output(1, "CONFLICT (delete/modify): %s deleted in %s "
1046 + output(o, 1, "CONFLICT (delete/modify): %s deleted in %s "
1047 "and modified in %s. Version %s of %s left in tree.",
1052 - path, branch1,
1053 - branch2, branch2, path);
1048 + path, o->branch1,
1049 + o->branch2, o->branch2, path);
1050 update_file(0, b_sha, b_mode, path);
1051 } else {
1056 - output(1, "CONFLICT (delete/modify): %s deleted in %s "
1052 + output(o, 1, "CONFLICT (delete/modify): %s deleted in %s "
1053 "and modified in %s. Version %s of %s left in tree.",
1058 - path, branch2,
1059 - branch1, branch1, path);
1054 + path, o->branch2,
1055 + o->branch1, o->branch1, path);
1056 update_file(0, a_sha, a_mode, path);
1057 }
1058 }
@@ -1071,14 +1067,14 @@ static int process_entry(const char *path, struct stage_data *entry,
1067 const char *conf;
1068
1069 if (a_sha) {
1074 - add_branch = branch1;
1075 - other_branch = branch2;
1070 + add_branch = o->branch1;
1071 + other_branch = o->branch2;
1072 mode = a_mode;
1073 sha = a_sha;
1074 conf = "file/directory";
1075 } else {
1080 - add_branch = branch2;
1081 - other_branch = branch1;
1076 + add_branch = o->branch2;
1077 + other_branch = o->branch1;
1078 mode = b_mode;
1079 sha = b_sha;
1080 conf = "directory/file";
@@ -1086,13 +1082,13 @@ static int process_entry(const char *path, struct stage_data *entry,
1082 if (string_list_has_string(&current_directory_set, path)) {
1083 const char *new_path = unique_path(path, add_branch);
1084 clean_merge = 0;
1089 - output(1, "CONFLICT (%s): There is a directory with name %s in %s. "
1085 + output(o, 1, "CONFLICT (%s): There is a directory with name %s in %s. "
1086 "Adding %s as %s",
1087 conf, path, other_branch, path, new_path);
1088 remove_file(0, path, 0);
1089 update_file(0, sha, mode, new_path);
1090 } else {
1095 - output(2, "Adding %s", path);
1091 + output(o, 2, "Adding %s", path);
1092 update_file(1, sha, mode, path);
1093 }
1094 } else if (a_sha && b_sha) {
@@ -1100,32 +1096,32 @@ static int process_entry(const char *path, struct stage_data *entry,
1096 /* case D: Modified in both, but differently. */
1097 const char *reason = "content";
1098 struct merge_file_info mfi;
1103 - struct diff_filespec o, a, b;
1099 + struct diff_filespec one, a, b;
1100
1101 if (!o_sha) {
1102 reason = "add/add";
1103 o_sha = (unsigned char *)null_sha1;
1104 }
1109 - output(2, "Auto-merging %s", path);
1110 - o.path = a.path = b.path = (char *)path;
1111 - hashcpy(o.sha1, o_sha);
1112 - o.mode = o_mode;
1105 + output(o, 2, "Auto-merging %s", path);
1106 + one.path = a.path = b.path = (char *)path;
1107 + hashcpy(one.sha1, o_sha);
1108 + one.mode = o_mode;
1109 hashcpy(a.sha1, a_sha);
1110 a.mode = a_mode;
1111 hashcpy(b.sha1, b_sha);
1112 b.mode = b_mode;
1113
1118 - mfi = merge_file(&o, &a, &b,
1119 - branch1, branch2);
1114 + mfi = merge_file(&one, &a, &b,
1115 + o->branch1, o->branch2);
1116
1117 clean_merge = mfi.clean;
1118 if (mfi.clean)
1119 update_file(1, mfi.sha, mfi.mode, path);
1120 else if (S_ISGITLINK(mfi.mode))
1125 - output(1, "CONFLICT (submodule): Merge conflict in %s "
1121 + output(o, 1, "CONFLICT (submodule): Merge conflict in %s "
1122 "- needs %s", path, sha1_to_hex(b.sha1));
1123 else {
1128 - output(1, "CONFLICT (%s): Merge conflict in %s",
1124 + output(o, 1, "CONFLICT (%s): Merge conflict in %s",
1125 reason, path);
1126
1127 if (index_only)
@@ -1146,22 +1142,21 @@ static int process_entry(const char *path, struct stage_data *entry,
1142 return clean_merge;
1143 }
1144
1149 -int merge_trees(struct tree *head,
1145 +int merge_trees(struct merge_options *o,
1146 + struct tree *head,
1147 struct tree *merge,
1148 struct tree *common,
1152 - const char *branch1,
1153 - const char *branch2,
1149 struct tree **result)
1150 {
1151 int code, clean;
1152
1158 - if (subtree_merge) {
1153 + if (o->subtree_merge) {
1154 merge = shift_tree_object(head, merge);
1155 common = shift_tree_object(head, common);
1156 }
1157
1158 if (sha_eq(common->object.sha1, merge->object.sha1)) {
1164 - output(0, "Already uptodate!");
1159 + output(o, 0, "Already uptodate!");
1160 *result = head;
1161 return 1;
1162 }
@@ -1182,15 +1177,14 @@ int merge_trees(struct tree *head,
1177 get_files_dirs(merge);
1178
1179 entries = get_unmerged();
1185 - re_head = get_renames(head, common, head, merge, entries);
1186 - re_merge = get_renames(merge, common, head, merge, entries);
1187 - clean = process_renames(re_head, re_merge,
1188 - branch1, branch2);
1180 + re_head = get_renames(o, head, common, head, merge, entries);
1181 + re_merge = get_renames(o, merge, common, head, merge, entries);
1182 + clean = process_renames(o, re_head, re_merge);
1183 for (i = 0; i < entries->nr; i++) {
1184 const char *path = entries->items[i].string;
1185 struct stage_data *e = entries->items[i].util;
1186 if (!e->processed
1193 - && !process_entry(path, e, branch1, branch2))
1187 + && !process_entry(o, path, e))
1188 clean = 0;
1189 }
1190
@@ -1203,7 +1197,7 @@ int merge_trees(struct tree *head,
1197 clean = 1;
1198
1199 if (index_only)
1206 - *result = write_tree_from_memory();
1200 + *result = write_tree_from_memory(o);
1201
1202 return clean;
1203 }
@@ -1223,10 +1217,9 @@ static struct commit_list *reverse_commit_list(struct commit_list *list)
1217 * Merge the commits h1 and h2, return the resulting virtual
1218 * commit object and a flag indicating the cleanness of the merge.
1219 */
1226 -int merge_recursive(struct commit *h1,
1220 +int merge_recursive(struct merge_options *o,
1221 + struct commit *h1,
1222 struct commit *h2,
1228 - const char *branch1,
1229 - const char *branch2,
1223 struct commit_list *ca,
1224 struct commit **result)
1225 {
@@ -1235,8 +1228,8 @@ int merge_recursive(struct commit *h1,
1228 struct tree *mrtree = mrtree;
1229 int clean;
1230
1238 - if (show(4)) {
1239 - output(4, "Merging:");
1231 + if (show(o, 4)) {
1232 + output(o, 4, "Merging:");
1233 output_commit_title(h1);
1234 output_commit_title(h2);
1235 }
@@ -1246,8 +1239,8 @@ int merge_recursive(struct commit *h1,
1239 ca = reverse_commit_list(ca);
1240 }
1241
1249 - if (show(5)) {
1250 - output(5, "found %u common ancestor(s):", commit_list_count(ca));
1242 + if (show(o, 5)) {
1243 + output(o, 5, "found %u common ancestor(s):", commit_list_count(ca));
1244 for (iter = ca; iter; iter = iter->next)
1245 output_commit_title(iter->item);
1246 }
@@ -1264,6 +1257,7 @@ int merge_recursive(struct commit *h1,
1257 }
1258
1259 for (iter = ca; iter; iter = iter->next) {
1260 + const char *saved_b1, *saved_b2;
1261 call_depth++;
1262 /*
1263 * When the merge fails, the result contains files
@@ -1273,11 +1267,14 @@ int merge_recursive(struct commit *h1,
1267 * "conflicts" were already resolved.
1268 */
1269 discard_cache();
1276 - merge_recursive(merged_common_ancestors, iter->item,
1277 - "Temporary merge branch 1",
1278 - "Temporary merge branch 2",
1279 - NULL,
1280 - &merged_common_ancestors);
1270 + saved_b1 = o->branch1;
1271 + saved_b2 = o->branch2;
1272 + o->branch1 = "Temporary merge branch 1";
1273 + o->branch2 = "Temporary merge branch 2";
1274 + merge_recursive(o, merged_common_ancestors, iter->item,
1275 + NULL, &merged_common_ancestors);
1276 + o->branch1 = saved_b1;
1277 + o->branch2 = saved_b2;
1278 call_depth--;
1279
1280 if (!merged_common_ancestors)
@@ -1291,8 +1288,8 @@ int merge_recursive(struct commit *h1,
1288 } else
1289 index_only = 1;
1290
1294 - clean = merge_trees(h1->tree, h2->tree, merged_common_ancestors->tree,
1295 - branch1, branch2, &mrtree);
1291 + clean = merge_trees(o, h1->tree, h2->tree, merged_common_ancestors->tree,
1292 + &mrtree);
1293
1294 if (index_only) {
1295 *result = make_virtual_commit(mrtree, "merged tree");
@@ -1319,35 +1316,33 @@ static struct commit *get_ref(const unsigned char *sha1, const char *name)
1316 return (struct commit *)object;
1317 }
1318
1322 -int merge_recursive_generic(const char **base_list,
1323 - const unsigned char *head_sha1, const char *head_name,
1324 - const unsigned char *next_sha1, const char *next_name)
1319 +int merge_recursive_generic(struct merge_options *o,
1320 + const unsigned char *head,
1321 + const unsigned char *merge,
1322 + int num_base_list,
1323 + const unsigned char **base_list,
1324 + struct commit **result)
1325 {
1326 int clean, index_fd;
1327 struct lock_file *lock = xcalloc(1, sizeof(struct lock_file));
1328 - struct commit *result;
1329 - struct commit *head_commit = get_ref(head_sha1, head_name);
1330 - struct commit *next_commit = get_ref(next_sha1, next_name);
1328 + struct commit *head_commit = get_ref(head, o->branch1);
1329 + struct commit *next_commit = get_ref(merge, o->branch2);
1330 struct commit_list *ca = NULL;
1331
1332 if (base_list) {
1333 int i;
1335 - for (i = 0; base_list[i]; ++i) {
1336 - unsigned char sha[20];
1334 + for (i = 0; i < num_base_list; ++i) {
1335 struct commit *base;
1338 - if (get_sha1(base_list[i], sha))
1339 - return error("Could not resolve ref '%s'",
1340 - base_list[i]);
1341 - if (!(base = get_ref(sha, base_list[i])))
1336 + if (!(base = get_ref(base_list[i], sha1_to_hex(base_list[i]))))
1337 return error("Could not parse object '%s'",
1343 - base_list[i]);
1338 + sha1_to_hex(base_list[i]));
1339 commit_list_insert(base, &ca);
1340 }
1341 }
1342
1343 index_fd = hold_locked_index(lock, 1);
1349 - clean = merge_recursive(head_commit, next_commit,
1350 - head_name, next_name, ca, &result);
1344 + clean = merge_recursive(o, head_commit, next_commit, ca,
1345 + result);
1346 if (active_cache_changed &&
1347 (write_cache(index_fd, active_cache, active_nr) ||
1348 commit_locked_index(lock)))
@@ -1356,29 +1351,35 @@ int merge_recursive_generic(const char **base_list,
1351 return clean ? 0 : 1;
1352 }
1353
1359 -int merge_recursive_config(const char *var, const char *value, void *cb)
1354 +static int merge_recursive_config(const char *var, const char *value, void *cb)
1355 {
1356 + struct merge_options *o = cb;
1357 if (!strcasecmp(var, "merge.verbosity")) {
1362 - merge_recursive_verbosity = git_config_int(var, value);
1358 + o->verbosity = git_config_int(var, value);
1359 return 0;
1360 }
1361 if (!strcasecmp(var, "diff.renamelimit")) {
1366 - diff_rename_limit = git_config_int(var, value);
1362 + o->diff_rename_limit = git_config_int(var, value);
1363 return 0;
1364 }
1365 if (!strcasecmp(var, "merge.renamelimit")) {
1370 - merge_rename_limit = git_config_int(var, value);
1366 + o->merge_rename_limit = git_config_int(var, value);
1367 return 0;
1368 }
1369 return git_default_config(var, value, cb);
1370 }
1371
1376 -void merge_recursive_setup(int is_subtree_merge)
1372 +void init_merge_options(struct merge_options *o)
1373 {
1374 + memset(o, 0, sizeof(struct merge_options));
1375 + o->verbosity = 2;
1376 + o->buffer_output = 1;
1377 + o->diff_rename_limit = -1;
1378 + o->merge_rename_limit = -1;
1379 + git_config(merge_recursive_config, o);
1380 if (getenv("GIT_MERGE_VERBOSITY"))
1379 - merge_recursive_verbosity =
1381 + o->verbosity =
1382 strtol(getenv("GIT_MERGE_VERBOSITY"), NULL, 10);
1381 - if (merge_recursive_verbosity >= 5)
1382 - buffer_output = 0;
1383 - subtree_merge = is_subtree_merge;
1383 + if (o->verbosity >= 5)
1384 + o->buffer_output = 0;
1385 }
merge-recursive.h
+29 -13
@@ -1,26 +1,42 @@
1 #ifndef MERGE_RECURSIVE_H
2 #define MERGE_RECURSIVE_H
3
4 -int merge_recursive(struct commit *h1,
4 +struct merge_options {
5 + const char *branch1;
6 + const char *branch2;
7 + unsigned subtree_merge : 1;
8 + unsigned buffer_output : 1;
9 + int verbosity;
10 + int diff_rename_limit;
11 + int merge_rename_limit;
12 +};
13 +
14 +/* merge_trees() but with recursive ancestor consolidation */
15 +int merge_recursive(struct merge_options *o,
16 + struct commit *h1,
17 struct commit *h2,
6 - const char *branch1,
7 - const char *branch2,
18 struct commit_list *ancestors,
19 struct commit **result);
20
11 -int merge_trees(struct tree *head,
21 +/* rename-detecting three-way merge, no recursion */
22 +int merge_trees(struct merge_options *o,
23 + struct tree *head,
24 struct tree *merge,
25 struct tree *common,
14 - const char *branch1,
15 - const char *branch2,
26 struct tree **result);
17 -extern int merge_recursive_generic(const char **base_list,
18 - const unsigned char *head_sha1, const char *head_name,
19 - const unsigned char *next_sha1, const char *next_name);
20 -int merge_recursive_config(const char *var, const char *value, void *cb);
21 -void merge_recursive_setup(int is_subtree_merge);
22 -struct tree *write_tree_from_memory(void);
27
24 -extern int merge_recursive_verbosity;
28 +/*
29 + * "git-merge-recursive" can be fed trees; wrap them into
30 + * virtual commits and call merge_recursive() proper.
31 + */
32 +int merge_recursive_generic(struct merge_options *o,
33 + const unsigned char *head,
34 + const unsigned char *merge,
35 + int num_ca,
36 + const unsigned char **ca,
37 + struct commit **result);
38 +
39 +void init_merge_options(struct merge_options *o);
40 +struct tree *write_tree_from_memory(struct merge_options *o);
41
42 #endif