@matheusbsbs / matheus-bagliano / commits / 18668f5319
Fork 0

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;