builtin-merge: avoid run_command_v_opt() for recursive and subtree
The try_merge_strategy() function always ran the strategy in a separate process, though this is not always necessary. The recursive and subtree strategy can be called without a fork(). This patch adds a check, and calls recursive in the same process without wasting resources. Signed-off-by: Johannes Schindelin <johannes.schindelin@gmx.de> Signed-off-by: Miklos Vajna <vmiklos@frugalware.org> Signed-off-by: Junio C Hamano <gitster@pobox.com>
Miklos Vajna committed
Aug 28, 2008 at 15:43 UTC
18668f5319b079cce29e19817bc352b1413e0908
1 file changed
+63
-29
builtin-merge.c
+63
-29
@@ -23,6 +23,7 @@
23
#include "color.h"
24
#include "rerere.h"
25
#include "help.h"
26
+#include "merge-recursive.h"
27
28
#define DEFAULT_TWOHEAD (1<<0)
29
#define DEFAULT_OCTOPUS (1<<1)
@@ -545,28 +546,64 @@ static int try_merge_strategy(const char *strategy, struct commit_list *common,
546
struct commit_list *j;
547
struct strbuf buf;
548
548
- args = xmalloc((4 + commit_list_count(common) +
549
- commit_list_count(remoteheads)) * sizeof(char *));
550
- strbuf_init(&buf, 0);
551
- strbuf_addf(&buf, "merge-%s", strategy);
552
- args[i++] = buf.buf;
553
- for (j = common; j; j = j->next)
554
- args[i++] = xstrdup(sha1_to_hex(j->item->object.sha1));
555
- args[i++] = "--";
556
- args[i++] = head_arg;
557
- for (j = remoteheads; j; j = j->next)
558
- args[i++] = xstrdup(sha1_to_hex(j->item->object.sha1));
559
- args[i] = NULL;
560
- ret = run_command_v_opt(args, RUN_GIT_CMD);
561
- strbuf_release(&buf);
562
- i = 1;
563
- for (j = common; j; j = j->next)
564
- free((void *)args[i++]);
565
- i += 2;
566
- for (j = remoteheads; j; j = j->next)
567
- free((void *)args[i++]);
568
- free(args);
569
- return -ret;
549
+ if (!strcmp(strategy, "recursive") || !strcmp(strategy, "subtree")) {
550
+ int clean;
551
+ struct commit *result;
552
+ struct lock_file *lock = xcalloc(1, sizeof(struct lock_file));
553
+ int index_fd;
554
+ struct commit_list *reversed = NULL;
555
+ struct merge_options o;
556
+
557
+ if (remoteheads->next) {
558
+ error("Not handling anything other than two heads merge.");
559
+ return 2;
560
+ }
561
+
562
+ init_merge_options(&o);
563
+ if (!strcmp(strategy, "subtree"))
564
+ o.subtree_merge = 1;
565
+
566
+ o.branch1 = head_arg;
567
+ o.branch2 = remoteheads->item->util;
568
+
569
+ for (j = common; j; j = j->next)
570
+ commit_list_insert(j->item, &reversed);
571
+
572
+ index_fd = hold_locked_index(lock, 1);
573
+ clean = merge_recursive(&o, lookup_commit(head),
574
+ remoteheads->item, reversed, &result);
575
+ if (active_cache_changed &&
576
+ (write_cache(index_fd, active_cache, active_nr) ||
577
+ commit_locked_index(lock)))
578
+ die ("unable to write %s", get_index_file());
579
+ return clean ? 0 : 1;
580
+ } else {
581
+ args = xmalloc((4 + commit_list_count(common) +
582
+ commit_list_count(remoteheads)) * sizeof(char *));
583
+ strbuf_init(&buf, 0);
584
+ strbuf_addf(&buf, "merge-%s", strategy);
585
+ args[i++] = buf.buf;
586
+ for (j = common; j; j = j->next)
587
+ args[i++] = xstrdup(sha1_to_hex(j->item->object.sha1));
588
+ args[i++] = "--";
589
+ args[i++] = head_arg;
590
+ for (j = remoteheads; j; j = j->next)
591
+ args[i++] = xstrdup(sha1_to_hex(j->item->object.sha1));
592
+ args[i] = NULL;
593
+ ret = run_command_v_opt(args, RUN_GIT_CMD);
594
+ strbuf_release(&buf);
595
+ i = 1;
596
+ for (j = common; j; j = j->next)
597
+ free((void *)args[i++]);
598
+ i += 2;
599
+ for (j = remoteheads; j; j = j->next)
600
+ free((void *)args[i++]);
601
+ free(args);
602
+ discard_cache();
603
+ if (read_cache() < 0)
604
+ die("failed to read the cache");
605
+ return -ret;
606
+ }
607
}
608
609
static void count_diff_files(struct diff_queue_struct *q,
@@ -777,10 +814,6 @@ static int evaluate_result(void)
814
int cnt = 0;
815
struct rev_info rev;
816
780
- discard_cache();
781
- if (read_cache() < 0)
782
- die("failed to read the cache");
783
-
817
/* Check how many files differ. */
818
init_revisions(&rev, "");
819
setup_revisions(0, NULL, &rev, NULL);
@@ -914,12 +947,14 @@ int cmd_merge(int argc, const char **argv, const char *prefix)
947
948
for (i = 0; i < argc; i++) {
949
struct object *o;
950
+ struct commit *commit;
951
952
o = peel_to_type(argv[i], 0, NULL, OBJ_COMMIT);
953
if (!o)
954
die("%s - not something we can merge", argv[i]);
921
- remotes = &commit_list_insert(lookup_commit(o->sha1),
922
- remotes)->next;
955
+ commit = lookup_commit(o->sha1);
956
+ commit->util = (void *)argv[i];
957
+ remotes = &commit_list_insert(commit, remotes)->next;
958
959
strbuf_addf(&buf, "GITHEAD_%s", sha1_to_hex(o->sha1));
960
setenv(buf.buf, argv[i], 1);
@@ -1113,7 +1148,6 @@ int cmd_merge(int argc, const char **argv, const char *prefix)
1148
}
1149
1150
/* Automerge succeeded. */
1116
- discard_cache();
1151
write_tree_trivial(result_tree);
1152
automerge_was_ok = 1;
1153
break;