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(¤t_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(¤t_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(¤t_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(¤t_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