From patchwork Mon Oct 5 12:26:36 2020 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Alban Gruin X-Patchwork-Id: 11816579 Return-Path: Received: from mail.kernel.org (pdx-korg-mail-1.web.codeaurora.org [172.30.200.123]) by pdx-korg-patchwork-2.web.codeaurora.org (Postfix) with ESMTP id 5DEE713B2 for ; Mon, 5 Oct 2020 12:27:45 +0000 (UTC) Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by mail.kernel.org (Postfix) with ESMTP id 3CC342085B for ; Mon, 5 Oct 2020 12:27:45 +0000 (UTC) Authentication-Results: mail.kernel.org; dkim=pass (2048-bit key) header.d=gmail.com header.i=@gmail.com header.b="foDvYiFP" Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1726160AbgJEM1m (ORCPT ); Mon, 5 Oct 2020 08:27:42 -0400 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:48730 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1725891AbgJEM1k (ORCPT ); Mon, 5 Oct 2020 08:27:40 -0400 Received: from mail-wr1-x436.google.com (mail-wr1-x436.google.com [IPv6:2a00:1450:4864:20::436]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id 5824FC0613CE for ; Mon, 5 Oct 2020 05:27:38 -0700 (PDT) Received: by mail-wr1-x436.google.com with SMTP id k10so9333517wru.6 for ; Mon, 05 Oct 2020 05:27:38 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20161025; h=from:to:cc:subject:date:message-id:in-reply-to:references :mime-version:content-transfer-encoding; bh=bEoBMi9MN/2sJT0ee3kBf3jUbUNW5KYMWA5wIPZ+zh4=; b=foDvYiFPWJ6yDqohCx0s+n1dafikCu+iCACynZCx7b8boGbDLP7tKDfdrkK0M8JjTz Wyp0HEIRgYHIe4Sux4Wo1Gl1fBjXJCxy5irTdm7X6ipgMsz1k07iuwVsbZqR2NR4l5z2 iPwxUYJu++aIZlPPfK6I9RmjisSb6RhpG8uEarfzDd/DbYSiMNAAQvV1VxuqdHrg2FN2 8GtYZeYuuCZQ/b9by21Xdndsj23UE4WJdxXYbMCx/Rj3yatPwdOYS5IQv0BMlAG4ls/o mM4R8WM3e5mvUTJvtfBHjUdkn5i6Fz6H8pfS0Ji40WXvUf6iyWnVWhXhRBW5Rf49UBX1 iyFA== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-gm-message-state:from:to:cc:subject:date:message-id:in-reply-to :references:mime-version:content-transfer-encoding; bh=bEoBMi9MN/2sJT0ee3kBf3jUbUNW5KYMWA5wIPZ+zh4=; b=VtK6Jla0cavJAWFb9ONBqwONHGYIQHEhRY8XnSg3BsEDwl77eVJjuVnrm6v7UDiEyr T8hMsm7IwlUzbCUUQNzhEHTtQvBCapmuHcWWcCvYQ6P0GiThKJsiHLToAFT18HmchvwY xnTOngSt/+uz4lsvN+zkDeYHMGIduOu0abZnmBmVYcjbJIjRydNLXhmrsNsXt/DHdmSn s2mx+EiqUca1D322Zxsumtye3DEeS9tWh+o57C7d2u/WV36exCt8taz3mUbD/1wiAJ3/ Wfv64TFQ2GImX0VDkIJJuY0egBxswkwVoCJb09M0MDiJnNCzVYXwkjC8Wq4hpSoekzKI skrw== X-Gm-Message-State: AOAM530U5Ux0HI4sg2sCSJvV1UDLWRB6h0zor+mknDY3DBAJImGicZcV b1aSlsFaje8Kl6p2uZKENbFPZHULl1c= X-Google-Smtp-Source: ABdhPJy4/btW/0p3SlPvlJHhIM5bLJEQPsmz4wwZyTHQK5JviPaSTu6e3CX27qnET6qVFJrSzLoYpA== X-Received: by 2002:a5d:458a:: with SMTP id p10mr16986803wrq.282.1601900856533; Mon, 05 Oct 2020 05:27:36 -0700 (PDT) Received: from ylate.lan (atoulouse-654-1-293-21.w86-199.abo.wanadoo.fr. [86.199.76.21]) by smtp.googlemail.com with ESMTPSA id n2sm13270400wma.29.2020.10.05.05.27.35 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Mon, 05 Oct 2020 05:27:35 -0700 (PDT) From: Alban Gruin To: git@vger.kernel.org Cc: Junio C Hamano , phillip.wood@dunelm.org.uk, Alban Gruin Subject: [PATCH v3 01/11] t6027: modernise tests Date: Mon, 5 Oct 2020 14:26:36 +0200 Message-Id: <20201005122646.27994-2-alban.gruin@gmail.com> X-Mailer: git-send-email 2.20.1 In-Reply-To: <20201005122646.27994-1-alban.gruin@gmail.com> References: <20200901105705.6059-1-alban.gruin@gmail.com> <20201005122646.27994-1-alban.gruin@gmail.com> MIME-Version: 1.0 Precedence: bulk List-ID: X-Mailing-List: git@vger.kernel.org Some tests in t6027 uses a if/then/else to check if a command failed or not, but we have the `test_must_fail' function to do it correctly for us nowadays. Signed-off-by: Alban Gruin --- t/t6407-merge-binary.sh | 27 ++++++--------------------- 1 file changed, 6 insertions(+), 21 deletions(-) diff --git a/t/t6407-merge-binary.sh b/t/t6407-merge-binary.sh index 4e6c7cb77e..071d3f7343 100755 --- a/t/t6407-merge-binary.sh +++ b/t/t6407-merge-binary.sh @@ -5,7 +5,6 @@ test_description='ask merge-recursive to merge binary files' . ./test-lib.sh test_expect_success setup ' - cat "$TEST_DIRECTORY"/test-binary-1.png >m && git add m && git ls-files -s | sed -e "s/ 0 / 1 /" >E1 && @@ -35,33 +34,19 @@ test_expect_success setup ' ' test_expect_success resolve ' - rm -f a* m* && git reset --hard anchor && - - if git merge -s resolve master - then - echo Oops, should not have succeeded - false - else - git ls-files -s >current - test_cmp expect current - fi + test_must_fail git merge -s resolve master && + git ls-files -s >current && + test_cmp expect current ' test_expect_success recursive ' - rm -f a* m* && git reset --hard anchor && - - if git merge -s recursive master - then - echo Oops, should not have succeeded - false - else - git ls-files -s >current - test_cmp expect current - fi + test_must_fail git merge -s recursive master && + git ls-files -s >current && + test_cmp expect current ' test_done From patchwork Mon Oct 5 12:26:37 2020 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Alban Gruin X-Patchwork-Id: 11816573 Return-Path: Received: from mail.kernel.org (pdx-korg-mail-1.web.codeaurora.org [172.30.200.123]) by pdx-korg-patchwork-2.web.codeaurora.org (Postfix) with ESMTP id 99BBB112E for ; Mon, 5 Oct 2020 12:27:43 +0000 (UTC) Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by mail.kernel.org (Postfix) with ESMTP id 7331F208A9 for ; Mon, 5 Oct 2020 12:27:43 +0000 (UTC) Authentication-Results: mail.kernel.org; dkim=pass (2048-bit key) header.d=gmail.com header.i=@gmail.com header.b="bwLESe+M" Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1726165AbgJEM1m (ORCPT ); Mon, 5 Oct 2020 08:27:42 -0400 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:48742 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1726131AbgJEM1l (ORCPT ); Mon, 5 Oct 2020 08:27:41 -0400 Received: from mail-wr1-x443.google.com (mail-wr1-x443.google.com [IPv6:2a00:1450:4864:20::443]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id 9EABAC0613A7 for ; Mon, 5 Oct 2020 05:27:40 -0700 (PDT) Received: by mail-wr1-x443.google.com with SMTP id n15so3581407wrq.2 for ; Mon, 05 Oct 2020 05:27:40 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20161025; h=from:to:cc:subject:date:message-id:in-reply-to:references :mime-version:content-transfer-encoding; bh=zCiNMbrY9/lLS+3HqGIBypmp7ghNhzeW8cpIr2CkH/0=; b=bwLESe+M7xDU77iH1KM4xJy6ub8urOBA31MvYxfffXo4wR8yY2n7xWXxcrI8lgvBGo LBZ0ZN0UI6KF0WGIv5EajvbVCUcX6rQSo20w9aZpiXcWphsCKs9iRegxOqB6zzyal8g+ OvA+KQXlBpHcd6xVEj/B8nCt+Mff3kg7jkaLmP7TRFnKSJlK8kXnxbB/JcIs2cmAzF1i 01LhTbSLBQ8isL3214uhy5TNGbe5hju6rO4gnPibcqXjnuVsXzKDtOcSI9olyz0pFAUp Do4Wta4h6dBvgWx8wX7SuaBjtaFwQxwfVB2ws+NkbfyH7JjcGypjWEtADBoZATFlpf9B 0tXg== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-gm-message-state:from:to:cc:subject:date:message-id:in-reply-to :references:mime-version:content-transfer-encoding; bh=zCiNMbrY9/lLS+3HqGIBypmp7ghNhzeW8cpIr2CkH/0=; b=RNuPXIDxcwLwtQv1nD93QALs9j727aoWbdFd/1Ud1ob8vJkzxXnzl+XJ8OpPYLKLhx r8EgN0a3UMRTlH6lVj4kz3MvFFgm1a72lgI5t7sYSRLCFIrn3zx9cEXEeG8QSFGhXMXl PaClnitnyyB1I/ZluDC/6xVyrdxit+3JxDxEsjojmaq0hhajmkJyyJa9XofQcSRpClNA i/ftdjcT2JeIgct1y+2Ln+TeOsAlrTx3vJnRzUx9mHc01tW58m72to8qZ2b82Ao3HC15 YMDfZ4XSSlOitk+nS2D3tDsK+qSjvLBRFvXamEGukFEJ5V2/7SgnbNnZVzpew2Jwz85R x98Q== X-Gm-Message-State: AOAM5306z+qio52luoRFEFwikTCwgC9exo4+L0gbeFAV2CtoBH5gleDx 3HPoMGTCmW7RO+NYVjwHveU7LSG7FxA= X-Google-Smtp-Source: ABdhPJwBjYFomlxAui++anWxK4qbTEuVro0y+ddlD2G87UDdh2jBHXdlWJGGLWfL9Hw/Yn8IPi89gA== X-Received: by 2002:adf:ee01:: with SMTP id y1mr18074139wrn.2.1601900858516; Mon, 05 Oct 2020 05:27:38 -0700 (PDT) Received: from ylate.lan (atoulouse-654-1-293-21.w86-199.abo.wanadoo.fr. [86.199.76.21]) by smtp.googlemail.com with ESMTPSA id n2sm13270400wma.29.2020.10.05.05.27.36 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Mon, 05 Oct 2020 05:27:37 -0700 (PDT) From: Alban Gruin To: git@vger.kernel.org Cc: Junio C Hamano , phillip.wood@dunelm.org.uk, Alban Gruin Subject: [PATCH v3 02/11] merge-one-file: rewrite in C Date: Mon, 5 Oct 2020 14:26:37 +0200 Message-Id: <20201005122646.27994-3-alban.gruin@gmail.com> X-Mailer: git-send-email 2.20.1 In-Reply-To: <20201005122646.27994-1-alban.gruin@gmail.com> References: <20200901105705.6059-1-alban.gruin@gmail.com> <20201005122646.27994-1-alban.gruin@gmail.com> MIME-Version: 1.0 Precedence: bulk List-ID: X-Mailing-List: git@vger.kernel.org This rewrites `git merge-one-file' from shell to C. This port is not completely straightforward: to save precious cycles by avoiding reading and flushing the index repeatedly, write temporary files when an operation can be performed in-memory, or allow other function to use the rewrite without forking nor worrying about the index, the calls to external processes are replaced by calls to functions in libgit.a: - calls to `update-index --add --cacheinfo' are replaced by calls to add_cache_entry(); - calls to `update-index --remove' are replaced by calls to remove_file_from_cache(); - calls to `checkout-index -u -f' are replaced by calls to checkout_entry(); - calls to `unpack-file' and `merge-files' are replaced by calls to read_mmblob() and ll_merge(), respectively, to merge files in-memory; - calls to `checkout-index -f --stage=2' are replaced by calls to cache_file_exists(); - calls to `update-index' are replaced by calls to add_file_to_cache(). The bulk of the rewrite is done in a new file in libgit.a, merge-strategies.c. This will enable the resolve and octopus strategies to directly call it instead of forking. This also fixes a bug present in the original script: instead of checking if a _regular_ file exists when a file exists in the branch to merge, but not in our branch, the rewritten version checks if a file of any kind (ie. a directory, ...) exists. This fixes the tests t6035.14, where the branch to merge had a new file, `a/b', but our branch had a directory there; it should have failed because a directory exists, but it did not because there was no regular file called `a/b'. This test is now marked as successful. Signed-off-by: Alban Gruin --- Makefile | 3 +- builtin.h | 1 + builtin/merge-one-file.c | 92 ++++++++++++++ git-merge-one-file.sh | 167 ------------------------- git.c | 1 + merge-strategies.c | 214 ++++++++++++++++++++++++++++++++ merge-strategies.h | 13 ++ t/t6415-merge-dir-to-symlink.sh | 2 +- 8 files changed, 324 insertions(+), 169 deletions(-) create mode 100644 builtin/merge-one-file.c delete mode 100755 git-merge-one-file.sh create mode 100644 merge-strategies.c create mode 100644 merge-strategies.h diff --git a/Makefile b/Makefile index de53954590..6dfdb33cb2 100644 --- a/Makefile +++ b/Makefile @@ -601,7 +601,6 @@ SCRIPT_SH += git-bisect.sh SCRIPT_SH += git-difftool--helper.sh SCRIPT_SH += git-filter-branch.sh SCRIPT_SH += git-merge-octopus.sh -SCRIPT_SH += git-merge-one-file.sh SCRIPT_SH += git-merge-resolve.sh SCRIPT_SH += git-mergetool.sh SCRIPT_SH += git-quiltimport.sh @@ -909,6 +908,7 @@ LIB_OBJS += match-trees.o LIB_OBJS += mem-pool.o LIB_OBJS += merge-blobs.o LIB_OBJS += merge-recursive.o +LIB_OBJS += merge-strategies.o LIB_OBJS += merge.o LIB_OBJS += mergesort.o LIB_OBJS += midx.o @@ -1094,6 +1094,7 @@ BUILTIN_OBJS += builtin/mailsplit.o BUILTIN_OBJS += builtin/merge-base.o BUILTIN_OBJS += builtin/merge-file.o BUILTIN_OBJS += builtin/merge-index.o +BUILTIN_OBJS += builtin/merge-one-file.o BUILTIN_OBJS += builtin/merge-ours.o BUILTIN_OBJS += builtin/merge-recursive.o BUILTIN_OBJS += builtin/merge-tree.o diff --git a/builtin.h b/builtin.h index 53fb290963..4d2cd78856 100644 --- a/builtin.h +++ b/builtin.h @@ -178,6 +178,7 @@ int cmd_merge_base(int argc, const char **argv, const char *prefix); int cmd_merge_index(int argc, const char **argv, const char *prefix); int cmd_merge_ours(int argc, const char **argv, const char *prefix); int cmd_merge_file(int argc, const char **argv, const char *prefix); +int cmd_merge_one_file(int argc, const char **argv, const char *prefix); int cmd_merge_recursive(int argc, const char **argv, const char *prefix); int cmd_merge_tree(int argc, const char **argv, const char *prefix); int cmd_mktag(int argc, const char **argv, const char *prefix); diff --git a/builtin/merge-one-file.c b/builtin/merge-one-file.c new file mode 100644 index 0000000000..598338ba16 --- /dev/null +++ b/builtin/merge-one-file.c @@ -0,0 +1,92 @@ +/* + * Builtin "git merge-one-file" + * + * Copyright (c) 2020 Alban Gruin + * + * Based on git-merge-one-file.sh, written by Linus Torvalds. + * + * This is the git per-file merge utility, called with + * + * argv[1] - original file SHA1 (or empty) + * argv[2] - file in branch1 SHA1 (or empty) + * argv[3] - file in branch2 SHA1 (or empty) + * argv[4] - pathname in repository + * argv[5] - original file mode (or empty) + * argv[6] - file in branch1 mode (or empty) + * argv[7] - file in branch2 mode (or empty) + * + * Handle some trivial cases. The _really_ trivial cases have been + * handled already by git read-tree, but that one doesn't do any merges + * that might change the tree layout. + */ + +#define USE_THE_INDEX_COMPATIBILITY_MACROS +#include "cache.h" +#include "builtin.h" +#include "lockfile.h" +#include "merge-strategies.h" + +static const char builtin_merge_one_file_usage[] = + "git merge-one-file " + " \n\n" + "Blob ids and modes should be empty for missing files."; + +static int read_mode(const char *name, const char *arg, unsigned int *mode) +{ + char *last; + int ret = 0; + + *mode = strtol(arg, &last, 8); + + if (*last) + ret = error(_("invalid '%s' mode: expected nothing, got '%c'"), name, *last); + else if (!(S_ISREG(*mode) || S_ISDIR(*mode) || S_ISLNK(*mode))) + ret = error(_("invalid '%s' mode: %o"), name, *mode); + + return ret; +} + +int cmd_merge_one_file(int argc, const char **argv, const char *prefix) +{ + struct object_id orig_blob, our_blob, their_blob, + *p_orig_blob = NULL, *p_our_blob = NULL, *p_their_blob = NULL; + unsigned int orig_mode = 0, our_mode = 0, their_mode = 0, ret = 0; + struct lock_file lock = LOCK_INIT; + + if (argc != 8) + usage(builtin_merge_one_file_usage); + + if (read_cache() < 0) + die("invalid index"); + + hold_locked_index(&lock, LOCK_DIE_ON_ERROR); + + if (!get_oid(argv[1], &orig_blob)) { + p_orig_blob = &orig_blob; + ret = read_mode("orig", argv[5], &orig_mode); + } + + if (!get_oid(argv[2], &our_blob)) { + p_our_blob = &our_blob; + ret = read_mode("our", argv[6], &our_mode); + } + + if (!get_oid(argv[3], &their_blob)) { + p_their_blob = &their_blob; + ret = read_mode("their", argv[7], &their_mode); + } + + if (ret) + return ret; + + ret = merge_strategies_one_file(the_repository, + p_orig_blob, p_our_blob, p_their_blob, argv[4], + orig_mode, our_mode, their_mode); + + if (ret) { + rollback_lock_file(&lock); + return !!ret; + } + + return write_locked_index(&the_index, &lock, COMMIT_LOCK); +} diff --git a/git-merge-one-file.sh b/git-merge-one-file.sh deleted file mode 100755 index f6d9852d2f..0000000000 --- a/git-merge-one-file.sh +++ /dev/null @@ -1,167 +0,0 @@ -#!/bin/sh -# -# Copyright (c) Linus Torvalds, 2005 -# -# This is the git per-file merge script, called with -# -# $1 - original file SHA1 (or empty) -# $2 - file in branch1 SHA1 (or empty) -# $3 - file in branch2 SHA1 (or empty) -# $4 - pathname in repository -# $5 - original file mode (or empty) -# $6 - file in branch1 mode (or empty) -# $7 - file in branch2 mode (or empty) -# -# Handle some trivial cases.. The _really_ trivial cases have -# been handled already by git read-tree, but that one doesn't -# do any merges that might change the tree layout. - -USAGE=' ' -USAGE="$USAGE " -LONG_USAGE="usage: git merge-one-file $USAGE - -Blob ids and modes should be empty for missing files." - -SUBDIRECTORY_OK=Yes -. git-sh-setup -cd_to_toplevel -require_work_tree - -if test $# != 7 -then - echo "$LONG_USAGE" - exit 1 -fi - -case "${1:-.}${2:-.}${3:-.}" in -# -# Deleted in both or deleted in one and unchanged in the other -# -"$1.." | "$1.$1" | "$1$1.") - if { test -z "$6" && test "$5" != "$7"; } || - { test -z "$7" && test "$5" != "$6"; } - then - echo "ERROR: File $4 deleted on one branch but had its" >&2 - echo "ERROR: permissions changed on the other." >&2 - exit 1 - fi - - if test -n "$2" - then - echo "Removing $4" - else - # read-tree checked that index matches HEAD already, - # so we know we do not have this path tracked. - # there may be an unrelated working tree file here, - # which we should just leave unmolested. Make sure - # we do not have it in the index, though. - exec git update-index --remove -- "$4" - fi - if test -f "$4" - then - rm -f -- "$4" && - rmdir -p "$(expr "z$4" : 'z\(.*\)/')" 2>/dev/null || : - fi && - exec git update-index --remove -- "$4" - ;; - -# -# Added in one. -# -".$2.") - # the other side did not add and we added so there is nothing - # to be done, except making the path merged. - exec git update-index --add --cacheinfo "$6" "$2" "$4" - ;; -"..$3") - echo "Adding $4" - if test -f "$4" - then - echo "ERROR: untracked $4 is overwritten by the merge." >&2 - exit 1 - fi - git update-index --add --cacheinfo "$7" "$3" "$4" && - exec git checkout-index -u -f -- "$4" - ;; - -# -# Added in both, identically (check for same permissions). -# -".$3$2") - if test "$6" != "$7" - then - echo "ERROR: File $4 added identically in both branches," >&2 - echo "ERROR: but permissions conflict $6->$7." >&2 - exit 1 - fi - echo "Adding $4" - git update-index --add --cacheinfo "$6" "$2" "$4" && - exec git checkout-index -u -f -- "$4" - ;; - -# -# Modified in both, but differently. -# -"$1$2$3" | ".$2$3") - - case ",$6,$7," in - *,120000,*) - echo "ERROR: $4: Not merging symbolic link changes." >&2 - exit 1 - ;; - *,160000,*) - echo "ERROR: $4: Not merging conflicting submodule changes." >&2 - exit 1 - ;; - esac - - src1=$(git unpack-file $2) - src2=$(git unpack-file $3) - case "$1" in - '') - echo "Added $4 in both, but differently." - orig=$(git unpack-file $(git hash-object /dev/null)) - ;; - *) - echo "Auto-merging $4" - orig=$(git unpack-file $1) - ;; - esac - - git merge-file "$src1" "$orig" "$src2" - ret=$? - msg= - if test $ret != 0 || test -z "$1" - then - msg='content conflict' - ret=1 - fi - - # Create the working tree file, using "our tree" version from the - # index, and then store the result of the merge. - git checkout-index -f --stage=2 -- "$4" && cat "$src1" >"$4" || exit 1 - rm -f -- "$orig" "$src1" "$src2" - - if test "$6" != "$7" - then - if test -n "$msg" - then - msg="$msg, " - fi - msg="${msg}permissions conflict: $5->$6,$7" - ret=1 - fi - - if test $ret != 0 - then - echo "ERROR: $msg in $4" >&2 - exit 1 - fi - exec git update-index -- "$4" - ;; - -*) - echo "ERROR: $4: Not handling case $1 -> $2 -> $3" >&2 - ;; -esac -exit 1 diff --git a/git.c b/git.c index f1e8b56d99..a4d3f98094 100644 --- a/git.c +++ b/git.c @@ -540,6 +540,7 @@ static struct cmd_struct commands[] = { { "merge-file", cmd_merge_file, RUN_SETUP_GENTLY }, { "merge-index", cmd_merge_index, RUN_SETUP | NO_PARSEOPT }, { "merge-ours", cmd_merge_ours, RUN_SETUP | NO_PARSEOPT }, + { "merge-one-file", cmd_merge_one_file, RUN_SETUP | NEED_WORK_TREE | NO_PARSEOPT }, { "merge-recursive", cmd_merge_recursive, RUN_SETUP | NEED_WORK_TREE | NO_PARSEOPT }, { "merge-recursive-ours", cmd_merge_recursive, RUN_SETUP | NEED_WORK_TREE | NO_PARSEOPT }, { "merge-recursive-theirs", cmd_merge_recursive, RUN_SETUP | NEED_WORK_TREE | NO_PARSEOPT }, diff --git a/merge-strategies.c b/merge-strategies.c new file mode 100644 index 0000000000..bbe6f48698 --- /dev/null +++ b/merge-strategies.c @@ -0,0 +1,214 @@ +#include "cache.h" +#include "dir.h" +#include "ll-merge.h" +#include "merge-strategies.h" +#include "xdiff-interface.h" + +static int add_to_index_cacheinfo(struct index_state *istate, + unsigned int mode, + const struct object_id *oid, const char *path) +{ + struct cache_entry *ce; + int len, option; + + if (!verify_path(path, mode)) + return error(_("Invalid path '%s'"), path); + + len = strlen(path); + ce = make_empty_cache_entry(istate, len); + + oidcpy(&ce->oid, oid); + memcpy(ce->name, path, len); + ce->ce_flags = create_ce_flags(0); + ce->ce_namelen = len; + ce->ce_mode = create_ce_mode(mode); + if (assume_unchanged) + ce->ce_flags |= CE_VALID; + option = ADD_CACHE_OK_TO_ADD | ADD_CACHE_OK_TO_REPLACE; + if (add_index_entry(istate, ce, option)) + return error(_("%s: cannot add to the index"), path); + + return 0; +} + +static int checkout_from_index(struct index_state *istate, const char *path) +{ + struct checkout state = CHECKOUT_INIT; + struct cache_entry *ce; + + state.istate = istate; + state.force = 1; + state.base_dir = ""; + state.base_dir_len = 0; + + ce = index_file_exists(istate, path, strlen(path), 0); + if (checkout_entry(ce, &state, NULL, NULL) < 0) + return error(_("%s: cannot checkout file"), path); + return 0; +} + +static int merge_one_file_deleted(struct index_state *istate, + const struct object_id *orig_blob, + const struct object_id *our_blob, + const struct object_id *their_blob, const char *path, + unsigned int orig_mode, unsigned int our_mode, unsigned int their_mode) +{ + if ((our_blob && orig_mode != our_mode) || + (their_blob && orig_mode != their_mode)) + return error(_("File %s deleted on one branch but had its " + "permissions changed on the other."), path); + + if (our_blob) { + printf(_("Removing %s\n"), path); + + if (file_exists(path)) + remove_path(path); + } + + if (remove_file_from_index(istate, path)) + return error("%s: cannot remove from the index", path); + return 0; +} + +static int do_merge_one_file(struct index_state *istate, + const struct object_id *orig_blob, + const struct object_id *our_blob, + const struct object_id *their_blob, const char *path, + unsigned int orig_mode, unsigned int our_mode, unsigned int their_mode) +{ + int ret, i, dest; + ssize_t written; + mmbuffer_t result = {NULL, 0}; + mmfile_t mmfs[3]; + struct ll_merge_options merge_opts = {0}; + struct cache_entry *ce; + + if (our_mode == S_IFLNK || their_mode == S_IFLNK) + return error(_("%s: Not merging symbolic link changes."), path); + else if (our_mode == S_IFGITLINK || their_mode == S_IFGITLINK) + return error(_("%s: Not merging conflicting submodule changes."), path); + + read_mmblob(mmfs + 1, our_blob); + read_mmblob(mmfs + 2, their_blob); + + if (orig_blob) { + printf(_("Auto-merging %s\n"), path); + read_mmblob(mmfs + 0, orig_blob); + } else { + printf(_("Added %s in both, but differently.\n"), path); + read_mmblob(mmfs + 0, &null_oid); + } + + merge_opts.xdl_opts = XDL_MERGE_ZEALOUS_ALNUM; + ret = ll_merge(&result, path, + mmfs + 0, "orig", + mmfs + 1, "our", + mmfs + 2, "their", + istate, &merge_opts); + + for (i = 0; i < 3; i++) + free(mmfs[i].ptr); + + if (ret < 0) { + free(result.ptr); + return error(_("Failed to execute internal merge")); + } + + /* + * Create the working tree file, using "our tree" version from + * the index, and then store the result of the merge. + */ + ce = index_file_exists(istate, path, strlen(path), 0); + if (!ce) + BUG("file is not present in the cache?"); + + unlink(path); + if ((dest = open(path, O_WRONLY | O_CREAT, ce->ce_mode)) < 0) { + free(result.ptr); + return error_errno(_("failed to open file '%s'"), path); + } + + written = write_in_full(dest, result.ptr, result.size); + close(dest); + + free(result.ptr); + + if (written < 0) + return error_errno(_("failed to write to '%s'"), path); + + if (ret != 0 || !orig_blob) + ret = error(_("content conflict in %s"), path); + if (our_mode != their_mode) + return error(_("permission conflict: %o->%o,%o in %s"), + orig_mode, our_mode, their_mode, path); + if (ret) + return -1; + + return add_file_to_index(istate, path, 0); +} + +int merge_strategies_one_file(struct repository *r, + const struct object_id *orig_blob, + const struct object_id *our_blob, + const struct object_id *their_blob, const char *path, + unsigned int orig_mode, unsigned int our_mode, + unsigned int their_mode) +{ + if (orig_blob && + ((!their_blob && our_blob && oideq(orig_blob, our_blob)) || + (!our_blob && their_blob && oideq(orig_blob, their_blob)))) + /* Deleted in both or deleted in one and unchanged in the other. */ + return merge_one_file_deleted(r->index, + orig_blob, our_blob, their_blob, path, + orig_mode, our_mode, their_mode); + else if (!orig_blob && our_blob && !their_blob) { + /* + * Added in one. The other side did not add and we + * added so there is nothing to be done, except making + * the path merged. + */ + return add_to_index_cacheinfo(r->index, our_mode, our_blob, path); + } else if (!orig_blob && !our_blob && their_blob) { + printf(_("Adding %s\n"), path); + + if (file_exists(path)) + return error(_("untracked %s is overwritten by the merge."), path); + + if (add_to_index_cacheinfo(r->index, their_mode, their_blob, path)) + return -1; + return checkout_from_index(r->index, path); + } else if (!orig_blob && our_blob && their_blob && + oideq(our_blob, their_blob)) { + /* Added in both, identically (check for same permissions). */ + if (our_mode != their_mode) + return error(_("File %s added identically in both branches, " + "but permissions conflict %o->%o."), + path, our_mode, their_mode); + + printf(_("Adding %s\n"), path); + + if (add_to_index_cacheinfo(r->index, our_mode, our_blob, path)) + return -1; + return checkout_from_index(r->index, path); + } else if (our_blob && their_blob) + /* Modified in both, but differently. */ + return do_merge_one_file(r->index, + orig_blob, our_blob, their_blob, path, + orig_mode, our_mode, their_mode); + else { + char orig_hex[GIT_MAX_HEXSZ] = {0}, our_hex[GIT_MAX_HEXSZ] = {0}, + their_hex[GIT_MAX_HEXSZ] = {0}; + + if (orig_blob) + oid_to_hex_r(orig_hex, orig_blob); + if (our_blob) + oid_to_hex_r(our_hex, our_blob); + if (their_blob) + oid_to_hex_r(their_hex, their_blob); + + return error(_("%s: Not handling case %s -> %s -> %s"), + path, orig_hex, our_hex, their_hex); + } + + return 0; +} diff --git a/merge-strategies.h b/merge-strategies.h new file mode 100644 index 0000000000..b527d145c7 --- /dev/null +++ b/merge-strategies.h @@ -0,0 +1,13 @@ +#ifndef MERGE_STRATEGIES_H +#define MERGE_STRATEGIES_H + +#include "object.h" + +int merge_strategies_one_file(struct repository *r, + const struct object_id *orig_blob, + const struct object_id *our_blob, + const struct object_id *their_blob, const char *path, + unsigned int orig_mode, unsigned int our_mode, + unsigned int their_mode); + +#endif /* MERGE_STRATEGIES_H */ diff --git a/t/t6415-merge-dir-to-symlink.sh b/t/t6415-merge-dir-to-symlink.sh index 2eddcc7664..5fb74e39a0 100755 --- a/t/t6415-merge-dir-to-symlink.sh +++ b/t/t6415-merge-dir-to-symlink.sh @@ -94,7 +94,7 @@ test_expect_success SYMLINKS 'a/b was resolved as symlink' ' test -h a/b ' -test_expect_failure 'do not lose untracked in merge (resolve)' ' +test_expect_success 'do not lose untracked in merge (resolve)' ' git reset --hard && git checkout baseline^0 && >a/b/c/e && From patchwork Mon Oct 5 12:26:38 2020 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Alban Gruin X-Patchwork-Id: 11816575 Return-Path: Received: from mail.kernel.org (pdx-korg-mail-1.web.codeaurora.org [172.30.200.123]) by pdx-korg-patchwork-2.web.codeaurora.org (Postfix) with ESMTP id DAD8313B2 for ; Mon, 5 Oct 2020 12:27:43 +0000 (UTC) Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by mail.kernel.org (Postfix) with ESMTP id BB8CC208B6 for ; Mon, 5 Oct 2020 12:27:43 +0000 (UTC) Authentication-Results: mail.kernel.org; dkim=pass (2048-bit key) header.d=gmail.com header.i=@gmail.com header.b="X5nAJQ9U" Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1726197AbgJEM1n (ORCPT ); Mon, 5 Oct 2020 08:27:43 -0400 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:48744 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1726138AbgJEM1m (ORCPT ); Mon, 5 Oct 2020 08:27:42 -0400 Received: from mail-wr1-x442.google.com (mail-wr1-x442.google.com [IPv6:2a00:1450:4864:20::442]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id C82D1C0613A8 for ; Mon, 5 Oct 2020 05:27:41 -0700 (PDT) Received: by mail-wr1-x442.google.com with SMTP id e18so3435282wrw.9 for ; Mon, 05 Oct 2020 05:27:41 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20161025; h=from:to:cc:subject:date:message-id:in-reply-to:references :mime-version:content-transfer-encoding; bh=VqPu+6eMDaMas6kXEYkJIlsPiQuAzz9VhfIi/RUao9U=; b=X5nAJQ9Uw4hSJD+fuTK+9hSuMDr2cXfnTjnucyOnESGW7F1QGmDDsc1QOXANNA6sA4 8p/KwDCwqxdfCqAgCINZcIsmrvTZ35Ot+qJGuYYprSDmi72cfm05jO4Br3cOqDfpqk8i Ewec9v5RJkMILmbBCGmre5t17sDwf00Et4mvqXib1XNps4W2XBEOrnrqN/NeJpZjrnHT 4NdIOQxfEkmS3Htw+z3stf0fv+nMPNarY+l+o4l06EKW65OK/+Jnpf3gGPi3ClaaftDR mdS66jPDNMCbWqrcmyV4DgcFVQug6yz9EtfoEeZf1oj9KeZfvXhzJA6UiuPdQReJKBYW BNMA== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-gm-message-state:from:to:cc:subject:date:message-id:in-reply-to :references:mime-version:content-transfer-encoding; bh=VqPu+6eMDaMas6kXEYkJIlsPiQuAzz9VhfIi/RUao9U=; b=puFEKiVlXdr/2wH2gsyWnpEYjzOwD8lzi2Ehn95C0zt0pycGJaJsYltN0GeMZs5P1y oJLbB7z9To6Ye4zhn9A5Ll9MmZaeyXwN4zqYzuXl+Xd2XKBdStvqMZ2/Wei4OHlcLgiW 4m2F/EHkoGoqKg28G+FCxSSYRO0bdqUE0GmVBCcuY1+J76EGm4Qc2za2udUfMEShfGDX sVNN4G5AfmfoA3Z4DtJm6/0SRuc4nRqDsqPqLJa3pbL5M0d8AZBhT5AJHQUXbusEu16H 1d8+O0QUgP7n2cVvaaLs5VfUcSJReHUc0SWkFAc5rvzdE6Rw6RmUNAc+n1PJfS0mJcXn eVwQ== X-Gm-Message-State: AOAM531yp3mqz+rzpToYvyKaQC4TMlGfN8HUtLFsJJaVenhghFLLaD2d gPEoLchEL2r0gBnrkbb6u3w69oneg9A= X-Google-Smtp-Source: ABdhPJy8EAcQp2DcZhGC1bkIdEZBLCdciINUCRVPKw8Bx/OvhSZd9jFp21Fma2yOgNmUYtg39x/KWw== X-Received: by 2002:adf:eb8f:: with SMTP id t15mr17398909wrn.417.1601900860109; Mon, 05 Oct 2020 05:27:40 -0700 (PDT) Received: from ylate.lan (atoulouse-654-1-293-21.w86-199.abo.wanadoo.fr. [86.199.76.21]) by smtp.googlemail.com with ESMTPSA id n2sm13270400wma.29.2020.10.05.05.27.38 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Mon, 05 Oct 2020 05:27:39 -0700 (PDT) From: Alban Gruin To: git@vger.kernel.org Cc: Junio C Hamano , phillip.wood@dunelm.org.uk, Alban Gruin Subject: [PATCH v3 03/11] merge-index: libify merge_one_path() and merge_all() Date: Mon, 5 Oct 2020 14:26:38 +0200 Message-Id: <20201005122646.27994-4-alban.gruin@gmail.com> X-Mailer: git-send-email 2.20.1 In-Reply-To: <20201005122646.27994-1-alban.gruin@gmail.com> References: <20200901105705.6059-1-alban.gruin@gmail.com> <20201005122646.27994-1-alban.gruin@gmail.com> MIME-Version: 1.0 Precedence: bulk List-ID: X-Mailing-List: git@vger.kernel.org The "resolve" and "octopus" merge strategies do not call directly `git merge-one-file', they delegate the work to another git command, `git merge-index', that will loop over files in the index and call the specified command. Unfortunately, these functions are not part of libgit.a, which means that once rewritten, the strategies would still have to invoke `merge-one-file' by spawning a new process first. To avoid this, this moves merge_one_path(), merge_all(), and their helpers to merge-strategies.c. They also take a callback to dictate what they should do for each file. For now, to preserve the behaviour of `merge-index', only one callback, launching a new process, is defined. Signed-off-by: Alban Gruin --- builtin/merge-index.c | 77 +++------------------------------ merge-strategies.c | 99 +++++++++++++++++++++++++++++++++++++++++++ merge-strategies.h | 17 ++++++++ 3 files changed, 123 insertions(+), 70 deletions(-) diff --git a/builtin/merge-index.c b/builtin/merge-index.c index 38ea6ad6ca..6cb666cc78 100644 --- a/builtin/merge-index.c +++ b/builtin/merge-index.c @@ -1,74 +1,11 @@ #define USE_THE_INDEX_COMPATIBILITY_MACROS #include "builtin.h" -#include "run-command.h" - -static const char *pgm; -static int one_shot, quiet; -static int err; - -static int merge_entry(int pos, const char *path) -{ - int found; - const char *arguments[] = { pgm, "", "", "", path, "", "", "", NULL }; - char hexbuf[4][GIT_MAX_HEXSZ + 1]; - char ownbuf[4][60]; - - if (pos >= active_nr) - die("git merge-index: %s not in the cache", path); - found = 0; - do { - const struct cache_entry *ce = active_cache[pos]; - int stage = ce_stage(ce); - - if (strcmp(ce->name, path)) - break; - found++; - oid_to_hex_r(hexbuf[stage], &ce->oid); - xsnprintf(ownbuf[stage], sizeof(ownbuf[stage]), "%o", ce->ce_mode); - arguments[stage] = hexbuf[stage]; - arguments[stage + 4] = ownbuf[stage]; - } while (++pos < active_nr); - if (!found) - die("git merge-index: %s not in the cache", path); - - if (run_command_v_opt(arguments, 0)) { - if (one_shot) - err++; - else { - if (!quiet) - die("merge program failed"); - exit(1); - } - } - return found; -} - -static void merge_one_path(const char *path) -{ - int pos = cache_name_pos(path, strlen(path)); - - /* - * If it already exists in the cache as stage0, it's - * already merged and there is nothing to do. - */ - if (pos < 0) - merge_entry(-pos-1, path); -} - -static void merge_all(void) -{ - int i; - for (i = 0; i < active_nr; i++) { - const struct cache_entry *ce = active_cache[i]; - if (!ce_stage(ce)) - continue; - i += merge_entry(i, ce->name)-1; - } -} +#include "merge-strategies.h" int cmd_merge_index(int argc, const char **argv, const char *prefix) { - int i, force_file = 0; + int i, force_file = 0, err = 0, one_shot = 0, quiet = 0; + const char *pgm; /* Without this we cannot rely on waitpid() to tell * what happened to our children. @@ -98,14 +35,14 @@ int cmd_merge_index(int argc, const char **argv, const char *prefix) continue; } if (!strcmp(arg, "-a")) { - merge_all(); + err |= merge_all(&the_index, one_shot, quiet, + merge_program_cb, (void *)pgm); continue; } die("git merge-index: unknown option %s", arg); } - merge_one_path(arg); + err |= merge_one_path(&the_index, one_shot, quiet, arg, + merge_program_cb, (void *)pgm); } - if (err && !quiet) - die("merge program failed"); return err; } diff --git a/merge-strategies.c b/merge-strategies.c index bbe6f48698..f0e30f5624 100644 --- a/merge-strategies.c +++ b/merge-strategies.c @@ -2,6 +2,7 @@ #include "dir.h" #include "ll-merge.h" #include "merge-strategies.h" +#include "run-command.h" #include "xdiff-interface.h" static int add_to_index_cacheinfo(struct index_state *istate, @@ -212,3 +213,101 @@ int merge_strategies_one_file(struct repository *r, return 0; } + +int merge_program_cb(const struct object_id *orig_blob, + const struct object_id *our_blob, + const struct object_id *their_blob, const char *path, + unsigned int orig_mode, unsigned int our_mode, unsigned int their_mode, + void *data) +{ + char ownbuf[3][GIT_MAX_HEXSZ] = {{0}}; + const char *arguments[] = { (char *)data, "", "", "", path, + ownbuf[0], ownbuf[1], ownbuf[2], + NULL }; + + if (orig_blob) + arguments[1] = oid_to_hex(orig_blob); + if (our_blob) + arguments[2] = oid_to_hex(our_blob); + if (their_blob) + arguments[3] = oid_to_hex(their_blob); + + xsnprintf(ownbuf[0], sizeof(ownbuf[0]), "%o", orig_mode); + xsnprintf(ownbuf[1], sizeof(ownbuf[1]), "%o", our_mode); + xsnprintf(ownbuf[2], sizeof(ownbuf[2]), "%o", their_mode); + + return run_command_v_opt(arguments, 0); +} + +static int merge_entry(struct index_state *istate, int quiet, int pos, + const char *path, merge_cb cb, void *data) +{ + int found = 0; + const struct object_id *oids[3] = {NULL}; + unsigned int modes[3] = {0}; + + do { + const struct cache_entry *ce = istate->cache[pos]; + int stage = ce_stage(ce); + + if (strcmp(ce->name, path)) + break; + found++; + oids[stage - 1] = &ce->oid; + modes[stage - 1] = ce->ce_mode; + } while (++pos < istate->cache_nr); + if (!found) + return error(_("%s is not in the cache"), path); + + if (cb(oids[0], oids[1], oids[2], path, modes[0], modes[1], modes[2], data)) { + if (!quiet) + error(_("Merge program failed")); + return -2; + } + + return found; +} + +int merge_one_path(struct index_state *istate, int oneshot, int quiet, + const char *path, merge_cb cb, void *data) +{ + int pos = index_name_pos(istate, path, strlen(path)), ret; + + /* + * If it already exists in the cache as stage0, it's + * already merged and there is nothing to do. + */ + if (pos < 0) { + ret = merge_entry(istate, quiet, -pos - 1, path, cb, data); + if (ret == -1) + return -1; + else if (ret == -2) + return 1; + } + return 0; +} + +int merge_all(struct index_state *istate, int oneshot, int quiet, + merge_cb cb, void *data) +{ + int err = 0, i, ret; + for (i = 0; i < istate->cache_nr; i++) { + const struct cache_entry *ce = istate->cache[i]; + if (!ce_stage(ce)) + continue; + + ret = merge_entry(istate, quiet, i, ce->name, cb, data); + if (ret > 0) + i += ret - 1; + else if (ret == -1) + return -1; + else if (ret == -2) { + if (oneshot) + err++; + else + return 1; + } + } + + return err; +} diff --git a/merge-strategies.h b/merge-strategies.h index b527d145c7..cf78d7eaf4 100644 --- a/merge-strategies.h +++ b/merge-strategies.h @@ -10,4 +10,21 @@ int merge_strategies_one_file(struct repository *r, unsigned int orig_mode, unsigned int our_mode, unsigned int their_mode); +typedef int (*merge_cb)(const struct object_id *orig_blob, + const struct object_id *our_blob, + const struct object_id *their_blob, const char *path, + unsigned int orig_mode, unsigned int our_mode, unsigned int their_mode, + void *data); + +int merge_program_cb(const struct object_id *orig_blob, + const struct object_id *our_blob, + const struct object_id *their_blob, const char *path, + unsigned int orig_mode, unsigned int our_mode, unsigned int their_mode, + void *data); + +int merge_one_path(struct index_state *istate, int oneshot, int quiet, + const char *path, merge_cb cb, void *data); +int merge_all(struct index_state *istate, int oneshot, int quiet, + merge_cb cb, void *data); + #endif /* MERGE_STRATEGIES_H */ From patchwork Mon Oct 5 12:26:39 2020 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Alban Gruin X-Patchwork-Id: 11816591 Return-Path: Received: from mail.kernel.org (pdx-korg-mail-1.web.codeaurora.org [172.30.200.123]) by pdx-korg-patchwork-2.web.codeaurora.org (Postfix) with ESMTP id 30990112E for ; Mon, 5 Oct 2020 12:28:31 +0000 (UTC) Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by mail.kernel.org (Postfix) with ESMTP id 0C3042078D for ; Mon, 5 Oct 2020 12:28:31 +0000 (UTC) Authentication-Results: mail.kernel.org; dkim=pass (2048-bit key) header.d=gmail.com header.i=@gmail.com header.b="dcbqKduc" Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1726389AbgJEM1u (ORCPT ); Mon, 5 Oct 2020 08:27:50 -0400 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:48750 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1726138AbgJEM1n (ORCPT ); Mon, 5 Oct 2020 08:27:43 -0400 Received: from mail-wr1-x444.google.com (mail-wr1-x444.google.com [IPv6:2a00:1450:4864:20::444]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id 13D74C0613CE for ; Mon, 5 Oct 2020 05:27:43 -0700 (PDT) Received: by mail-wr1-x444.google.com with SMTP id e17so641180wru.12 for ; Mon, 05 Oct 2020 05:27:43 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20161025; h=from:to:cc:subject:date:message-id:in-reply-to:references :mime-version:content-transfer-encoding; bh=BQ0GJ4E36ELS4BFjFwFHRqCVo74tbgfktw0J6x7UGhU=; b=dcbqKduczbDNIfKMmgXiXi+vOdzMtqZTTe3LbZ8dXYQsFsHK/cCzq4kDEXnfYWMCP0 NgJVJbnYGdSXXgN0qPCIggjgExzMRqM6BmzPi0u6Ujzi8qtsxKezIi/zRouYHJKPZ5Cf NHq6lGtehYVRng4CT9R5IR0Y3DuDWP7Bvwtp2jRQAenrKVqwNBYlMivpupDrmKNRcaN+ oTGCTRPmL4YcfwE3sfZGRxYW/k6zSSCGnGyJZsVHgJ00t8H9OrJOYaXt0hAuVOxdptPD TAfpnR5ITxYXgLirtACXDu8wuhF/LmfGuwQC9mzzIymOQv+7tltYx4bd3xB/cAfX2ywA t3yQ== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-gm-message-state:from:to:cc:subject:date:message-id:in-reply-to :references:mime-version:content-transfer-encoding; bh=BQ0GJ4E36ELS4BFjFwFHRqCVo74tbgfktw0J6x7UGhU=; b=md/QpI7G0xy3dBiglIupwuJaSa9sJk9hQVyQavSvanD74+VEmeHDhRRyJM4LKa0rqd XpjcNIs+i/U3YhliuUYb1EeyFfRmShFPeV/fQsiy2SBrn3f2F+QpcaIzStdKSE8JSB/i eP1I55LJ1/wPTP+L6SsjmaXTfyKBEKcOlbseAGN+koWKGKBuPacca0hLXUTSobgBhlOy naC2l1O14Nkp7Z8rO9JFLILVdUcv9zYeCp+U/U88oQ54MY1ZSVk6Ei0KQPikKXWZnD+c j0dFYwtoqg4WK0IgXQk9t0Y7cNqfv39oyybHftTYZNE7kxy1LsRwGO1DgeVTsqLDIebX HozQ== X-Gm-Message-State: AOAM532zr1iz0pQIleBjVV+0N8PDw+C/9t87o12VJJ5jl+x6e/JgCeI5 FTNXRYaNcWFpW3gVN7YF9QERnNevIPk= X-Google-Smtp-Source: ABdhPJzlezWKGBpCNjmzmSunJW/i6ygV95zs9Bou+GI5EfeaLH6+zaOpteNkgFMhcUg6RS6Qr38KFQ== X-Received: by 2002:adf:97cb:: with SMTP id t11mr12082943wrb.292.1601900861473; Mon, 05 Oct 2020 05:27:41 -0700 (PDT) Received: from ylate.lan (atoulouse-654-1-293-21.w86-199.abo.wanadoo.fr. [86.199.76.21]) by smtp.googlemail.com with ESMTPSA id n2sm13270400wma.29.2020.10.05.05.27.40 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Mon, 05 Oct 2020 05:27:40 -0700 (PDT) From: Alban Gruin To: git@vger.kernel.org Cc: Junio C Hamano , phillip.wood@dunelm.org.uk, Alban Gruin Subject: [PATCH v3 04/11] merge-index: don't fork if the requested program is `git-merge-one-file' Date: Mon, 5 Oct 2020 14:26:39 +0200 Message-Id: <20201005122646.27994-5-alban.gruin@gmail.com> X-Mailer: git-send-email 2.20.1 In-Reply-To: <20201005122646.27994-1-alban.gruin@gmail.com> References: <20200901105705.6059-1-alban.gruin@gmail.com> <20201005122646.27994-1-alban.gruin@gmail.com> MIME-Version: 1.0 Precedence: bulk List-ID: X-Mailing-List: git@vger.kernel.org Since `git-merge-one-file' has been rewritten and libified, this teaches `merge-index' to call merge_strategies_one_file() without forking using a new callback, merge_one_file_cb(). Signed-off-by: Alban Gruin --- builtin/merge-index.c | 29 +++++++++++++++++++++++++++-- merge-strategies.c | 11 +++++++++++ merge-strategies.h | 6 ++++++ 3 files changed, 44 insertions(+), 2 deletions(-) diff --git a/builtin/merge-index.c b/builtin/merge-index.c index 6cb666cc78..19fff9a113 100644 --- a/builtin/merge-index.c +++ b/builtin/merge-index.c @@ -1,11 +1,15 @@ #define USE_THE_INDEX_COMPATIBILITY_MACROS #include "builtin.h" +#include "lockfile.h" #include "merge-strategies.h" int cmd_merge_index(int argc, const char **argv, const char *prefix) { int i, force_file = 0, err = 0, one_shot = 0, quiet = 0; const char *pgm; + void *data; + merge_cb merge_action; + struct lock_file lock = LOCK_INIT; /* Without this we cannot rely on waitpid() to tell * what happened to our children. @@ -26,7 +30,19 @@ int cmd_merge_index(int argc, const char **argv, const char *prefix) quiet = 1; i++; } + pgm = argv[i++]; + if (!strcmp(pgm, "git-merge-one-file")) { + merge_action = merge_one_file_cb; + data = (void *)the_repository; + + setup_work_tree(); + hold_locked_index(&lock, LOCK_DIE_ON_ERROR); + } else { + merge_action = merge_program_cb; + data = (void *)pgm; + } + for (; i < argc; i++) { const char *arg = argv[i]; if (!force_file && *arg == '-') { @@ -36,13 +52,22 @@ int cmd_merge_index(int argc, const char **argv, const char *prefix) } if (!strcmp(arg, "-a")) { err |= merge_all(&the_index, one_shot, quiet, - merge_program_cb, (void *)pgm); + merge_action, data); continue; } die("git merge-index: unknown option %s", arg); } err |= merge_one_path(&the_index, one_shot, quiet, arg, - merge_program_cb, (void *)pgm); + merge_action, data); + } + + if (merge_action == merge_one_file_cb) { + if (err) { + rollback_lock_file(&lock); + return err; + } + + return write_locked_index(&the_index, &lock, COMMIT_LOCK); } return err; } diff --git a/merge-strategies.c b/merge-strategies.c index f0e30f5624..c022ba9748 100644 --- a/merge-strategies.c +++ b/merge-strategies.c @@ -214,6 +214,17 @@ int merge_strategies_one_file(struct repository *r, return 0; } +int merge_one_file_cb(const struct object_id *orig_blob, + const struct object_id *our_blob, + const struct object_id *their_blob, const char *path, + unsigned int orig_mode, unsigned int our_mode, unsigned int their_mode, + void *data) +{ + return merge_strategies_one_file((struct repository *)data, + orig_blob, our_blob, their_blob, path, + orig_mode, our_mode, their_mode); +} + int merge_program_cb(const struct object_id *orig_blob, const struct object_id *our_blob, const struct object_id *their_blob, const char *path, diff --git a/merge-strategies.h b/merge-strategies.h index cf78d7eaf4..40e175ca39 100644 --- a/merge-strategies.h +++ b/merge-strategies.h @@ -16,6 +16,12 @@ typedef int (*merge_cb)(const struct object_id *orig_blob, unsigned int orig_mode, unsigned int our_mode, unsigned int their_mode, void *data); +int merge_one_file_cb(const struct object_id *orig_blob, + const struct object_id *our_blob, + const struct object_id *their_blob, const char *path, + unsigned int orig_mode, unsigned int our_mode, unsigned int their_mode, + void *data); + int merge_program_cb(const struct object_id *orig_blob, const struct object_id *our_blob, const struct object_id *their_blob, const char *path, From patchwork Mon Oct 5 12:26:40 2020 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Alban Gruin X-Patchwork-Id: 11816595 Return-Path: Received: from mail.kernel.org (pdx-korg-mail-1.web.codeaurora.org [172.30.200.123]) by pdx-korg-patchwork-2.web.codeaurora.org (Postfix) with ESMTP id 1623C618 for ; Mon, 5 Oct 2020 12:28:42 +0000 (UTC) Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by mail.kernel.org (Postfix) with ESMTP id E4954208B6 for ; Mon, 5 Oct 2020 12:28:41 +0000 (UTC) Authentication-Results: mail.kernel.org; dkim=pass (2048-bit key) header.d=gmail.com header.i=@gmail.com header.b="npSo0L3y" Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1726330AbgJEM1u (ORCPT ); Mon, 5 Oct 2020 08:27:50 -0400 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:48758 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1725970AbgJEM1p (ORCPT ); Mon, 5 Oct 2020 08:27:45 -0400 Received: from mail-wm1-x344.google.com (mail-wm1-x344.google.com [IPv6:2a00:1450:4864:20::344]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id AF226C0613A7 for ; Mon, 5 Oct 2020 05:27:44 -0700 (PDT) Received: by mail-wm1-x344.google.com with SMTP id y15so8588885wmi.0 for ; Mon, 05 Oct 2020 05:27:44 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20161025; h=from:to:cc:subject:date:message-id:in-reply-to:references :mime-version:content-transfer-encoding; bh=3rB3VNrc+86vIwdvgJqzkxd0B5WUYC0AkgCKiXyEq7o=; b=npSo0L3yd+HVCo8a6DFNhuEMkm8cojA+7TZeMgdZq/cQhbZXmqciUcRa4NvOcCC8Ku HwfS1Q2zgIfISkQsZ6vPxHsnaKKuCr8zLoo5QY9xk+X6gTQ4OCdI9/0S/XN671DZBsUm pW/yVY9S74LQcNwytW/fePwJzj3euvUBayQwtqgj6YpTs8uV6SkDElAciyme1q0eEuzz ipP7MGbDIbqDnPl6+MCt/fP7FQeedcVZOs8cTEYpPVrsuQ9820eT30/Dab2nD6kZcBqd 5vqt2AFfcy4ovwcIuBxfplqPyXTrYhE78k43N8rhgYHElce+QjZQsUSx5wl7gKxqSrqR dJmg== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-gm-message-state:from:to:cc:subject:date:message-id:in-reply-to :references:mime-version:content-transfer-encoding; bh=3rB3VNrc+86vIwdvgJqzkxd0B5WUYC0AkgCKiXyEq7o=; b=Rm9mx5IlXWvYYebr1iTmaIbvehUvocks2keP483k/0WTKm1T55PhEDLh2ZD7SVw8lO X/rFU6QfAoOjSrujonSYIqBqrbBp8Sq0YNYR0J53efzD42UZWW2D57kPWJHeVDVubt1Z IBLLv7pzdjaMc9+mnCd48zvba6YH2YP2NL240fPkEfYfkx1Da0w88/w4b0+qeBY0RdPf TMe2sJKWo3sfbNVDxS5E8bN07FWA+1urKVwImfeNw9Ss0LUoH/Q7XKfYkwRGV14PI53h a4b5+ulcLuksSFwrMQdxr2KCu9g2sZKp3rQEWyuN9yNdqrRWKCabk5Wtbztwtw/pkafK BCXQ== X-Gm-Message-State: AOAM532pKtpPHrN8aIfU5S4ZDTx6gYL+fyMIbOadSDOSpqHxOCSBgk2Y e4c6hbhpCy0jOKjokd5hXWf48kNzZwQ= X-Google-Smtp-Source: ABdhPJxtAl/gPDpH0WHASMi7GvwL7bpIP4gqR1NJxS57mG2guXpcu4t3AWJVvSEL0xGDFnk4aoOtKw== X-Received: by 2002:a7b:cc02:: with SMTP id f2mr16230351wmh.1.1601900862822; Mon, 05 Oct 2020 05:27:42 -0700 (PDT) Received: from ylate.lan (atoulouse-654-1-293-21.w86-199.abo.wanadoo.fr. [86.199.76.21]) by smtp.googlemail.com with ESMTPSA id n2sm13270400wma.29.2020.10.05.05.27.41 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Mon, 05 Oct 2020 05:27:42 -0700 (PDT) From: Alban Gruin To: git@vger.kernel.org Cc: Junio C Hamano , phillip.wood@dunelm.org.uk, Alban Gruin Subject: [PATCH v3 05/11] merge-resolve: rewrite in C Date: Mon, 5 Oct 2020 14:26:40 +0200 Message-Id: <20201005122646.27994-6-alban.gruin@gmail.com> X-Mailer: git-send-email 2.20.1 In-Reply-To: <20201005122646.27994-1-alban.gruin@gmail.com> References: <20200901105705.6059-1-alban.gruin@gmail.com> <20201005122646.27994-1-alban.gruin@gmail.com> MIME-Version: 1.0 Precedence: bulk List-ID: X-Mailing-List: git@vger.kernel.org This rewrites `git merge-resolve' from shell to C. As for `git merge-one-file', this port is not completely straightforward and removes calls to external processes to avoid reading and writing the index over and over again. - The call to `update-index -q --refresh' is replaced by a call to refresh_index(). - The call to `read-tree' is replaced by a call to unpack_trees() (and all the setup needed). - The call to `write-tree' is replaced by a call to write_index_as_tree(). - The call to `merge-index', needed to invoke `git merge-one-file', is replaced by a call to the new merge_all() function. A callback function, merge_one_file_cb(), is added to allow it to call merge_one_file() without forking. Here too, the index is read in cmd_merge_resolve(), but merge_strategies_resolve() takes care of writing it back to the disk. The parameters of merge_strategies_resolve() will be surprising at first glance: why using a commit list for `bases' and `remote', where we could use an oid array, and a pointer to an oid? Because, in a later commit, try_merge_strategy() will be able to call merge_strategies_resolve() directly, and it already uses a commit list for `bases' (`common') and `remote' (`remoteheads'), and a string for `head_arg'. To reduce frictions later, merge_strategies_resolve() takes the same types of parameters. Signed-off-by: Alban Gruin --- Makefile | 2 +- builtin.h | 1 + builtin/merge-resolve.c | 69 +++++++++++++++++++++++++++++++++ git-merge-resolve.sh | 54 -------------------------- git.c | 1 + merge-strategies.c | 85 +++++++++++++++++++++++++++++++++++++++++ merge-strategies.h | 5 +++ 7 files changed, 162 insertions(+), 55 deletions(-) create mode 100644 builtin/merge-resolve.c delete mode 100755 git-merge-resolve.sh diff --git a/Makefile b/Makefile index 6dfdb33cb2..3cc6b192f1 100644 --- a/Makefile +++ b/Makefile @@ -601,7 +601,6 @@ SCRIPT_SH += git-bisect.sh SCRIPT_SH += git-difftool--helper.sh SCRIPT_SH += git-filter-branch.sh SCRIPT_SH += git-merge-octopus.sh -SCRIPT_SH += git-merge-resolve.sh SCRIPT_SH += git-mergetool.sh SCRIPT_SH += git-quiltimport.sh SCRIPT_SH += git-request-pull.sh @@ -1097,6 +1096,7 @@ BUILTIN_OBJS += builtin/merge-index.o BUILTIN_OBJS += builtin/merge-one-file.o BUILTIN_OBJS += builtin/merge-ours.o BUILTIN_OBJS += builtin/merge-recursive.o +BUILTIN_OBJS += builtin/merge-resolve.o BUILTIN_OBJS += builtin/merge-tree.o BUILTIN_OBJS += builtin/merge.o BUILTIN_OBJS += builtin/mktag.o diff --git a/builtin.h b/builtin.h index 4d2cd78856..35e91c16d0 100644 --- a/builtin.h +++ b/builtin.h @@ -180,6 +180,7 @@ int cmd_merge_ours(int argc, const char **argv, const char *prefix); int cmd_merge_file(int argc, const char **argv, const char *prefix); int cmd_merge_one_file(int argc, const char **argv, const char *prefix); int cmd_merge_recursive(int argc, const char **argv, const char *prefix); +int cmd_merge_resolve(int argc, const char **argv, const char *prefix); int cmd_merge_tree(int argc, const char **argv, const char *prefix); int cmd_mktag(int argc, const char **argv, const char *prefix); int cmd_mktree(int argc, const char **argv, const char *prefix); diff --git a/builtin/merge-resolve.c b/builtin/merge-resolve.c new file mode 100644 index 0000000000..59f734473b --- /dev/null +++ b/builtin/merge-resolve.c @@ -0,0 +1,69 @@ +/* + * Builtin "git merge-resolve" + * + * Copyright (c) 2020 Alban Gruin + * + * Based on git-merge-resolve.sh, written by Linus Torvalds and Junio C + * Hamano. + * + * Resolve two trees, using enhanced multi-base read-tree. + */ + +#include "cache.h" +#include "builtin.h" +#include "merge-strategies.h" + +static const char builtin_merge_resolve_usage[] = + "git merge-resolve ... -- "; + +int cmd_merge_resolve(int argc, const char **argv, const char *prefix) +{ + int i, is_baseless = 1, sep_seen = 0; + const char *head = NULL; + struct commit_list *bases = NULL, *remote = NULL; + struct commit_list **next_base = &bases; + + if (argc < 5) + usage(builtin_merge_resolve_usage); + + setup_work_tree(); + if (repo_read_index(the_repository) < 0) + die("invalid index"); + + /* The first parameters up to -- are merge bases; the rest are + * heads. */ + for (i = 1; i < argc; i++) { + if (strcmp(argv[i], "--") == 0) + sep_seen = 1; + else if (strcmp(argv[i], "-h") == 0) + usage(builtin_merge_resolve_usage); + else if (sep_seen && !head) + head = argv[i]; + else if (remote) { + /* Give up if we are given two or more remotes. + * Not handling octopus. */ + return 2; + } else { + struct object_id oid; + + get_oid(argv[i], &oid); + is_baseless &= sep_seen; + + if (!oideq(&oid, the_hash_algo->empty_tree)) { + struct commit *commit; + commit = lookup_commit_or_die(&oid, argv[i]); + + if (sep_seen) + commit_list_append(commit, &remote); + else + next_base = commit_list_append(commit, next_base); + } + } + } + + /* Give up if this is a baseless merge. */ + if (is_baseless) + return 2; + + return merge_strategies_resolve(the_repository, bases, head, remote); +} diff --git a/git-merge-resolve.sh b/git-merge-resolve.sh deleted file mode 100755 index 343fe7bccd..0000000000 --- a/git-merge-resolve.sh +++ /dev/null @@ -1,54 +0,0 @@ -#!/bin/sh -# -# Copyright (c) 2005 Linus Torvalds -# Copyright (c) 2005 Junio C Hamano -# -# Resolve two trees, using enhanced multi-base read-tree. - -# The first parameters up to -- are merge bases; the rest are heads. -bases= head= remotes= sep_seen= -for arg -do - case ",$sep_seen,$head,$arg," in - *,--,) - sep_seen=yes - ;; - ,yes,,*) - head=$arg - ;; - ,yes,*) - remotes="$remotes$arg " - ;; - *) - bases="$bases$arg " - ;; - esac -done - -# Give up if we are given two or more remotes -- not handling octopus. -case "$remotes" in -?*' '?*) - exit 2 ;; -esac - -# Give up if this is a baseless merge. -if test '' = "$bases" -then - exit 2 -fi - -git update-index -q --refresh -git read-tree -u -m --aggressive $bases $head $remotes || exit 2 -echo "Trying simple merge." -if result_tree=$(git write-tree 2>/dev/null) -then - exit 0 -else - echo "Simple merge failed, trying Automatic merge." - if git merge-index -o git-merge-one-file -a - then - exit 0 - else - exit 1 - fi -fi diff --git a/git.c b/git.c index a4d3f98094..64a1a1de41 100644 --- a/git.c +++ b/git.c @@ -544,6 +544,7 @@ static struct cmd_struct commands[] = { { "merge-recursive", cmd_merge_recursive, RUN_SETUP | NEED_WORK_TREE | NO_PARSEOPT }, { "merge-recursive-ours", cmd_merge_recursive, RUN_SETUP | NEED_WORK_TREE | NO_PARSEOPT }, { "merge-recursive-theirs", cmd_merge_recursive, RUN_SETUP | NEED_WORK_TREE | NO_PARSEOPT }, + { "merge-resolve", cmd_merge_resolve, RUN_SETUP | NEED_WORK_TREE | NO_PARSEOPT }, { "merge-subtree", cmd_merge_recursive, RUN_SETUP | NEED_WORK_TREE | NO_PARSEOPT }, { "merge-tree", cmd_merge_tree, RUN_SETUP | NO_PARSEOPT }, { "mktag", cmd_mktag, RUN_SETUP | NO_PARSEOPT }, diff --git a/merge-strategies.c b/merge-strategies.c index c022ba9748..6b4b3d03a6 100644 --- a/merge-strategies.c +++ b/merge-strategies.c @@ -1,8 +1,11 @@ #include "cache.h" +#include "cache-tree.h" #include "dir.h" #include "ll-merge.h" +#include "lockfile.h" #include "merge-strategies.h" #include "run-command.h" +#include "unpack-trees.h" #include "xdiff-interface.h" static int add_to_index_cacheinfo(struct index_state *istate, @@ -322,3 +325,85 @@ int merge_all(struct index_state *istate, int oneshot, int quiet, return err; } + +static int add_tree(const struct object_id *oid, struct tree_desc *t) +{ + struct tree *tree; + + tree = parse_tree_indirect(oid); + if (parse_tree(tree)) + return -1; + + init_tree_desc(t, tree->buffer, tree->size); + return 0; +} + +int merge_strategies_resolve(struct repository *r, + struct commit_list *bases, const char *head_arg, + struct commit_list *remote) +{ + int i = 0; + struct lock_file lock = LOCK_INIT; + struct tree_desc t[MAX_UNPACK_TREES]; + struct unpack_trees_options opts; + struct object_id head, oid; + struct commit_list *j; + + if (head_arg) + get_oid(head_arg, &head); + + repo_hold_locked_index(r, &lock, LOCK_DIE_ON_ERROR); + refresh_index(r->index, 0, NULL, NULL, NULL); + + memset(&opts, 0, sizeof(opts)); + opts.head_idx = 1; + opts.src_index = r->index; + opts.dst_index = r->index; + opts.update = 1; + opts.merge = 1; + opts.aggressive = 1; + + for (j = bases; j && j->item; j = j->next) { + if (add_tree(&j->item->object.oid, t + (i++))) + goto out; + } + + if (head_arg && add_tree(&head, t + (i++))) + goto out; + if (remote && add_tree(&remote->item->object.oid, t + (i++))) + goto out; + + if (i == 1) + opts.fn = oneway_merge; + else if (i == 2) { + opts.fn = twoway_merge; + opts.initial_checkout = is_index_unborn(r->index); + } else if (i >= 3) { + opts.fn = threeway_merge; + opts.head_idx = i - 1; + } + + if (unpack_trees(i, t, &opts)) + goto out; + + puts(_("Trying simple merge.")); + write_locked_index(r->index, &lock, COMMIT_LOCK); + + if (write_index_as_tree(&oid, r->index, r->index_file, + WRITE_TREE_SILENT, NULL)) { + int ret; + + puts(_("Simple merge failed, trying Automatic merge.")); + repo_hold_locked_index(r, &lock, LOCK_DIE_ON_ERROR); + ret = merge_all(r->index, 0, 0, merge_one_file_cb, r); + + write_locked_index(r->index, &lock, COMMIT_LOCK); + return !!ret; + } + + return 0; + + out: + rollback_lock_file(&lock); + return 2; +} diff --git a/merge-strategies.h b/merge-strategies.h index 40e175ca39..778f8ce9d6 100644 --- a/merge-strategies.h +++ b/merge-strategies.h @@ -1,6 +1,7 @@ #ifndef MERGE_STRATEGIES_H #define MERGE_STRATEGIES_H +#include "commit.h" #include "object.h" int merge_strategies_one_file(struct repository *r, @@ -33,4 +34,8 @@ int merge_one_path(struct index_state *istate, int oneshot, int quiet, int merge_all(struct index_state *istate, int oneshot, int quiet, merge_cb cb, void *data); +int merge_strategies_resolve(struct repository *r, + struct commit_list *bases, const char *head_arg, + struct commit_list *remote); + #endif /* MERGE_STRATEGIES_H */ From patchwork Mon Oct 5 12:26:41 2020 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Alban Gruin X-Patchwork-Id: 11816589 Return-Path: Received: from mail.kernel.org (pdx-korg-mail-1.web.codeaurora.org [172.30.200.123]) by pdx-korg-patchwork-2.web.codeaurora.org (Postfix) with ESMTP id 56D0D112E for ; Mon, 5 Oct 2020 12:28:26 +0000 (UTC) Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by mail.kernel.org (Postfix) with ESMTP id 3898C2085B for ; Mon, 5 Oct 2020 12:28:26 +0000 (UTC) Authentication-Results: mail.kernel.org; dkim=pass (2048-bit key) header.d=gmail.com header.i=@gmail.com header.b="dS1iMExP" Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1726410AbgJEM1u (ORCPT ); Mon, 5 Oct 2020 08:27:50 -0400 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:48764 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1726214AbgJEM1q (ORCPT ); Mon, 5 Oct 2020 08:27:46 -0400 Received: from mail-wm1-x344.google.com (mail-wm1-x344.google.com [IPv6:2a00:1450:4864:20::344]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id A4C72C0613AA for ; Mon, 5 Oct 2020 05:27:45 -0700 (PDT) Received: by mail-wm1-x344.google.com with SMTP id e2so8579340wme.1 for ; Mon, 05 Oct 2020 05:27:45 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20161025; h=from:to:cc:subject:date:message-id:in-reply-to:references :mime-version:content-transfer-encoding; bh=JLgOXavqtjFnKYe5ckatFzoZzjriXixtr2raTCetDHY=; b=dS1iMExP3fUhga+IP6U3OoXLBSBcoIc6hEsLGaDe7oJlb6i15oyDkKPuuBA8Y1pige GITv5ubMHo4XRgHaSEYC8OeX+I34Mi9bXHjbJNjp7DZs5C3+zPCFE6xxOOXf0zAgc3J+ erDCrwVqSv3kITZ9Q6+iXNZU8KF0re7kmLQIEnUe++kL5QYvmktk8bh3dTlqosDUYZCE HQS/ElKvGCleyVyJW3cs3gGlYSEaPhXRDWFm+6V49uis33Ra8+Fqe1w94Z9jH5Cr3Wm+ D0GTt+d46IPuYRL5MPRvbWt6pjJlh8YKL/m33qkr6v72xfEHaKVtAybSN7xKLLjDwxgA zs3A== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-gm-message-state:from:to:cc:subject:date:message-id:in-reply-to :references:mime-version:content-transfer-encoding; bh=JLgOXavqtjFnKYe5ckatFzoZzjriXixtr2raTCetDHY=; b=BMhtAwcdLUuKTlYDNkaZY9KI+dxrhJmPVCQfprwg3xgiV1YvONyjgKASTt/1c08SKs YSx+sTADOTsMDU6bG7dqQgTtVCwJsfb8ZXoSL6rDASFMR9L9AQpQOgOZrY8atSox0xE8 N4LEcC4Pbpnru26DqvDHVfsXybIE3lv25ihHmNEZj6UfmcX4Fh/t0OdCIdt0mr3xzVsH sXZy4Yxg3wvBlAc50vG69Hso5Tg9dSmcFOMgOvwfEdDRyfrqxl6oK1DgTwDz9lDUTNGO 72JXgoRLWE3Dk219IeS9rI938+9GCVt+Om3MDoYgzYSYn4z4upDyys7fw5BwwtF4pzgb kWbg== X-Gm-Message-State: AOAM532XTVhwJ52feCaYMY9/2PatHqspa4ZvbRZ3QoVg3PssKt4uRydC J4Ey9A0Xz+PFiX/tVYjV4QGMA9am07c= X-Google-Smtp-Source: ABdhPJxeHITGL9YySXDXUngA2iaTzEWQVZqmItor5PFvO/N0Av4OQYRo37ed+7ssdG1708moSXxX8g== X-Received: by 2002:a1c:b78a:: with SMTP id h132mr15484921wmf.172.1601900863980; Mon, 05 Oct 2020 05:27:43 -0700 (PDT) Received: from ylate.lan (atoulouse-654-1-293-21.w86-199.abo.wanadoo.fr. [86.199.76.21]) by smtp.googlemail.com with ESMTPSA id n2sm13270400wma.29.2020.10.05.05.27.42 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Mon, 05 Oct 2020 05:27:43 -0700 (PDT) From: Alban Gruin To: git@vger.kernel.org Cc: Junio C Hamano , phillip.wood@dunelm.org.uk, Alban Gruin Subject: [PATCH v3 06/11] merge-recursive: move better_branch_name() to merge.c Date: Mon, 5 Oct 2020 14:26:41 +0200 Message-Id: <20201005122646.27994-7-alban.gruin@gmail.com> X-Mailer: git-send-email 2.20.1 In-Reply-To: <20201005122646.27994-1-alban.gruin@gmail.com> References: <20200901105705.6059-1-alban.gruin@gmail.com> <20201005122646.27994-1-alban.gruin@gmail.com> MIME-Version: 1.0 Precedence: bulk List-ID: X-Mailing-List: git@vger.kernel.org get_better_branch_name() will be used by rebase-octopus once it is rewritten in C, so instead of duplicating it, this moves this function preventively inside an appropriate file in libgit.a. This function is also renamed to reflect its usage by merge strategies. Signed-off-by: Alban Gruin --- builtin/merge-recursive.c | 16 ++-------------- cache.h | 2 +- merge.c | 12 ++++++++++++ 3 files changed, 15 insertions(+), 15 deletions(-) diff --git a/builtin/merge-recursive.c b/builtin/merge-recursive.c index a4bfd8fc51..972243b5e9 100644 --- a/builtin/merge-recursive.c +++ b/builtin/merge-recursive.c @@ -8,18 +8,6 @@ static const char builtin_merge_recursive_usage[] = "git %s ... -- ..."; -static char *better_branch_name(const char *branch) -{ - static char githead_env[8 + GIT_MAX_HEXSZ + 1]; - char *name; - - if (strlen(branch) != the_hash_algo->hexsz) - return xstrdup(branch); - xsnprintf(githead_env, sizeof(githead_env), "GITHEAD_%s", branch); - name = getenv(githead_env); - return xstrdup(name ? name : branch); -} - int cmd_merge_recursive(int argc, const char **argv, const char *prefix) { const struct object_id *bases[21]; @@ -75,8 +63,8 @@ int cmd_merge_recursive(int argc, const char **argv, const char *prefix) if (get_oid(o.branch2, &h2)) die(_("could not resolve ref '%s'"), o.branch2); - o.branch1 = better1 = better_branch_name(o.branch1); - o.branch2 = better2 = better_branch_name(o.branch2); + o.branch1 = better1 = merge_get_better_branch_name(o.branch1); + o.branch2 = better2 = merge_get_better_branch_name(o.branch2); if (o.verbosity >= 3) printf(_("Merging %s with %s\n"), o.branch1, o.branch2); diff --git a/cache.h b/cache.h index c0072d43b1..5fa0ed8d1a 100644 --- a/cache.h +++ b/cache.h @@ -1928,7 +1928,7 @@ int checkout_fast_forward(struct repository *r, const struct object_id *from, const struct object_id *to, int overwrite_ignore); - +char *merge_get_better_branch_name(const char *branch); int sane_execvp(const char *file, char *const argv[]); diff --git a/merge.c b/merge.c index 5fb88af102..801d673c5f 100644 --- a/merge.c +++ b/merge.c @@ -109,3 +109,15 @@ int checkout_fast_forward(struct repository *r, return error(_("unable to write new index file")); return 0; } + +char *merge_get_better_branch_name(const char *branch) +{ + static char githead_env[8 + GIT_MAX_HEXSZ + 1]; + char *name; + + if (strlen(branch) != the_hash_algo->hexsz) + return xstrdup(branch); + xsnprintf(githead_env, sizeof(githead_env), "GITHEAD_%s", branch); + name = getenv(githead_env); + return xstrdup(name ? name : branch); +} From patchwork Mon Oct 5 12:26:42 2020 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Alban Gruin X-Patchwork-Id: 11816585 Return-Path: Received: from mail.kernel.org (pdx-korg-mail-1.web.codeaurora.org [172.30.200.123]) by pdx-korg-patchwork-2.web.codeaurora.org (Postfix) with ESMTP id 5DFD4112E for ; Mon, 5 Oct 2020 12:28:12 +0000 (UTC) Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by mail.kernel.org (Postfix) with ESMTP id 31D342085B for ; Mon, 5 Oct 2020 12:28:12 +0000 (UTC) Authentication-Results: mail.kernel.org; dkim=pass (2048-bit key) header.d=gmail.com header.i=@gmail.com header.b="LfFq24qT" Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1726516AbgJEM1w (ORCPT ); Mon, 5 Oct 2020 08:27:52 -0400 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:48782 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1726235AbgJEM1t (ORCPT ); Mon, 5 Oct 2020 08:27:49 -0400 Received: from mail-wr1-x42c.google.com (mail-wr1-x42c.google.com [IPv6:2a00:1450:4864:20::42c]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id A4AB6C0613AC for ; Mon, 5 Oct 2020 05:27:47 -0700 (PDT) Received: by mail-wr1-x42c.google.com with SMTP id g12so3907729wrp.10 for ; Mon, 05 Oct 2020 05:27:47 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20161025; h=from:to:cc:subject:date:message-id:in-reply-to:references :mime-version:content-transfer-encoding; bh=Eb73SFwQJPJU4UOnzUjaIQG0I5hmoZzAI3ZtmxU1W7o=; b=LfFq24qTAp3cQVAWEr2peBuujCBZEnvD5AKbYV2qHFJ/nhTMaunOaxqakRgW0MULcg AUbc0+LNIckKOlRKiIdjsPjnUq55S0l1Iwgcl+rCU87CMZDG1228HydxEgLIx6kzJoB1 PiuVTM/d8nNdRc5DRIJ09Qitp4Jb/QoCy7I635HkQiMMojSpalWCC8NqsjQ/d7wbHyx2 NngI/dspTFhJWeVQ218TA/QPQlp64IDcfXO7++yiIuFLVqOXk9HVNd6Vmjl2Xt7IIwnM WLATOr0O4ZrU15xH56GqbL8QkdicWdJ8ZsLk/S0ds+cXM3GzHXyDE4m5h4vakA+WKYd5 rUaw== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-gm-message-state:from:to:cc:subject:date:message-id:in-reply-to :references:mime-version:content-transfer-encoding; bh=Eb73SFwQJPJU4UOnzUjaIQG0I5hmoZzAI3ZtmxU1W7o=; b=FU8keHOQELlJxL5VIiJTC5t5jX2Ql7fb3zvP99+O2Adxv6JDcHvwoj6yWLMJod8JNX lZh1iktYjbPpWR30TbcM1+jbcbbiDIcHnIZyLkDrViCVF0MrNhW/q64PK/EhRDbIUBCd 8JVp4fPaNQxHBJgrVmPXAtAMjI9ZLCxXvhQFxmlTN5rrSKs1eeDrmOQly8uiqtBiLkwh HCuSfQ2cdASBdsM7wQeEzidPsFY2cg3KgEbMp01fD0GNffD8NXa5L1kkyCE9D2CeIMS8 joSvfY1+mRAj1c13YL+IEcBuIRv5ltrj0mDWZmK6kvipepNlPdVI8NPyQM+NZyXD3iJ4 hw5g== X-Gm-Message-State: AOAM533EM9i1XvKweLi9iwObpGwTSqmIlCnj9tTztqmajC9clzSw1lsq kq9vwtaSvb8nfrmSdH1/gCeMcaimuDI= X-Google-Smtp-Source: ABdhPJxih970Wmre9G/cE2MEg91dagoEx2Oa6k6VLCZhkfsmRpErzGh5ZaNabtdy5NS4aH/GPtkAlA== X-Received: by 2002:a5d:660f:: with SMTP id n15mr18646094wru.103.1601900865524; Mon, 05 Oct 2020 05:27:45 -0700 (PDT) Received: from ylate.lan (atoulouse-654-1-293-21.w86-199.abo.wanadoo.fr. [86.199.76.21]) by smtp.googlemail.com with ESMTPSA id n2sm13270400wma.29.2020.10.05.05.27.44 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Mon, 05 Oct 2020 05:27:44 -0700 (PDT) From: Alban Gruin To: git@vger.kernel.org Cc: Junio C Hamano , phillip.wood@dunelm.org.uk, Alban Gruin Subject: [PATCH v3 07/11] merge-octopus: rewrite in C Date: Mon, 5 Oct 2020 14:26:42 +0200 Message-Id: <20201005122646.27994-8-alban.gruin@gmail.com> X-Mailer: git-send-email 2.20.1 In-Reply-To: <20201005122646.27994-1-alban.gruin@gmail.com> References: <20200901105705.6059-1-alban.gruin@gmail.com> <20201005122646.27994-1-alban.gruin@gmail.com> MIME-Version: 1.0 Precedence: bulk List-ID: X-Mailing-List: git@vger.kernel.org This rewrites `git merge-octopus' from shell to C. As for the two last conversions, this port removes calls to external processes to avoid reading and writing the index over and over again. - Calls to `read-tree -u -m (--aggressive)?' are replaced by calls to unpack_trees(). - The call to `write-tree' is replaced by a call to write_index_as_tree(). - The call to `diff-index ...' is replaced by a call to repo_index_has_changes(), and is moved from cmd_merge_octopus() to merge_octopus(). - The call to `merge-index', needed to invoke `git merge-one-file', is replaced by a call to merge_all(). The index is read in cmd_merge_octopus(), and is wrote back by merge_strategies_octopus(). Here to, merge_strategies_octopus() takes two commit lists and a string to reduce frictions when try_merge_strategies() will be modified to call it directly. Signed-off-by: Alban Gruin --- Makefile | 2 +- builtin.h | 1 + builtin/merge-octopus.c | 69 ++++++++++++++ git-merge-octopus.sh | 112 ---------------------- git.c | 1 + merge-strategies.c | 204 ++++++++++++++++++++++++++++++++++++++++ merge-strategies.h | 3 + 7 files changed, 279 insertions(+), 113 deletions(-) create mode 100644 builtin/merge-octopus.c delete mode 100755 git-merge-octopus.sh diff --git a/Makefile b/Makefile index 3cc6b192f1..2b2bdffafe 100644 --- a/Makefile +++ b/Makefile @@ -600,7 +600,6 @@ unexport CDPATH SCRIPT_SH += git-bisect.sh SCRIPT_SH += git-difftool--helper.sh SCRIPT_SH += git-filter-branch.sh -SCRIPT_SH += git-merge-octopus.sh SCRIPT_SH += git-mergetool.sh SCRIPT_SH += git-quiltimport.sh SCRIPT_SH += git-request-pull.sh @@ -1093,6 +1092,7 @@ BUILTIN_OBJS += builtin/mailsplit.o BUILTIN_OBJS += builtin/merge-base.o BUILTIN_OBJS += builtin/merge-file.o BUILTIN_OBJS += builtin/merge-index.o +BUILTIN_OBJS += builtin/merge-octopus.o BUILTIN_OBJS += builtin/merge-one-file.o BUILTIN_OBJS += builtin/merge-ours.o BUILTIN_OBJS += builtin/merge-recursive.o diff --git a/builtin.h b/builtin.h index 35e91c16d0..50225404a0 100644 --- a/builtin.h +++ b/builtin.h @@ -176,6 +176,7 @@ int cmd_maintenance(int argc, const char **argv, const char *prefix); int cmd_merge(int argc, const char **argv, const char *prefix); int cmd_merge_base(int argc, const char **argv, const char *prefix); int cmd_merge_index(int argc, const char **argv, const char *prefix); +int cmd_merge_octopus(int argc, const char **argv, const char *prefix); int cmd_merge_ours(int argc, const char **argv, const char *prefix); int cmd_merge_file(int argc, const char **argv, const char *prefix); int cmd_merge_one_file(int argc, const char **argv, const char *prefix); diff --git a/builtin/merge-octopus.c b/builtin/merge-octopus.c new file mode 100644 index 0000000000..abf0981fe8 --- /dev/null +++ b/builtin/merge-octopus.c @@ -0,0 +1,69 @@ +/* + * Builtin "git merge-octopus" + * + * Copyright (c) 2020 Alban Gruin + * + * Based on git-merge-octopus.sh, written by Junio C Hamano. + * + * Resolve two or more trees. + */ + +#include "cache.h" +#include "builtin.h" +#include "commit.h" +#include "merge-strategies.h" + +static const char builtin_merge_octopus_usage[] = + "git merge-octopus [...] -- [...]"; + +int cmd_merge_octopus(int argc, const char **argv, const char *prefix) +{ + int i, sep_seen = 0; + struct commit_list *bases = NULL, *remotes = NULL; + struct commit_list **next_base = &bases, **next_remote = &remotes; + const char *head_arg = NULL; + + if (argc < 5) + usage(builtin_merge_octopus_usage); + + setup_work_tree(); + if (repo_read_index(the_repository) < 0) + die("corrupted cache"); + + /* + * The first parameters up to -- are merge bases; the rest are + * heads. + */ + for (i = 1; i < argc; i++) { + if (strcmp(argv[i], "--") == 0) + sep_seen = 1; + else if (strcmp(argv[i], "-h") == 0) + usage(builtin_merge_octopus_usage); + else if (sep_seen && !head_arg) + head_arg = argv[i]; + else { + struct object_id oid; + + get_oid(argv[i], &oid); + + if (!oideq(&oid, the_hash_algo->empty_tree)) { + struct commit *commit; + commit = lookup_commit_or_die(&oid, argv[i]); + + if (sep_seen) + next_remote = commit_list_append(commit, next_remote); + else + next_base = commit_list_append(commit, next_base); + } + } + } + + /* + * Reject if this is not an octopus -- resolve should be used + * instead. + */ + if (commit_list_count(remotes) < 2) + return 2; + + return merge_strategies_octopus(the_repository, bases, head_arg, remotes); +} diff --git a/git-merge-octopus.sh b/git-merge-octopus.sh deleted file mode 100755 index 7d19d37951..0000000000 --- a/git-merge-octopus.sh +++ /dev/null @@ -1,112 +0,0 @@ -#!/bin/sh -# -# Copyright (c) 2005 Junio C Hamano -# -# Resolve two or more trees. -# - -. git-sh-setup - -LF=' -' - -# The first parameters up to -- are merge bases; the rest are heads. -bases= head= remotes= sep_seen= -for arg -do - case ",$sep_seen,$head,$arg," in - *,--,) - sep_seen=yes - ;; - ,yes,,*) - head=$arg - ;; - ,yes,*) - remotes="$remotes$arg " - ;; - *) - bases="$bases$arg " - ;; - esac -done - -# Reject if this is not an octopus -- resolve should be used instead. -case "$remotes" in -?*' '?*) - ;; -*) - exit 2 ;; -esac - -# MRC is the current "merge reference commit" -# MRT is the current "merge result tree" - -if ! git diff-index --quiet --cached HEAD -- -then - gettextln "Error: Your local changes to the following files would be overwritten by merge" - git diff-index --cached --name-only HEAD -- | sed -e 's/^/ /' - exit 2 -fi -MRC=$(git rev-parse --verify -q $head) -MRT=$(git write-tree) -NON_FF_MERGE=0 -OCTOPUS_FAILURE=0 -for SHA1 in $remotes -do - case "$OCTOPUS_FAILURE" in - 1) - # We allow only last one to have a hand-resolvable - # conflicts. Last round failed and we still had - # a head to merge. - gettextln "Automated merge did not work." - gettextln "Should not be doing an octopus." - exit 2 - esac - - eval pretty_name=\${GITHEAD_$SHA1:-$SHA1} - if test "$SHA1" = "$pretty_name" - then - SHA1_UP="$(echo "$SHA1" | tr a-z A-Z)" - eval pretty_name=\${GITHEAD_$SHA1_UP:-$pretty_name} - fi - common=$(git merge-base --all $SHA1 $MRC) || - die "$(eval_gettext "Unable to find common commit with \$pretty_name")" - - case "$LF$common$LF" in - *"$LF$SHA1$LF"*) - eval_gettextln "Already up to date with \$pretty_name" - continue - ;; - esac - - if test "$common,$NON_FF_MERGE" = "$MRC,0" - then - # The first head being merged was a fast-forward. - # Advance MRC to the head being merged, and use that - # tree as the intermediate result of the merge. - # We still need to count this as part of the parent set. - - eval_gettextln "Fast-forwarding to: \$pretty_name" - git read-tree -u -m $head $SHA1 || exit - MRC=$SHA1 MRT=$(git write-tree) - continue - fi - - NON_FF_MERGE=1 - - eval_gettextln "Trying simple merge with \$pretty_name" - git read-tree -u -m --aggressive $common $MRT $SHA1 || exit 2 - next=$(git write-tree 2>/dev/null) - if test $? -ne 0 - then - gettextln "Simple merge did not work, trying automatic merge." - git merge-index -o git-merge-one-file -a || - OCTOPUS_FAILURE=1 - next=$(git write-tree 2>/dev/null) - fi - - MRC="$MRC $SHA1" - MRT=$next -done - -exit "$OCTOPUS_FAILURE" diff --git a/git.c b/git.c index 64a1a1de41..d51fb5d2bf 100644 --- a/git.c +++ b/git.c @@ -539,6 +539,7 @@ static struct cmd_struct commands[] = { { "merge-base", cmd_merge_base, RUN_SETUP }, { "merge-file", cmd_merge_file, RUN_SETUP_GENTLY }, { "merge-index", cmd_merge_index, RUN_SETUP | NO_PARSEOPT }, + { "merge-octopus", cmd_merge_octopus, RUN_SETUP | NO_PARSEOPT }, { "merge-ours", cmd_merge_ours, RUN_SETUP | NO_PARSEOPT }, { "merge-one-file", cmd_merge_one_file, RUN_SETUP | NEED_WORK_TREE | NO_PARSEOPT }, { "merge-recursive", cmd_merge_recursive, RUN_SETUP | NEED_WORK_TREE | NO_PARSEOPT }, diff --git a/merge-strategies.c b/merge-strategies.c index 6b4b3d03a6..37c662094e 100644 --- a/merge-strategies.c +++ b/merge-strategies.c @@ -1,5 +1,6 @@ #include "cache.h" #include "cache-tree.h" +#include "commit-reach.h" #include "dir.h" #include "ll-merge.h" #include "lockfile.h" @@ -407,3 +408,206 @@ int merge_strategies_resolve(struct repository *r, rollback_lock_file(&lock); return 2; } + +static int fast_forward(struct repository *r, const struct object_id *oids, + int nr, int aggressive) +{ + int i; + struct tree_desc t[MAX_UNPACK_TREES]; + struct unpack_trees_options opts; + struct lock_file lock = LOCK_INIT; + + repo_read_index_preload(r, NULL, 0); + if (refresh_index(r->index, REFRESH_QUIET, NULL, NULL, NULL)) + return -1; + + repo_hold_locked_index(r, &lock, LOCK_DIE_ON_ERROR); + + memset(&opts, 0, sizeof(opts)); + opts.head_idx = 1; + opts.src_index = r->index; + opts.dst_index = r->index; + opts.merge = 1; + opts.update = 1; + opts.aggressive = aggressive; + + for (i = 0; i < nr; i++) { + struct tree *tree; + tree = parse_tree_indirect(oids + i); + if (parse_tree(tree)) + return -1; + init_tree_desc(t + i, tree->buffer, tree->size); + } + + if (nr == 1) + opts.fn = oneway_merge; + else if (nr == 2) { + opts.fn = twoway_merge; + opts.initial_checkout = is_index_unborn(r->index); + } else if (nr >= 3) { + opts.fn = threeway_merge; + opts.head_idx = nr - 1; + } + + if (unpack_trees(nr, t, &opts)) + return -1; + + if (write_locked_index(r->index, &lock, COMMIT_LOCK)) + return error(_("unable to write new index file")); + + return 0; +} + +static int write_tree(struct repository *r, struct tree **reference_tree) +{ + struct object_id oid; + int ret; + + ret = write_index_as_tree(&oid, r->index, r->index_file, 0, NULL); + if (!ret) + *reference_tree = lookup_tree(r, &oid); + + return ret; +} + +int merge_strategies_octopus(struct repository *r, + struct commit_list *bases, const char *head_arg, + struct commit_list *remotes) +{ + int non_ff_merge = 0, ret = 0, references = 1; + struct commit **reference_commit; + struct tree *reference_tree; + struct commit_list *j; + struct object_id head; + struct strbuf sb = STRBUF_INIT; + + get_oid(head_arg, &head); + + reference_commit = xcalloc(commit_list_count(remotes) + 1, sizeof(struct commit *)); + reference_commit[0] = lookup_commit_reference(r, &head); + reference_tree = repo_get_commit_tree(r, reference_commit[0]); + + if (repo_index_has_changes(r, reference_tree, &sb)) { + error(_("Your local changes to the following files " + "would be overwritten by merge:\n %s"), + sb.buf); + strbuf_release(&sb); + ret = 2; + goto out; + } + + for (j = remotes; j && j->item; j = j->next) { + struct commit *c = j->item; + struct object_id *oid = &c->object.oid; + struct commit_list *common, *k; + char *branch_name; + int can_ff = 1; + + if (ret) { + /* + * We allow only last one to have a + * hand-resolvable conflicts. Last round failed + * and we still had a head to merge. + */ + puts(_("Automated merge did not work.")); + puts(_("Should not be doing an octopus.")); + + ret = 2; + goto out; + } + + branch_name = merge_get_better_branch_name(oid_to_hex(oid)); + common = get_merge_bases_many(c, references, reference_commit); + + if (!common) + die(_("Unable to find common commit with %s"), branch_name); + + for (k = common; k && !oideq(&k->item->object.oid, oid); k = k->next); + + if (k) { + printf(_("Already up to date with %s\n"), branch_name); + free(branch_name); + free_commit_list(common); + continue; + } + + if (!non_ff_merge) { + int i; + + for (i = 0, k = common; k && i < references && can_ff; k = k->next, i++) { + can_ff = oideq(&k->item->object.oid, + &reference_commit[i]->object.oid); + } + } + + if (!non_ff_merge && can_ff) { + /* + * The first head being merged was a + * fast-forward. Advance the reference commit + * to the head being merged, and use that tree + * as the intermediate result of the merge. We + * still need to count this as part of the + * parent set. + */ + struct object_id oids[2]; + printf(_("Fast-forwarding to: %s\n"), branch_name); + + oidcpy(oids, &head); + oidcpy(oids + 1, oid); + + ret = fast_forward(r, oids, 2, 0); + if (ret) { + free(branch_name); + free_commit_list(common); + goto out; + } + + references = 0; + write_tree(r, &reference_tree); + } else { + int i = 0; + struct tree *next = NULL; + struct object_id oids[MAX_UNPACK_TREES]; + + non_ff_merge = 1; + printf(_("Trying simple merge with %s\n"), branch_name); + + for (k = common; k; k = k->next) + oidcpy(oids + (i++), &k->item->object.oid); + + oidcpy(oids + (i++), &reference_tree->object.oid); + oidcpy(oids + (i++), oid); + + if (fast_forward(r, oids, i, 1)) { + ret = 2; + + free(branch_name); + free_commit_list(common); + + goto out; + } + + if (write_tree(r, &next)) { + struct lock_file lock = LOCK_INIT; + + puts(_("Simple merge did not work, trying automatic merge.")); + repo_hold_locked_index(r, &lock, LOCK_DIE_ON_ERROR); + ret = !!merge_all(r->index, 0, 0, merge_one_file_cb, r); + write_locked_index(r->index, &lock, COMMIT_LOCK); + + write_tree(r, &next); + } + + reference_tree = next; + } + + reference_commit[references++] = c; + + free(branch_name); + free_commit_list(common); + } + +out: + free(reference_commit); + return ret; +} diff --git a/merge-strategies.h b/merge-strategies.h index 778f8ce9d6..938411a04e 100644 --- a/merge-strategies.h +++ b/merge-strategies.h @@ -37,5 +37,8 @@ int merge_all(struct index_state *istate, int oneshot, int quiet, int merge_strategies_resolve(struct repository *r, struct commit_list *bases, const char *head_arg, struct commit_list *remote); +int merge_strategies_octopus(struct repository *r, + struct commit_list *bases, const char *head_arg, + struct commit_list *remote); #endif /* MERGE_STRATEGIES_H */ From patchwork Mon Oct 5 12:26:43 2020 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Alban Gruin X-Patchwork-Id: 11816581 Return-Path: Received: from mail.kernel.org (pdx-korg-mail-1.web.codeaurora.org [172.30.200.123]) by pdx-korg-patchwork-2.web.codeaurora.org (Postfix) with ESMTP id 91658112E for ; Mon, 5 Oct 2020 12:27:52 +0000 (UTC) Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by mail.kernel.org (Postfix) with ESMTP id 66CB1208A9 for ; Mon, 5 Oct 2020 12:27:52 +0000 (UTC) Authentication-Results: mail.kernel.org; dkim=pass (2048-bit key) header.d=gmail.com header.i=@gmail.com header.b="SCHCpIWH" Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1726469AbgJEM1v (ORCPT ); Mon, 5 Oct 2020 08:27:51 -0400 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:48778 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1726217AbgJEM1t (ORCPT ); Mon, 5 Oct 2020 08:27:49 -0400 Received: from mail-wm1-x341.google.com (mail-wm1-x341.google.com [IPv6:2a00:1450:4864:20::341]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id 856F6C0613AF for ; Mon, 5 Oct 2020 05:27:48 -0700 (PDT) Received: by mail-wm1-x341.google.com with SMTP id v12so8578378wmh.3 for ; Mon, 05 Oct 2020 05:27:48 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20161025; h=from:to:cc:subject:date:message-id:in-reply-to:references :mime-version:content-transfer-encoding; bh=sjabLEscXQSt36QjKVAcgAVQ781KyGg0xYwQdX+/Zks=; b=SCHCpIWHj8e4eHCVya1k3i1kzHxlDinOvNu0A3U2BO9fz3nL0CxbkHlm15NUqXuN0m P8sv7+DSTqviVveG9KnTbpNxMta45AzfbXRjo7FJs52DqNpkS/Ycpg/u57TuwMoYGz92 FSyWM0/W6LCqWXvr30b5DJtG5Nm/HGc+usdeO8rSAps3O9eUy5fLjF90txkwEiF4iBRI Nn7QYfR025xnwUdUVuZihTTwxJcHxxHYJ8kOsbBonG8hLCG8B9ATXmitfUZAFmD4oq94 d5qff8K2EFdEN2F4+2spQsXSLiUXd9/iV6a2WrJtQSKIQGyw6ToXebjlQybJUVWoJdEA 4yyQ== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-gm-message-state:from:to:cc:subject:date:message-id:in-reply-to :references:mime-version:content-transfer-encoding; bh=sjabLEscXQSt36QjKVAcgAVQ781KyGg0xYwQdX+/Zks=; b=qldzFXlG/mgUSMipDXnQDRFzC/x6TUVu4CBQnS7QD+NtlRPnU9FoYDSw3O0mtDLJlo Oxo0rSBKO9LMeF7ToHfQJ7KNVJ9bvvJU/xucb8mhLSCbMX5jUOBg28mKE2XvR1mYtKuV vUfBgKGSG2g4Bv1Zfg+qakMy6uAzikA8k57VdJVk697v/cWiIIP5pPSQKuAgY7RU5bU1 XdIjw3SI1srN3jRlDkbahsKgTw4n5rvwUFbnvuyJ58P0KcqEswfQXswF56Gfmdh73smg CmidcDRplkR2V+BVBXtp5OkuXnvuqFOht22wEctwRBp/j3H0y1RHz2qy454xtXLBq6G2 d1dA== X-Gm-Message-State: AOAM5310wf2+VIVb+5aN7UHv4EZn2HvJDy7zYX9YivFvg3hUS9SAuu5A 8HQnQTfjdNDiik7VS1hQsOKvQm1yfzE= X-Google-Smtp-Source: ABdhPJzL2xHIuP8sT46Nw1mM+qnXyAoVwfIObTrVjd634fE7TdAoxGzm60YChIDZDXESVGwsFRt12Q== X-Received: by 2002:a7b:c92c:: with SMTP id h12mr16841355wml.121.1601900866958; Mon, 05 Oct 2020 05:27:46 -0700 (PDT) Received: from ylate.lan (atoulouse-654-1-293-21.w86-199.abo.wanadoo.fr. [86.199.76.21]) by smtp.googlemail.com with ESMTPSA id n2sm13270400wma.29.2020.10.05.05.27.45 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Mon, 05 Oct 2020 05:27:46 -0700 (PDT) From: Alban Gruin To: git@vger.kernel.org Cc: Junio C Hamano , phillip.wood@dunelm.org.uk, Alban Gruin Subject: [PATCH v3 08/11] merge: use the "resolve" strategy without forking Date: Mon, 5 Oct 2020 14:26:43 +0200 Message-Id: <20201005122646.27994-9-alban.gruin@gmail.com> X-Mailer: git-send-email 2.20.1 In-Reply-To: <20201005122646.27994-1-alban.gruin@gmail.com> References: <20200901105705.6059-1-alban.gruin@gmail.com> <20201005122646.27994-1-alban.gruin@gmail.com> MIME-Version: 1.0 Precedence: bulk List-ID: X-Mailing-List: git@vger.kernel.org This teaches `git merge' to invoke the "resolve" strategy with a function call instead of forking. Signed-off-by: Alban Gruin --- builtin/merge.c | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/builtin/merge.c b/builtin/merge.c index 9d5359edc2..ddfefd8ce3 100644 --- a/builtin/merge.c +++ b/builtin/merge.c @@ -41,6 +41,7 @@ #include "commit-reach.h" #include "wt-status.h" #include "commit-graph.h" +#include "merge-strategies.h" #define DEFAULT_TWOHEAD (1<<0) #define DEFAULT_OCTOPUS (1<<1) @@ -740,7 +741,10 @@ static int try_merge_strategy(const char *strategy, struct commit_list *common, COMMIT_LOCK | SKIP_IF_UNCHANGED)) die(_("unable to write %s"), get_index_file()); return clean ? 0 : 1; - } else { + } else if (!strcmp(strategy, "resolve")) + return merge_strategies_resolve(the_repository, common, + head_arg, remoteheads); + else { return try_merge_command(the_repository, strategy, xopts_nr, xopts, common, head_arg, remoteheads); From patchwork Mon Oct 5 12:26:44 2020 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Alban Gruin X-Patchwork-Id: 11816593 Return-Path: Received: from mail.kernel.org (pdx-korg-mail-1.web.codeaurora.org [172.30.200.123]) by pdx-korg-patchwork-2.web.codeaurora.org (Postfix) with ESMTP id B62A6618 for ; Mon, 5 Oct 2020 12:28:40 +0000 (UTC) Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by mail.kernel.org (Postfix) with ESMTP id 92F5F2078D for ; Mon, 5 Oct 2020 12:28:40 +0000 (UTC) Authentication-Results: mail.kernel.org; dkim=pass (2048-bit key) header.d=gmail.com header.i=@gmail.com header.b="qttoVSo8" Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1726691AbgJEM2c (ORCPT ); Mon, 5 Oct 2020 08:28:32 -0400 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:48778 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1726362AbgJEM1u (ORCPT ); Mon, 5 Oct 2020 08:27:50 -0400 Received: from mail-wm1-x342.google.com (mail-wm1-x342.google.com [IPv6:2a00:1450:4864:20::342]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id DA0D8C0613CE for ; Mon, 5 Oct 2020 05:27:49 -0700 (PDT) Received: by mail-wm1-x342.google.com with SMTP id e2so8579526wme.1 for ; Mon, 05 Oct 2020 05:27:49 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20161025; h=from:to:cc:subject:date:message-id:in-reply-to:references :mime-version:content-transfer-encoding; bh=56EjVO+wZTopXnAlR4SnRyJwwjdvLiBgA5T16TnpTVA=; b=qttoVSo82hk8Gmn8p81FPFz7gww8qkL57ZQkkP1IXyMGJVsRKTXvUhHxJKrhTIC0oz VpYUqRSPbEJ2uBJ0gZpdlfIvirYJYlWKU6sWJNiNJkLkalXSzjHJytVBj8qb6mYFOOcm Dmqt+TOKZGoBLM4pdzHzFc+0hs0Wb0ZkH2ua5Y4gH1zwSHt1/p1LxzOlNYQlxxhDaf+W JKVih716ReMzkXRPyz1XnLAeK9uPO1/QWkds1zo1yCVb90eTEOtri0I6/Xc48ipgkUYG O86A/LZ14fI59pZ0g2Hv7UI8t2OcOt7QHs3VmS+0pfSmvos9rdnuR9aT2FYx5yyJt9+l FALg== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-gm-message-state:from:to:cc:subject:date:message-id:in-reply-to :references:mime-version:content-transfer-encoding; bh=56EjVO+wZTopXnAlR4SnRyJwwjdvLiBgA5T16TnpTVA=; b=WDWJQ6V6Mj1geOS08Iog71Ye9jrmI34vXQLjsHps0SqpW7qrIjqt1JHqw2/PuIC8Te cFPt4jnH3//Usf7E6tdVSHW2jemyohPigeuuGlYJXVCkdvaWieey1ojvQr7IqN8JmiCR 0JoSLpMsgIFLlkYzqF8YAKtp+kBNECjBbyS5xfwtowlmdn4jKd7swdFmkulvMBHGGj1Z mt46hve5T3E55go/AvMJ995MT5QhIKiQXteyvFuK9hweiSLfEeFbIp6h/8wW+CP+TEKS 4udatx5xRAqbbOTRb+EDof7Ta6z4Yn//9EYsXi8HKCVJVQmxU97nvEh0H7mhrbzWdTS3 VkIA== X-Gm-Message-State: AOAM533I1s/YwX1dXYO+7VORLZWLxmUtUI/qSckInCaYNWP1h0SwwUXk DYxxswMJW6G71QLZ6Ahle2fvTjKe+LM= X-Google-Smtp-Source: ABdhPJwrOJJtWEAfdfNEfEO71geW6JNZ7k+aHl899taynwtYYGzhhvtTg6/0oJ/N02DrSOh24I8dHg== X-Received: by 2002:a1c:f415:: with SMTP id z21mr16679112wma.88.1601900868303; Mon, 05 Oct 2020 05:27:48 -0700 (PDT) Received: from ylate.lan (atoulouse-654-1-293-21.w86-199.abo.wanadoo.fr. [86.199.76.21]) by smtp.googlemail.com with ESMTPSA id n2sm13270400wma.29.2020.10.05.05.27.47 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Mon, 05 Oct 2020 05:27:47 -0700 (PDT) From: Alban Gruin To: git@vger.kernel.org Cc: Junio C Hamano , phillip.wood@dunelm.org.uk, Alban Gruin Subject: [PATCH v3 09/11] merge: use the "octopus" strategy without forking Date: Mon, 5 Oct 2020 14:26:44 +0200 Message-Id: <20201005122646.27994-10-alban.gruin@gmail.com> X-Mailer: git-send-email 2.20.1 In-Reply-To: <20201005122646.27994-1-alban.gruin@gmail.com> References: <20200901105705.6059-1-alban.gruin@gmail.com> <20201005122646.27994-1-alban.gruin@gmail.com> MIME-Version: 1.0 Precedence: bulk List-ID: X-Mailing-List: git@vger.kernel.org This teaches `git merge' to invoke the "octopus" strategy with a function call instead of forking. Signed-off-by: Alban Gruin --- builtin/merge.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/builtin/merge.c b/builtin/merge.c index ddfefd8ce3..02a2367647 100644 --- a/builtin/merge.c +++ b/builtin/merge.c @@ -744,6 +744,9 @@ static int try_merge_strategy(const char *strategy, struct commit_list *common, } else if (!strcmp(strategy, "resolve")) return merge_strategies_resolve(the_repository, common, head_arg, remoteheads); + else if (!strcmp(strategy, "octopus")) + return merge_strategies_octopus(the_repository, common, + head_arg, remoteheads); else { return try_merge_command(the_repository, strategy, xopts_nr, xopts, From patchwork Mon Oct 5 12:26:45 2020 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Alban Gruin X-Patchwork-Id: 11816587 Return-Path: Received: from mail.kernel.org (pdx-korg-mail-1.web.codeaurora.org [172.30.200.123]) by pdx-korg-patchwork-2.web.codeaurora.org (Postfix) with ESMTP id EA202112E for ; Mon, 5 Oct 2020 12:28:17 +0000 (UTC) Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by mail.kernel.org (Postfix) with ESMTP id CB8632078D for ; Mon, 5 Oct 2020 12:28:17 +0000 (UTC) Authentication-Results: mail.kernel.org; dkim=pass (2048-bit key) header.d=gmail.com header.i=@gmail.com header.b="Bu3iU65B" Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1726641AbgJEM2O (ORCPT ); Mon, 5 Oct 2020 08:28:14 -0400 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:48796 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1725981AbgJEM1v (ORCPT ); Mon, 5 Oct 2020 08:27:51 -0400 Received: from mail-wr1-x442.google.com (mail-wr1-x442.google.com [IPv6:2a00:1450:4864:20::442]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id EC56FC0613CE for ; Mon, 5 Oct 2020 05:27:50 -0700 (PDT) Received: by mail-wr1-x442.google.com with SMTP id e18so3435858wrw.9 for ; Mon, 05 Oct 2020 05:27:50 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20161025; h=from:to:cc:subject:date:message-id:in-reply-to:references :mime-version:content-transfer-encoding; bh=mb9tLYVsaEjYwo9yQTDbfBTN4/5xWRH6g0bAbuFD01I=; b=Bu3iU65B46o9u11J4R004DWiZ5Mk/HVEG3X4qLFDhCQrxxUcnxNUNV3jXrDI0xCyj2 kTT4biqGXlJL5Bkx/9FvnB4kMAB3X/rNx0l5eZpAbX20v0zsw21SR2SFl/OkTOQoRO6U GxrW0rdUUvFo0s79ItHBtVB6Ro9LTJYe/E/L0mfMQsHz5Czj4u0l1NyzVD1KqusGeQUA z+C+RIgD43C5Ziq7mx6yMeLnwWj0Bh0cFGrrGYF+PJku+iXzQyvfESL1siLtlhTuqlkM YW4ntIuzAsdnCEOXSiotTU6vVH3S9Ev+lx+O7vH8t1hC5nD3Lxkhsjqyclm5gFt6AwU6 4tJA== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-gm-message-state:from:to:cc:subject:date:message-id:in-reply-to :references:mime-version:content-transfer-encoding; bh=mb9tLYVsaEjYwo9yQTDbfBTN4/5xWRH6g0bAbuFD01I=; b=uiisrPbVFy0tjjpoDSlq65vfrPcY+KEWMMbXNFHclmEqV9mDFmmKQQnGqe+uftrRcZ +qYVJMOPVsUmbeADhr7bjJaj50lyKonJPGMD+ocF+am6oyEkKg9Efii88tsD+0R1Qzjz C6lv88rt/2o7UxAADumY/lqJg90eXCy0PADwqYw+cNjVofgdxLqyvJmqfG5TS/Aew7iq dJmj5fWmkPsdTpfwyvnC8C2lkq0Eo0dwaPLorp4UcjctBOY3A6g2RyXlB82UIAE/80qE kBTWrFzzzmSJm6NWF9oMIXGoaRM7D+Bi1ocV6RgBnrzsc4ChzHi6ZNtPqi1LwdxgSa0k QmFQ== X-Gm-Message-State: AOAM533UPEIfb7mjQF0x3y/9azH+IjKom/6Zl+CX0VmiGTPpQt6CSXQz FW2G9F/Dmc8DrWjvjRRr/W6r0br4BVk= X-Google-Smtp-Source: ABdhPJzRLZDOIsQaG/AkJiAwqroo3nUAn3jXKkKtJFVrS6cjceOT04Bik1V9eeY6E778LUaVAp2D9g== X-Received: by 2002:a5d:40c3:: with SMTP id b3mr7734042wrq.157.1601900869424; Mon, 05 Oct 2020 05:27:49 -0700 (PDT) Received: from ylate.lan (atoulouse-654-1-293-21.w86-199.abo.wanadoo.fr. [86.199.76.21]) by smtp.googlemail.com with ESMTPSA id n2sm13270400wma.29.2020.10.05.05.27.48 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Mon, 05 Oct 2020 05:27:48 -0700 (PDT) From: Alban Gruin To: git@vger.kernel.org Cc: Junio C Hamano , phillip.wood@dunelm.org.uk, Alban Gruin Subject: [PATCH v3 10/11] sequencer: use the "resolve" strategy without forking Date: Mon, 5 Oct 2020 14:26:45 +0200 Message-Id: <20201005122646.27994-11-alban.gruin@gmail.com> X-Mailer: git-send-email 2.20.1 In-Reply-To: <20201005122646.27994-1-alban.gruin@gmail.com> References: <20200901105705.6059-1-alban.gruin@gmail.com> <20201005122646.27994-1-alban.gruin@gmail.com> MIME-Version: 1.0 Precedence: bulk List-ID: X-Mailing-List: git@vger.kernel.org This teaches the sequencer to invoke the "resolve" strategy with a function call instead of forking. Signed-off-by: Alban Gruin --- sequencer.c | 13 ++++++++++--- 1 file changed, 10 insertions(+), 3 deletions(-) diff --git a/sequencer.c b/sequencer.c index e8676e965f..ff411d54af 100644 --- a/sequencer.c +++ b/sequencer.c @@ -33,6 +33,7 @@ #include "commit-reach.h" #include "rebase-interactive.h" #include "reset.h" +#include "merge-strategies.h" #define GIT_REFLOG_ACTION "GIT_REFLOG_ACTION" @@ -2000,9 +2001,15 @@ static int do_pick_commit(struct repository *r, commit_list_insert(base, &common); commit_list_insert(next, &remotes); - res |= try_merge_command(r, opts->strategy, - opts->xopts_nr, (const char **)opts->xopts, - common, oid_to_hex(&head), remotes); + + if (!strcmp(opts->strategy, "resolve")) { + repo_read_index(r); + res |= merge_strategies_resolve(r, common, oid_to_hex(&head), remotes); + } else + res |= try_merge_command(r, opts->strategy, + opts->xopts_nr, (const char **)opts->xopts, + common, oid_to_hex(&head), remotes); + free_commit_list(common); free_commit_list(remotes); } From patchwork Mon Oct 5 12:26:46 2020 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Alban Gruin X-Patchwork-Id: 11816583 Return-Path: Received: from mail.kernel.org (pdx-korg-mail-1.web.codeaurora.org [172.30.200.123]) by pdx-korg-patchwork-2.web.codeaurora.org (Postfix) with ESMTP id 4DC13618 for ; Mon, 5 Oct 2020 12:28:10 +0000 (UTC) Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by mail.kernel.org (Postfix) with ESMTP id 2A88E2078D for ; Mon, 5 Oct 2020 12:28:10 +0000 (UTC) Authentication-Results: mail.kernel.org; dkim=pass (2048-bit key) header.d=gmail.com header.i=@gmail.com header.b="Jl1OjyYR" Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1726597AbgJEM2A (ORCPT ); Mon, 5 Oct 2020 08:28:00 -0400 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:48802 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1726517AbgJEM1w (ORCPT ); Mon, 5 Oct 2020 08:27:52 -0400 Received: from mail-wr1-x443.google.com (mail-wr1-x443.google.com [IPv6:2a00:1450:4864:20::443]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id 02AF8C0613A8 for ; Mon, 5 Oct 2020 05:27:52 -0700 (PDT) Received: by mail-wr1-x443.google.com with SMTP id e18so3435913wrw.9 for ; Mon, 05 Oct 2020 05:27:51 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20161025; h=from:to:cc:subject:date:message-id:in-reply-to:references :mime-version:content-transfer-encoding; bh=cIMY4obEMVT1HyovhuoLTYqtYdv+pCw5tXwxpQnpBl8=; b=Jl1OjyYRyoRO08+TH3oQnOUEVwnVTjO9tpKqgj30B+l9pEsixmyk7nOciPk+GPGj6g pSRoh/AL0I41Ahxr9iFQkV2qt/T1WSYlboJbUGaIaLzk+jTo5vIvgK5hNurFx+mIIiOy jPwLAqWxNNaKiNWuMxnNkJ1ZkfyWl8O4gh5ylpviJfUIvq+wI5mPa+msWBi8C2851pDC 8x3Uvw+iir+L2TbRBRikcF1ci5mu0oqz1MNPsFPxtyz4XBOZcb5ipzvlo/sodfw2BxGP iPKxgNmNyQvgcIa3f32Ox2FeIT7141/jZRNMHfly6u9SKpPTWsGgEmrZ+YVH3Gepl8/E 0w3Q== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-gm-message-state:from:to:cc:subject:date:message-id:in-reply-to :references:mime-version:content-transfer-encoding; bh=cIMY4obEMVT1HyovhuoLTYqtYdv+pCw5tXwxpQnpBl8=; b=RCTUcpg7mbcQbsGgmu6j2vJx/e1yU13If+MFGglW8JF+CZCbeN0KyKpOUVC6MeAMEx YU2sPZ0X5c6Jb0T1NIpzWWIryhZtg8Ed72dCz8QWgM2jdm6gNYwu9BPy+NGT1NJfNQ7/ odQgt0r+i8EcPrpXQx/cRwnJdy89M4Wex57ghBHUBt4I727D7OTfTS83z9JUmafb5bw8 9QU8FfPSNEogM4mo+r1LkESPiIi4OlkQWmMuIPZ2/0wb7cILrsg5mgWrC5fK/9dvCpCc FhMw67+HAu0UIN4EtAHU18Xsar6kDCqENzg/3VlfqONfTBuHeKedrlvOKgH3KQz3+rW2 /Gkg== X-Gm-Message-State: AOAM530+ZubpmOp3UeZgAe5dYmHPvZRdSqS2YwWaviZx0YCXc5NZDn0X s+s187/SUaRlmPKuWMqro0+l6GuwBEs= X-Google-Smtp-Source: ABdhPJyMX+WZCEKvPPcigdq1YfWdF0zak5lk2lvtxnelO//0uWjtfv+qxUi2TVcmE/0jGaotXq+RiQ== X-Received: by 2002:adf:ce8e:: with SMTP id r14mr17406467wrn.257.1601900870452; Mon, 05 Oct 2020 05:27:50 -0700 (PDT) Received: from ylate.lan (atoulouse-654-1-293-21.w86-199.abo.wanadoo.fr. [86.199.76.21]) by smtp.googlemail.com with ESMTPSA id n2sm13270400wma.29.2020.10.05.05.27.49 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Mon, 05 Oct 2020 05:27:49 -0700 (PDT) From: Alban Gruin To: git@vger.kernel.org Cc: Junio C Hamano , phillip.wood@dunelm.org.uk, Alban Gruin Subject: [PATCH v3 11/11] sequencer: use the "octopus" merge strategy without forking Date: Mon, 5 Oct 2020 14:26:46 +0200 Message-Id: <20201005122646.27994-12-alban.gruin@gmail.com> X-Mailer: git-send-email 2.20.1 In-Reply-To: <20201005122646.27994-1-alban.gruin@gmail.com> References: <20200901105705.6059-1-alban.gruin@gmail.com> <20201005122646.27994-1-alban.gruin@gmail.com> MIME-Version: 1.0 Precedence: bulk List-ID: X-Mailing-List: git@vger.kernel.org This teaches the sequencer to invoke the "octopus" strategy with a function call instead of forking. Signed-off-by: Alban Gruin --- sequencer.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/sequencer.c b/sequencer.c index ff411d54af..746afad930 100644 --- a/sequencer.c +++ b/sequencer.c @@ -2005,6 +2005,9 @@ static int do_pick_commit(struct repository *r, if (!strcmp(opts->strategy, "resolve")) { repo_read_index(r); res |= merge_strategies_resolve(r, common, oid_to_hex(&head), remotes); + } else if (!strcmp(opts->strategy, "octopus")) { + repo_read_index(r); + res |= merge_strategies_octopus(r, common, oid_to_hex(&head), remotes); } else res |= try_merge_command(r, opts->strategy, opts->xopts_nr, (const char **)opts->xopts,