From patchwork Fri Nov 13 11:04:17 2020 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Alban Gruin X-Patchwork-Id: 11903191 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org X-Spam-Level: X-Spam-Status: No, score=-12.6 required=3.0 tests=BAYES_00,DKIM_SIGNED, DKIM_VALID,DKIM_VALID_AU,FREEMAIL_FORGED_FROMDOMAIN,FREEMAIL_FROM, HEADER_FROM_DIFFERENT_DOMAINS,INCLUDES_PATCH,MAILING_LIST_MULTI,SIGNED_OFF_BY, SPF_HELO_NONE,SPF_PASS,URIBL_BLOCKED,USER_AGENT_GIT autolearn=ham autolearn_force=no version=3.4.0 Received: from mail.kernel.org (mail.kernel.org [198.145.29.99]) by smtp.lore.kernel.org (Postfix) with ESMTP id E18F1C388F7 for ; Fri, 13 Nov 2020 12:10:51 +0000 (UTC) Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by mail.kernel.org (Postfix) with ESMTP id 86EC322240 for ; Fri, 13 Nov 2020 12:10:51 +0000 (UTC) Authentication-Results: mail.kernel.org; dkim=pass (2048-bit key) header.d=gmail.com header.i=@gmail.com header.b="MLp7Cmss" Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1726546AbgKMMKu (ORCPT ); Fri, 13 Nov 2020 07:10:50 -0500 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:36880 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1726465AbgKMMKt (ORCPT ); Fri, 13 Nov 2020 07:10:49 -0500 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 F37D4C0617A6 for ; Fri, 13 Nov 2020 04:10:48 -0800 (PST) Received: by mail-wm1-x341.google.com with SMTP id w24so8284390wmi.0 for ; Fri, 13 Nov 2020 04:10:48 -0800 (PST) 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=7NKR8/TOOCNoRIdKvR8AV7cjS9Gl1SgDrV3MY2xgjQI=; b=MLp7CmssfOK6F1r6SC4pbfZnIYq2DOIynDbzYoP58fPLUuq2oCiubD5c2DP2GvM5y+ n1AtM5O1HEpGRvTCk+TG4BgOmjYQz2nZf1SVH7mpEtj31ayHTLQbdUuJJZtrnKyGkm/u kPRakRAu7vFaDmPaKb1sE0kz/DiJ241pFrnRbr+wKcsrTfUyXI7iggm6W5uFG+mfiVAs ksCUzUjxlzXlUGmNEg/4bJ2Z19WCi8h+C0/1bo9XmWYgqOBJRtRF+9XBEh5mkUdMcK85 cnf4GjrVTcs07V+/ea17tat+kTRPY7XrYgFmK2xkqVSGI/Xa2Fv/Sz57mmoDWrXJCEdh ECJA== 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=7NKR8/TOOCNoRIdKvR8AV7cjS9Gl1SgDrV3MY2xgjQI=; b=nYHHk32FLLyIopcYM564diFDMT0RLTrZ0bKpH6JfsfcsiJGl0GlnR6mP5l3VfnaNcp ivvLF39OgMliSURgE4ZPIBJVGDEPDlAzw6SmfLZOhHRT3FK7mThKNFMIoEsus5K2EOY7 sPRqu7BbbKc+OWXIiN+8MAA2n2kE+AG8gXnaV5ZCYd06jasmsTJdtnxRkUEZnM2lPi9O oXjuIroz8G7iSor1NYaTb8SW9xQIjLiRhuclLYr644xfLzZbtEMXnAJKIbmviGCPYbkn FlBLrXNMNGLSkhjx+msbnNPd5qtLExFFV09rgyNzyEQctpjeeH+gPgVuvehEwuYGqJZe hyhQ== X-Gm-Message-State: AOAM533BwG7Wm+7d3pUABwZ5KYGP4Fvkl499FDOykVtA+1jagn29i/vj P5SFxwIrKga7fN9LAsQt3bcJi24kquk= X-Google-Smtp-Source: ABdhPJzNQDXJvTSgztsxuPCo1obB1VAYsEZIcEb3FferJfB/LLPaNtVM5mlpBYy2O86I9nX4dZpAVQ== X-Received: by 2002:a1c:bbc4:: with SMTP id l187mr2348576wmf.133.1605269447519; Fri, 13 Nov 2020 04:10:47 -0800 (PST) Received: from ylate.lan (atoulouse-654-1-426-233.w2-6.abo.wanadoo.fr. [2.6.209.233]) by smtp.googlemail.com with ESMTPSA id g138sm10083697wme.39.2020.11.13.04.10.46 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Fri, 13 Nov 2020 04:10:47 -0800 (PST) From: Alban Gruin To: git@vger.kernel.org Cc: Junio C Hamano , Phillip Wood , Alban Gruin Subject: [PATCH v4 01/12] t6027: modernise tests Date: Fri, 13 Nov 2020 12:04:17 +0100 Message-Id: <20201113110428.21265-2-alban.gruin@gmail.com> X-Mailer: git-send-email 2.20.1 In-Reply-To: <20201113110428.21265-1-alban.gruin@gmail.com> References: <20201005122646.27994-1-alban.gruin@gmail.com> <20201113110428.21265-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 Fri Nov 13 11:04:18 2020 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Alban Gruin X-Patchwork-Id: 11903197 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org X-Spam-Level: X-Spam-Status: No, score=-12.6 required=3.0 tests=BAYES_00,DKIM_SIGNED, DKIM_VALID,DKIM_VALID_AU,FREEMAIL_FORGED_FROMDOMAIN,FREEMAIL_FROM, HEADER_FROM_DIFFERENT_DOMAINS,INCLUDES_PATCH,MAILING_LIST_MULTI,SIGNED_OFF_BY, SPF_HELO_NONE,SPF_PASS,USER_AGENT_GIT autolearn=ham autolearn_force=no version=3.4.0 Received: from mail.kernel.org (mail.kernel.org [198.145.29.99]) by smtp.lore.kernel.org (Postfix) with ESMTP id B23FCC56202 for ; Fri, 13 Nov 2020 12:10:52 +0000 (UTC) Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by mail.kernel.org (Postfix) with ESMTP id 6DF942078B for ; Fri, 13 Nov 2020 12:10:52 +0000 (UTC) Authentication-Results: mail.kernel.org; dkim=pass (2048-bit key) header.d=gmail.com header.i=@gmail.com header.b="GiAA2Jby" Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1726553AbgKMMKv (ORCPT ); Fri, 13 Nov 2020 07:10:51 -0500 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:36884 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1726443AbgKMMKu (ORCPT ); Fri, 13 Nov 2020 07:10:50 -0500 Received: from mail-wm1-x32e.google.com (mail-wm1-x32e.google.com [IPv6:2a00:1450:4864:20::32e]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id 4D38CC0617A7 for ; Fri, 13 Nov 2020 04:10:50 -0800 (PST) Received: by mail-wm1-x32e.google.com with SMTP id a65so8262862wme.1 for ; Fri, 13 Nov 2020 04:10:50 -0800 (PST) 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=XF1TFkYKb09IuVXVkVvH6iskGxmP9cD0WNFS1Kly3iE=; b=GiAA2JbyRN0hcRNsuGlKnWZbv/IGfDbSdOHG750lfUYRNmxP486gwJuY/e61736qA9 D/5PKebIGb+Vh+l11xKLWT4B4DrjrVHD30Rpdd/7rJv+DTUhQhUBMJSj0Shrm3O2x7je fK5ov/j/cRHsXdwY+gGGtKOILDg6+XEVW65gEbZyfuAba5tGRgrIiItmu+iqpsvn79+o hTiUyXBUYJR1bIlcf5lc0+pimQXU2MhHZZFKYV3JPrna+U6IHO2ueshANHSGDFJrjRMQ MQAxK0X/i5hcK5JaFtBRMxJY6Ll/kBlc7W3ICu9603wHxfmTgWD0Segp+ySiqqBfsqUb xcLA== 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=XF1TFkYKb09IuVXVkVvH6iskGxmP9cD0WNFS1Kly3iE=; b=QUA7HOb7fhjoeSWXQ9eB0NSjof9xXZccul2FNwNZ+ynqxX+arE3Z8UR1nd+Qk9i5D8 mcG15wX3SSMn6ZDrrOqeQxfm6KpGX6P8ETSHeE/Bax+qksm8pROadp7tSnqBfG0yJPeK Cd46Qpq94xFkUDoRF3+gzijVDGI+JZhJbNBThYnQwe1yU6w1U+kTrcE4D1JBJH3FJLNC CKBM9SvNOh9WbMALJAJE0FfhDidewg6FULSCaYaMkQL8MU7wxDGkosS/WJJe33K0qCTV O5B5E+DxrD3DmjK9BRxpTR2NrLaWAibFQ3HuRr6/os6hsnz3zLnzFmOI4uVwwxK1xaXk IxnQ== X-Gm-Message-State: AOAM5323T6mxsiRdcNFe8OyvUfj9qMmjHoAUt1gAZNrF8obpMIB6JZF7 BtQzHoGUaeLC/VM6UezZfxKIgH0+kB0= X-Google-Smtp-Source: ABdhPJyKc/qT+ujq/G9PeohxQFBi7oVLGJZijI287Xj5DknEtfGDSjRXGCSSwjNaJKJ/hMs5r4/1+Q== X-Received: by 2002:a1c:80cb:: with SMTP id b194mr2239930wmd.73.1605269448593; Fri, 13 Nov 2020 04:10:48 -0800 (PST) Received: from ylate.lan (atoulouse-654-1-426-233.w2-6.abo.wanadoo.fr. [2.6.209.233]) by smtp.googlemail.com with ESMTPSA id g138sm10083697wme.39.2020.11.13.04.10.47 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Fri, 13 Nov 2020 04:10:48 -0800 (PST) From: Alban Gruin To: git@vger.kernel.org Cc: Junio C Hamano , Phillip Wood , Alban Gruin Subject: [PATCH v4 02/12] update-index: move add_cacheinfo() to read-cache.c Date: Fri, 13 Nov 2020 12:04:18 +0100 Message-Id: <20201113110428.21265-3-alban.gruin@gmail.com> X-Mailer: git-send-email 2.20.1 In-Reply-To: <20201113110428.21265-1-alban.gruin@gmail.com> References: <20201005122646.27994-1-alban.gruin@gmail.com> <20201113110428.21265-1-alban.gruin@gmail.com> MIME-Version: 1.0 Precedence: bulk List-ID: X-Mailing-List: git@vger.kernel.org This moves the function add_cacheinfo() that already exists in update-index.c to update-index.c, renames it add_to_index_cacheinfo(), and adds an `istate' parameter. The new cache entry is returned through a pointer passed in the parameters. The return value is either 0 (success), -1 (invalid path), or -2 (failed to add the file in the index). This will become useful in the next commit, when the three-way merge will need to call this function. Signed-off-by: Alban Gruin --- builtin/update-index.c | 25 +++++++------------------ cache.h | 5 +++++ read-cache.c | 35 +++++++++++++++++++++++++++++++++++ 3 files changed, 47 insertions(+), 18 deletions(-) diff --git a/builtin/update-index.c b/builtin/update-index.c index 79087bccea..44862f5e1d 100644 --- a/builtin/update-index.c +++ b/builtin/update-index.c @@ -404,27 +404,16 @@ static int process_path(const char *path, struct stat *st, int stat_errno) static int add_cacheinfo(unsigned int mode, const struct object_id *oid, const char *path, int stage) { - int len, option; - struct cache_entry *ce; + int res; - if (!verify_path(path, mode)) - return error("Invalid path '%s'", path); - - len = strlen(path); - ce = make_empty_cache_entry(&the_index, len); - - oidcpy(&ce->oid, oid); - memcpy(ce->name, path, len); - ce->ce_flags = create_ce_flags(stage); - ce->ce_namelen = len; - ce->ce_mode = create_ce_mode(mode); - if (assume_unchanged) - ce->ce_flags |= CE_VALID; - option = allow_add ? ADD_CACHE_OK_TO_ADD : 0; - option |= allow_replace ? ADD_CACHE_OK_TO_REPLACE : 0; - if (add_cache_entry(ce, option)) + res = add_to_index_cacheinfo(&the_index, mode, oid, path, stage, + allow_add, allow_replace, NULL); + if (res == -1) + return res; + if (res == -2) return error("%s: cannot add to the index - missing --add option?", path); + report("add '%s'", path); return 0; } diff --git a/cache.h b/cache.h index c0072d43b1..be16ab3215 100644 --- a/cache.h +++ b/cache.h @@ -830,6 +830,11 @@ int remove_file_from_index(struct index_state *, const char *path); int add_to_index(struct index_state *, const char *path, struct stat *, int flags); int add_file_to_index(struct index_state *, const char *path, int flags); +int add_to_index_cacheinfo(struct index_state *, unsigned int mode, + const struct object_id *oid, const char *path, + int stage, int allow_add, int allow_replace, + struct cache_entry **pce); + int chmod_index_entry(struct index_state *, struct cache_entry *ce, char flip); int ce_same_name(const struct cache_entry *a, const struct cache_entry *b); void set_object_name_for_intent_to_add_entry(struct cache_entry *ce); diff --git a/read-cache.c b/read-cache.c index ecf6f68994..c25f951db4 100644 --- a/read-cache.c +++ b/read-cache.c @@ -1350,6 +1350,41 @@ int add_index_entry(struct index_state *istate, struct cache_entry *ce, int opti return 0; } +int add_to_index_cacheinfo(struct index_state *istate, unsigned int mode, + const struct object_id *oid, const char *path, + int stage, int allow_add, int allow_replace, + struct cache_entry **pce) +{ + int len, option; + struct cache_entry *ce = NULL; + + 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(stage); + ce->ce_namelen = len; + ce->ce_mode = create_ce_mode(mode); + if (assume_unchanged) + ce->ce_flags |= CE_VALID; + option = allow_add ? ADD_CACHE_OK_TO_ADD : 0; + option |= allow_replace ? ADD_CACHE_OK_TO_REPLACE : 0; + + if (add_index_entry(istate, ce, option)) { + discard_cache_entry(ce); + return -2; + } + + if (pce) + *pce = ce; + + return 0; +} + /* * "refresh" does not calculate a new sha1 file or bring the * cache up-to-date for mode/content changes. But what it From patchwork Fri Nov 13 11:04:19 2020 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Alban Gruin X-Patchwork-Id: 11903183 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org X-Spam-Level: X-Spam-Status: No, score=-12.6 required=3.0 tests=BAYES_00,DKIM_SIGNED, DKIM_VALID,DKIM_VALID_AU,FREEMAIL_FORGED_FROMDOMAIN,FREEMAIL_FROM, HEADER_FROM_DIFFERENT_DOMAINS,INCLUDES_PATCH,MAILING_LIST_MULTI,SIGNED_OFF_BY, SPF_HELO_NONE,SPF_PASS,URIBL_BLOCKED,USER_AGENT_GIT autolearn=ham autolearn_force=no version=3.4.0 Received: from mail.kernel.org (mail.kernel.org [198.145.29.99]) by smtp.lore.kernel.org (Postfix) with ESMTP id 01F1BC388F7 for ; Fri, 13 Nov 2020 12:10:58 +0000 (UTC) Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by mail.kernel.org (Postfix) with ESMTP id 996A322240 for ; Fri, 13 Nov 2020 12:10:57 +0000 (UTC) Authentication-Results: mail.kernel.org; dkim=pass (2048-bit key) header.d=gmail.com header.i=@gmail.com header.b="b2pBsPAI" Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1726557AbgKMMK4 (ORCPT ); Fri, 13 Nov 2020 07:10:56 -0500 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:36892 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1726443AbgKMMKx (ORCPT ); Fri, 13 Nov 2020 07:10:53 -0500 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 759D7C0613D1 for ; Fri, 13 Nov 2020 04:10:52 -0800 (PST) Received: by mail-wr1-x443.google.com with SMTP id 33so9593620wrl.7 for ; Fri, 13 Nov 2020 04:10:52 -0800 (PST) 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=lplqWk8OD6gy1Z79jgyAfJNr4cHv2o5utpGFFN7YCbw=; b=b2pBsPAIYVotxuE/E22xDn/bvNkMCjs6G6ZOcbOPnbP0HYY4RfQsllOvJV7c6tdXQ/ UCcDig6wtDdeUXa7Z84tcjGlKmcPvOc1vs7Sqepv3kENSAHpPXfXyN6jVglJXotktO3C JFgk3dH0W/JXYQLR2f4ipb7vfZ/YVzmETLywS53jeDRlDJDfz3FvzvMw5UyHOQmkGHgG oFsO0cWTlo9SHiAjghTwxKbrgmwssx/vXovnfGe8ujYIkoYm6wxDTic/gcxicvfNh/W5 qeKBhBrxBpkLQiSAU8hfKoqdM24TK60YBqnJQIRcEMNs9rN4mcj4EAynTBjUMwdV1/i8 kXjw== 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=lplqWk8OD6gy1Z79jgyAfJNr4cHv2o5utpGFFN7YCbw=; b=haDXhXkA31xCYDixA/o3XPOk4V0C4p90/hu2hldEQkRrmqZtoIpSywyihP15MAMEVF dz/i3s+Xnnatf7BUOvTFRNL8Es8y/vE3FD12FBHD6Qdsm9fWoA0E85Hz0FFFgzjC9HS9 xI5uh2BURSTCLvwAXFbLfniQrBBoz5+zpux44cCodP9GTVV/TAotHfOE7F0vjRpaLfVv rgEH6O+bN0Ul4qUN7fOF9V192FL5dnc2WvWzVlIALTeApsw1QG3ZXXVdtyzpQyP5CBFp EcruWwwxQ8uyrmjSvgZ3pEUHQvBg+357uVj5I7qh4qNWHDxplWPfMftGRObNBbevZhpr mZWw== X-Gm-Message-State: AOAM533vvCm8PhzvPCJwZmGSY9W0/3H4SNm3XSwC42lK59dnj4goUOxc azlRvg2AD6jTtKDW3Mci2UVs6JwhVHA= X-Google-Smtp-Source: ABdhPJwsE+M1723z76rlsTVhLATBS7MGUM+ldGZ+3TvzvCo2raYAhLVVtDpUpz2niZs6J9xXskNB8g== X-Received: by 2002:a5d:448a:: with SMTP id j10mr2974441wrq.33.1605269450474; Fri, 13 Nov 2020 04:10:50 -0800 (PST) Received: from ylate.lan (atoulouse-654-1-426-233.w2-6.abo.wanadoo.fr. [2.6.209.233]) by smtp.googlemail.com with ESMTPSA id g138sm10083697wme.39.2020.11.13.04.10.48 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Fri, 13 Nov 2020 04:10:49 -0800 (PST) From: Alban Gruin To: git@vger.kernel.org Cc: Junio C Hamano , Phillip Wood , Alban Gruin Subject: [PATCH v4 03/12] merge-one-file: rewrite in C Date: Fri, 13 Nov 2020 12:04:19 +0100 Message-Id: <20201113110428.21265-4-alban.gruin@gmail.com> X-Mailer: git-send-email 2.20.1 In-Reply-To: <20201113110428.21265-1-alban.gruin@gmail.com> References: <20201005122646.27994-1-alban.gruin@gmail.com> <20201113110428.21265-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_to_index_cacheinfo(); - calls to `update-index --remove' are replaced by calls to remove_file_from_index(); - 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 xdl_merge(), respectively, to merge files in-memory; - calls to `checkout-index -f --stage=2' are removed, as this is needed to have the correct permission bits on the merged file from the script, but not in the C version; - calls to `update-index' are replaced by calls to add_file_to_index(). 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 | 94 +++++++++++++++++ git-merge-one-file.sh | 167 ------------------------------ git.c | 1 + merge-strategies.c | 173 ++++++++++++++++++++++++++++++++ merge-strategies.h | 12 +++ t/t6415-merge-dir-to-symlink.sh | 2 +- 8 files changed, 284 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..9c21778e1d --- /dev/null +++ b/builtin/merge-one-file.c @@ -0,0 +1,94 @@ +/* + * 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 object name (or empty) + * argv[2] - file in branch1 object name (or empty) + * argv[3] - file in branch2 object name (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_hex(argv[1], &orig_blob)) { + p_orig_blob = &orig_blob; + ret = read_mode("orig", argv[5], &orig_mode); + } else if (!*argv[1] && *argv[5]) + ret = error(_("no 'orig' object id given, but a mode was still given.")); + + if (!get_oid_hex(argv[2], &our_blob)) { + p_our_blob = &our_blob; + ret = read_mode("our", argv[6], &our_mode); + } else if (!*argv[2] && *argv[6]) + ret = error(_("no 'our' object id given, but a mode was still given.")); + + if (!get_oid_hex(argv[3], &their_blob)) { + p_their_blob = &their_blob; + ret = read_mode("their", argv[7], &their_mode); + } else if (!*argv[3] && *argv[7]) + ret = error(_("no 'their' object id given, but a mode was still given.")); + + if (ret) + return ret; + + ret = merge_three_way(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..f5fdb15bbf --- /dev/null +++ b/merge-strategies.c @@ -0,0 +1,173 @@ +#include "cache.h" +#include "dir.h" +#include "merge-strategies.h" +#include "xdiff-interface.h" + +static int checkout_from_index(struct index_state *istate, const char *path, + struct cache_entry *ce) +{ + struct checkout state = CHECKOUT_INIT; + + state.istate = istate; + state.force = 1; + state.base_dir = ""; + state.base_dir_len = 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 *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]; + xmparam_t xmp = {{0}}; + + 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); + else if (our_mode != their_mode) + return error(_("permission conflict: %o->%o,%o in %s"), + orig_mode, our_mode, their_mode, path); + + 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); + } + + read_mmblob(mmfs + 1, our_blob); + read_mmblob(mmfs + 2, their_blob); + + xmp.level = XDL_MERGE_ZEALOUS_ALNUM; + xmp.style = 0; + xmp.favor = 0; + + ret = xdl_merge(mmfs + 0, mmfs + 1, mmfs + 2, &xmp, &result); + + for (i = 0; i < 3; i++) + free(mmfs[i].ptr); + + if (ret < 0) { + free(result.ptr); + return error(_("Failed to execute internal merge")); + } else if (ret > 0 || !orig_blob) { + free(result.ptr); + return error(_("content conflict in %s"), path); + } + + unlink(path); + if ((dest = open(path, O_WRONLY | O_CREAT, our_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); + + return add_file_to_index(istate, path, 0); +} + +int merge_three_way(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, 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, 0, 1, 1, NULL); + } else if (!orig_blob && !our_blob && their_blob) { + struct cache_entry *ce; + 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, 0, 1, 1, &ce)) + return -1; + return checkout_from_index(r->index, path, ce); + } else if (!orig_blob && our_blob && their_blob && + oideq(our_blob, their_blob)) { + struct cache_entry *ce; + + /* 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, 0, 1, 1, &ce)) + return -1; + return checkout_from_index(r->index, path, ce); + } 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..e624c4f27c --- /dev/null +++ b/merge-strategies.h @@ -0,0 +1,12 @@ +#ifndef MERGE_STRATEGIES_H +#define MERGE_STRATEGIES_H + +#include "object.h" + +int merge_three_way(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 Fri Nov 13 11:04:20 2020 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Alban Gruin X-Patchwork-Id: 11903193 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org X-Spam-Level: X-Spam-Status: No, score=-12.6 required=3.0 tests=BAYES_00,DKIM_SIGNED, DKIM_VALID,DKIM_VALID_AU,FREEMAIL_FORGED_FROMDOMAIN,FREEMAIL_FROM, HEADER_FROM_DIFFERENT_DOMAINS,INCLUDES_PATCH,MAILING_LIST_MULTI,SIGNED_OFF_BY, SPF_HELO_NONE,SPF_PASS,USER_AGENT_GIT autolearn=ham autolearn_force=no version=3.4.0 Received: from mail.kernel.org (mail.kernel.org [198.145.29.99]) by smtp.lore.kernel.org (Postfix) with ESMTP id A1F6CC63697 for ; Fri, 13 Nov 2020 12:10:59 +0000 (UTC) Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by mail.kernel.org (Postfix) with ESMTP id 65BB82224C for ; Fri, 13 Nov 2020 12:10:59 +0000 (UTC) Authentication-Results: mail.kernel.org; dkim=pass (2048-bit key) header.d=gmail.com header.i=@gmail.com header.b="rjXNm1lH" Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1726593AbgKMMK5 (ORCPT ); Fri, 13 Nov 2020 07:10:57 -0500 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:36906 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1726558AbgKMMK4 (ORCPT ); Fri, 13 Nov 2020 07:10:56 -0500 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 5764BC0613D1 for ; Fri, 13 Nov 2020 04:10:56 -0800 (PST) Received: by mail-wm1-x344.google.com with SMTP id c9so7903443wml.5 for ; Fri, 13 Nov 2020 04:10:56 -0800 (PST) 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=1YpVyg+L2WumoA2BhyTuTLloEC541IqEs9MhNB3Bt/A=; b=rjXNm1lHaZ6sBNovXWZsRVbtVBlMGe1k5/biVtIMFg0wE6467263X55X4qdg4Z8vzv 9y9CioCn6TnVmQBJQBAp/r5iitlLBXOTgg5KWN2Y+/CDuIMtCXOWPbamgeRVNA/pE7W1 HO59W9YKegpvRheBHZjk/kCSb3Ib+Jp0SMU4S5wQwMpK5pCv6YLL4uWQH5yvrWzBXWtL 5V+LjFnhxdtSIumcAJbEs1dUqMCeOnQOnscANglqfOPDLupNEgCXvcumgbzHEisDj8ug EmWcMN+cPnA0ApJA4HY+qGbNItEATVlT5wDyrd2uzltTLAOF6VYtoiwfyGQN8h/Bdkl8 Eaqw== 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=1YpVyg+L2WumoA2BhyTuTLloEC541IqEs9MhNB3Bt/A=; b=t6/ZlQwNcnxBDMNylRFr/cU7GUQSyoVplgYSlRpQx6w1T/wDEUubvQpqbrJoCa6a37 9Zh5bRQq+qdBBDbMem56XI8aDEM0z7PXu9C/vQFpVddLH6H+rBzOZeowSHQlA3ySeTmG ieSeZOBG1LSrXwMpBPq2fBh4mnD/rFlFLecLgTrBN+hlJL+Sihg7n0FyUzplzOGMZTby +JK3wPR0QtO4qECqsXd7fglL4zuq9Z4nMxJ2b+CLPhVit5nrkud9u61+KwY4LyJ4Y7Wx maKzY0fXI6kimh4jxWWHQNSHS+Eh2tRx+GHZByU1uB8qXKaJyW6sqadKFUJ8WMxW2BBi Nkig== X-Gm-Message-State: AOAM532sypQFXUc45V0EBDH5A/9j24OK7UKtOHHYD+tNcWoOX8ajkQJY 6vIrgriKTKF0dIdqE0d/W28fMIdEk2A= X-Google-Smtp-Source: ABdhPJxo7UVItjzhwuLWmcvTs15gHB2DFEgFTjqrBhYmPolc7+RZ66nYVlowAkO1rkGeqEGCYBOupw== X-Received: by 2002:a1c:df8a:: with SMTP id w132mr2242374wmg.90.1605269451823; Fri, 13 Nov 2020 04:10:51 -0800 (PST) Received: from ylate.lan (atoulouse-654-1-426-233.w2-6.abo.wanadoo.fr. [2.6.209.233]) by smtp.googlemail.com with ESMTPSA id g138sm10083697wme.39.2020.11.13.04.10.50 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Fri, 13 Nov 2020 04:10:51 -0800 (PST) From: Alban Gruin To: git@vger.kernel.org Cc: Junio C Hamano , Phillip Wood , Alban Gruin Subject: [PATCH v4 04/12] merge-index: libify merge_one_path() and merge_all() Date: Fri, 13 Nov 2020 12:04:20 +0100 Message-Id: <20201113110428.21265-5-alban.gruin@gmail.com> X-Mailer: git-send-email 2.20.1 In-Reply-To: <20201113110428.21265-1-alban.gruin@gmail.com> References: <20201005122646.27994-1-alban.gruin@gmail.com> <20201113110428.21265-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 and renames 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 | 103 ++++++++++++++++++++++++++++++++++++++++++ merge-strategies.h | 17 +++++++ 3 files changed, 127 insertions(+), 70 deletions(-) diff --git a/builtin/merge-index.c b/builtin/merge-index.c index 38ea6ad6ca..49e3382fb9 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_index(&the_index, one_shot, quiet, + merge_one_file_spawn, (void *)pgm); continue; } die("git merge-index: unknown option %s", arg); } - merge_one_path(arg); + err |= merge_index_path(&the_index, one_shot, quiet, arg, + merge_one_file_spawn, (void *)pgm); } - if (err && !quiet) - die("merge program failed"); return err; } diff --git a/merge-strategies.c b/merge-strategies.c index f5fdb15bbf..e1d121c993 100644 --- a/merge-strategies.c +++ b/merge-strategies.c @@ -1,6 +1,7 @@ #include "cache.h" #include "dir.h" #include "merge-strategies.h" +#include "run-command.h" #include "xdiff-interface.h" static int checkout_from_index(struct index_state *istate, const char *path, @@ -171,3 +172,105 @@ int merge_three_way(struct repository *r, return 0; } + +int merge_one_file_spawn(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 oids[3][GIT_MAX_HEXSZ + 1] = {{0}}; + char modes[3][10] = {{0}}; + const char *arguments[] = { (char *)data, oids[0], oids[1], oids[2], + path, modes[0], modes[1], modes[2], NULL }; + + if (orig_blob) { + oid_to_hex_r(oids[0], orig_blob); + xsnprintf(modes[0], sizeof(modes[0]), "%06o", orig_mode); + } + + if (our_blob) { + oid_to_hex_r(oids[1], our_blob); + xsnprintf(modes[1], sizeof(modes[1]), "%06o", our_mode); + } + + if (their_blob) { + oid_to_hex_r(oids[2], their_blob); + xsnprintf(modes[2], sizeof(modes[2]), "%06o", 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_fn fn, 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 (fn(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_index_path(struct index_state *istate, int oneshot, int quiet, + const char *path, merge_fn fn, 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, fn, data); + if (ret == -1) + return -1; + else if (ret == -2) + return 1; + } + return 0; +} + +int merge_all_index(struct index_state *istate, int oneshot, int quiet, + merge_fn fn, 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, fn, 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 e624c4f27c..d2f52d6792 100644 --- a/merge-strategies.h +++ b/merge-strategies.h @@ -9,4 +9,21 @@ int merge_three_way(struct repository *r, const struct object_id *their_blob, const char *path, unsigned int orig_mode, unsigned int our_mode, unsigned int their_mode); +typedef int (*merge_fn)(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_file_spawn(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_index_path(struct index_state *istate, int oneshot, int quiet, + const char *path, merge_fn fn, void *data); +int merge_all_index(struct index_state *istate, int oneshot, int quiet, + merge_fn fn, void *data); + #endif /* MERGE_STRATEGIES_H */ From patchwork Fri Nov 13 11:04:21 2020 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Alban Gruin X-Patchwork-Id: 11903199 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org X-Spam-Level: X-Spam-Status: No, score=-12.6 required=3.0 tests=BAYES_00,DKIM_SIGNED, DKIM_VALID,DKIM_VALID_AU,FREEMAIL_FORGED_FROMDOMAIN,FREEMAIL_FROM, HEADER_FROM_DIFFERENT_DOMAINS,INCLUDES_PATCH,MAILING_LIST_MULTI,SIGNED_OFF_BY, SPF_HELO_NONE,SPF_PASS,USER_AGENT_GIT autolearn=ham autolearn_force=no version=3.4.0 Received: from mail.kernel.org (mail.kernel.org [198.145.29.99]) by smtp.lore.kernel.org (Postfix) with ESMTP id D94CAC388F7 for ; Fri, 13 Nov 2020 12:11:07 +0000 (UTC) Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by mail.kernel.org (Postfix) with ESMTP id 99F682224C for ; Fri, 13 Nov 2020 12:11:07 +0000 (UTC) Authentication-Results: mail.kernel.org; dkim=pass (2048-bit key) header.d=gmail.com header.i=@gmail.com header.b="FqeK/7Hx" Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1726644AbgKMMLG (ORCPT ); Fri, 13 Nov 2020 07:11:06 -0500 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:36902 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1726633AbgKMMLF (ORCPT ); Fri, 13 Nov 2020 07:11:05 -0500 Received: from mail-wr1-x441.google.com (mail-wr1-x441.google.com [IPv6:2a00:1450:4864:20::441]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id 14A39C0617A6 for ; Fri, 13 Nov 2020 04:10:55 -0800 (PST) Received: by mail-wr1-x441.google.com with SMTP id u12so2377463wrt.0 for ; Fri, 13 Nov 2020 04:10:55 -0800 (PST) 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=UiyC54l9v2XbmUn2Eb9DWlWjmAiu3dBfYmc0opmC7/0=; b=FqeK/7Hxdtfn1JR5qKSaDy2EIK46ZbB9FbMpz+4RWFXarMMBezmChjDofJPPrANFmF cD6HOgs6pftAzQhsbjc6DiNiZxzLKW020WVC2LSKvdpSF55+JAUYWZ9v18aIibma5ZlS ZuiC+iq40mUpI3JzEo/HU//5a3lr35t1YWVAityGRIJa7VIdnFLAXC4/yXLFpujdpqqx 4paFwj0PT2rOCUaLrdFU5GitlfAhxp54L13JSBVNTeD6AxevYpkDKcFnFy+xZAYeBiUV dH2o5fSA00YIfNCFyNy7u/MqyjYd6EMCOdjeAzxGIvt0Z+CdVaAklP4dBQ0nYwB4Whjl ky8g== 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=UiyC54l9v2XbmUn2Eb9DWlWjmAiu3dBfYmc0opmC7/0=; b=mmooI8L6rjkuouKEf5Lr42X/fjLuEKipq7bFJ+GEpEDuPgoAngmkes8asLNTyMSYdv i4U1RH38REz2AD5tXEBdW8IOVPTlUqlUH02cwFwULr7pjcxYssb2vpUYvEHf9/1iA2/b 1Mnj/x3PiuKcqxlmYackuopcY4XsWAVql4bkr3WMx8DlKQ4E6KxPFBibGxaomKm3VMNl +dXyUcO3xGl94LMrqJrBD1FFtNVbRnkT1/0VVcqf3vDnToGlpot3pWummE+yeK+GpEL2 H8uzLj++P3S5jCwoTtBRy0xtYwdkmlYp+wp859QElCG2Sd+OkAGrjRcJbAD8GARSM+SW Q8HQ== X-Gm-Message-State: AOAM530+yozflHtqor+BZwIIzLo3MpWFpNJvAZXr9nWGlIfIz00/333J h5O8SXimixcWreEuwNDFYY+p9vlFrgE= X-Google-Smtp-Source: ABdhPJydHckGJEV30u5wmV0FHYjnuwMYPgWBhqp3rHxtxKiBY6BD5/QllS/2v6dDiX0G34wvY4UrHQ== X-Received: by 2002:a5d:4409:: with SMTP id z9mr3017449wrq.309.1605269453571; Fri, 13 Nov 2020 04:10:53 -0800 (PST) Received: from ylate.lan (atoulouse-654-1-426-233.w2-6.abo.wanadoo.fr. [2.6.209.233]) by smtp.googlemail.com with ESMTPSA id g138sm10083697wme.39.2020.11.13.04.10.51 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Fri, 13 Nov 2020 04:10:52 -0800 (PST) From: Alban Gruin To: git@vger.kernel.org Cc: Junio C Hamano , Phillip Wood , Alban Gruin Subject: [PATCH v4 05/12] merge-index: don't fork if the requested program is `git-merge-one-file' Date: Fri, 13 Nov 2020 12:04:21 +0100 Message-Id: <20201113110428.21265-6-alban.gruin@gmail.com> X-Mailer: git-send-email 2.20.1 In-Reply-To: <20201113110428.21265-1-alban.gruin@gmail.com> References: <20201005122646.27994-1-alban.gruin@gmail.com> <20201113110428.21265-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_three_way() without forking using a new callback, merge_one_file_func(). 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 49e3382fb9..e684811d35 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_fn 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_func; + data = (void *)the_repository; + + setup_work_tree(); + hold_locked_index(&lock, LOCK_DIE_ON_ERROR); + } else { + merge_action = merge_one_file_spawn; + 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_index(&the_index, one_shot, quiet, - merge_one_file_spawn, (void *)pgm); + merge_action, data); continue; } die("git merge-index: unknown option %s", arg); } err |= merge_index_path(&the_index, one_shot, quiet, arg, - merge_one_file_spawn, (void *)pgm); + merge_action, data); + } + + if (merge_action == merge_one_file_func) { + 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 e1d121c993..aa31b7045c 100644 --- a/merge-strategies.c +++ b/merge-strategies.c @@ -173,6 +173,17 @@ int merge_three_way(struct repository *r, return 0; } +int merge_one_file_func(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_three_way((struct repository *)data, + orig_blob, our_blob, their_blob, path, + orig_mode, our_mode, their_mode); +} + int merge_one_file_spawn(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 d2f52d6792..b69a12b390 100644 --- a/merge-strategies.h +++ b/merge-strategies.h @@ -15,6 +15,12 @@ typedef int (*merge_fn)(const struct object_id *orig_blob, unsigned int orig_mode, unsigned int our_mode, unsigned int their_mode, void *data); +int merge_one_file_func(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_file_spawn(const struct object_id *orig_blob, const struct object_id *our_blob, const struct object_id *their_blob, const char *path, From patchwork Fri Nov 13 11:04:22 2020 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Alban Gruin X-Patchwork-Id: 11903185 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org X-Spam-Level: X-Spam-Status: No, score=-12.6 required=3.0 tests=BAYES_00,DKIM_SIGNED, DKIM_VALID,DKIM_VALID_AU,FREEMAIL_FORGED_FROMDOMAIN,FREEMAIL_FROM, HEADER_FROM_DIFFERENT_DOMAINS,INCLUDES_PATCH,MAILING_LIST_MULTI,SIGNED_OFF_BY, SPF_HELO_NONE,SPF_PASS,URIBL_BLOCKED,USER_AGENT_GIT autolearn=ham autolearn_force=no version=3.4.0 Received: from mail.kernel.org (mail.kernel.org [198.145.29.99]) by smtp.lore.kernel.org (Postfix) with ESMTP id 83502C56202 for ; Fri, 13 Nov 2020 12:10:59 +0000 (UTC) Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by mail.kernel.org (Postfix) with ESMTP id 215C422240 for ; Fri, 13 Nov 2020 12:10:59 +0000 (UTC) Authentication-Results: mail.kernel.org; dkim=pass (2048-bit key) header.d=gmail.com header.i=@gmail.com header.b="Spq679yT" Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1726600AbgKMMK6 (ORCPT ); Fri, 13 Nov 2020 07:10:58 -0500 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:36908 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1726443AbgKMMK5 (ORCPT ); Fri, 13 Nov 2020 07:10:57 -0500 Received: from mail-wr1-x441.google.com (mail-wr1-x441.google.com [IPv6:2a00:1450:4864:20::441]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id A0B3DC0617A7 for ; Fri, 13 Nov 2020 04:10:56 -0800 (PST) Received: by mail-wr1-x441.google.com with SMTP id b6so9607960wrt.4 for ; Fri, 13 Nov 2020 04:10:56 -0800 (PST) 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=tzV2CGDbpfCGD8P4Bcx+JKrijTpClHVDpR1EZUYiGuw=; b=Spq679yTQlxgkINxY8kCl31J+V/DrngAFVpX5n/CMaEoPG05xbq9B1csMqMGdRLpGg TLxvNMhmX75jhG0iQqu4OG1p7VTfck+zs8qNvx17Ny1KMyCsG2n+o4nxeavF/jAfj9bz Gdn23ztixSDST+jbjPkI8fA+D6puOZ5CFgzx9kTvxRPR+2u1sqgfcLXGsH1Px/elwWV6 7cpy6vD0QaYc2dJSYIZHu4qIpMDpGbrBXgaw/kPz162m2BgMo6WPL9+qtKHvtTXDwaD+ 8wwG9WNEO8rdz/MwrabY03h8+6sITPcd8zMbqk4mv3WCsK2JvqQrSD2GEahl1YNavlgo qELw== 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=tzV2CGDbpfCGD8P4Bcx+JKrijTpClHVDpR1EZUYiGuw=; b=peEu2L+W/xZf7BzM0DwnkweFLo5bgy71rfMPafD6XCImdS16EgBbdvyPtSgefRhuME W7ov/ReE2sQpsEdcTIes/x6pW1NM+CqPHDvoCFpS2aKVQlvQV8ImGFsm06pOUkUj1R7q 7TQpUdAWyCHi4+JzhYdwrCBM5VOMqZ8j+IrEiNJY//u0WCESrD/TUhIU+aTuvAFeZnD0 qU6oLQqI6+6nST4ZWwJ5BZkKaPP0OWlCZEn0xK7DS+iw5sJt78L2q/tBr0V/6cjOucJq NzpgkSE6a5Rj9ItIg3NPDa+LtUetKWAtQchVN8Kuc7WOz5V5sc+5c//vC4mrN8aKWPcR CaQQ== X-Gm-Message-State: AOAM533FaFO9yhIDIESQf1ztiMQytuTpJh4NNbL5UvV94iWJfb+LOmpM 8e6Mdqq53mKQohKiZkvq8CQZXFjh1iM= X-Google-Smtp-Source: ABdhPJxPTZvhOaP6vDU1fFwZ6OwxwQevmRJJ4AAsBb/ex+4GKZIcqj++jtEn2kuq37P2cVSBYfCE7Q== X-Received: by 2002:adf:db0f:: with SMTP id s15mr3112081wri.354.1605269454822; Fri, 13 Nov 2020 04:10:54 -0800 (PST) Received: from ylate.lan (atoulouse-654-1-426-233.w2-6.abo.wanadoo.fr. [2.6.209.233]) by smtp.googlemail.com with ESMTPSA id g138sm10083697wme.39.2020.11.13.04.10.53 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Fri, 13 Nov 2020 04:10:54 -0800 (PST) From: Alban Gruin To: git@vger.kernel.org Cc: Junio C Hamano , Phillip Wood , Alban Gruin Subject: [PATCH v4 06/12] merge-resolve: rewrite in C Date: Fri, 13 Nov 2020 12:04:22 +0100 Message-Id: <20201113110428.21265-7-alban.gruin@gmail.com> X-Mailer: git-send-email 2.20.1 In-Reply-To: <20201113110428.21265-1-alban.gruin@gmail.com> References: <20201005122646.27994-1-alban.gruin@gmail.com> <20201113110428.21265-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_index() function. The index is read in cmd_merge_resolve(), and is wrote back by merge_strategies_resolve(). 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 | 73 +++++++++++++++++++++++++++++++++++ git-merge-resolve.sh | 54 -------------------------- git.c | 1 + merge-strategies.c | 85 +++++++++++++++++++++++++++++++++++++++++ merge-strategies.h | 5 +++ 7 files changed, 166 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..dca31676b8 --- /dev/null +++ b/builtin/merge-resolve.c @@ -0,0 +1,73 @@ +/* + * 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. + */ + +#define USE_THE_INDEX_COMPATIBILITY_MACROS +#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, 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 (read_cache() < 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], "--")) + sep_seen = 1; + else if (!strcmp(argv[i], "-h")) + usage(builtin_merge_resolve_usage); + else if (sep_seen && !head) + head = argv[i]; + else { + struct object_id oid; + struct commit *commit; + + if (get_oid(argv[i], &oid)) + die("object %s not found.", argv[i]); + + commit = lookup_commit_or_die(&oid, argv[i]); + + if (sep_seen) + commit_list_insert(commit, &remote); + else + next_base = commit_list_append(commit, next_base); + } + } + + /* + * Give up if we are given two or more remotes. Not handling + * octopus. + */ + if (remote && remote->next) + return 2; + + /* Give up if this is a baseless merge. */ + if (!bases) + 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 aa31b7045c..2b34ea0b76 100644 --- a/merge-strategies.c +++ b/merge-strategies.c @@ -1,7 +1,10 @@ #include "cache.h" +#include "cache-tree.h" #include "dir.h" +#include "lockfile.h" #include "merge-strategies.h" #include "run-command.h" +#include "unpack-trees.h" #include "xdiff-interface.h" static int checkout_from_index(struct index_state *istate, const char *path, @@ -285,3 +288,85 @@ int merge_all_index(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_index(r->index, 0, 0, merge_one_file_func, 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 b69a12b390..4f996261b4 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_three_way(struct repository *r, @@ -32,4 +33,8 @@ int merge_index_path(struct index_state *istate, int oneshot, int quiet, int merge_all_index(struct index_state *istate, int oneshot, int quiet, merge_fn fn, 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 Fri Nov 13 11:04:23 2020 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Alban Gruin X-Patchwork-Id: 11903189 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org X-Spam-Level: X-Spam-Status: No, score=-12.6 required=3.0 tests=BAYES_00,DKIM_SIGNED, DKIM_VALID,DKIM_VALID_AU,FREEMAIL_FORGED_FROMDOMAIN,FREEMAIL_FROM, HEADER_FROM_DIFFERENT_DOMAINS,INCLUDES_PATCH,MAILING_LIST_MULTI,SIGNED_OFF_BY, SPF_HELO_NONE,SPF_PASS,USER_AGENT_GIT autolearn=ham autolearn_force=no version=3.4.0 Received: from mail.kernel.org (mail.kernel.org [198.145.29.99]) by smtp.lore.kernel.org (Postfix) with ESMTP id B1837C63699 for ; Fri, 13 Nov 2020 12:11:00 +0000 (UTC) Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by mail.kernel.org (Postfix) with ESMTP id 75D9822240 for ; Fri, 13 Nov 2020 12:11:00 +0000 (UTC) Authentication-Results: mail.kernel.org; dkim=pass (2048-bit key) header.d=gmail.com header.i=@gmail.com header.b="YnvdTaMO" Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1726610AbgKMMK7 (ORCPT ); Fri, 13 Nov 2020 07:10:59 -0500 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:36906 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1726558AbgKMMK5 (ORCPT ); Fri, 13 Nov 2020 07:10:57 -0500 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 86541C0613D1 for ; Fri, 13 Nov 2020 04:10:57 -0800 (PST) Received: by mail-wm1-x341.google.com with SMTP id a65so8263509wme.1 for ; Fri, 13 Nov 2020 04:10:57 -0800 (PST) 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=erCmlE+BY3YMPeBRvPZQFAVR4wjD0xnNAA1juWeRcK8=; b=YnvdTaMOkmlN5A2K3UBMTbxthGY1qvNREgw+gediHUwoMalAi3XwBRg6LapDTbRz+5 oCPZsdRCwz8/7FymozPOroecQ04SS/AChhChkRO/xpULFZqXXY6MwJdHPi8EF3xZREr/ 20O7HAQiOB8NO7pfxpCP1EE2BVzTOp3tcPPaxg16kOlMs72JDk4gNwu9pUsBhP30llkc ZGfK6Yw1Kz8ASaYQkUPujVdDbHby4dKWwy7/zTPbRG/BWXxRsCrF438fzLVoGG4hoGXe kybQFU+WVCW8+fuHKiLgrG2p5enYyq64yft+ceJMFqdOXrU0esJ7O7y1KGsNaupg+PZp lCXw== 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=erCmlE+BY3YMPeBRvPZQFAVR4wjD0xnNAA1juWeRcK8=; b=eVqTmN1LVOkEl9WlubB3s+QEh03nRt+uoSn89QefyBaE/f1VTKq+oIQ5F5hQv3dmTG /eO6JeIYN19VXb6E7AZ8O39KevEJMI06W2ybVj1VMUYBKlfLsfPXKPbV261rs/7TtEW/ JTHPGaM2cwWcE4N9q7yBD7IyYQilZzlpXBHX9ep2TbfY91lBVBTHQCzhJwn1Ukq8JGOO 0xKBs8j4ZlisWt+8cxcmd+plENP19vQd+gkddIyvzX9VoKczAk1wReAWr+id7PlbGlQg ESHZW9pSuT9n88hAPeiw3r77mjVHfjOW59cazNwhocmiB2Crd14cyNcZDIetHqEuiIqe ZOQg== X-Gm-Message-State: AOAM532SsmVsr8naao0a/4V9zLoq+shILC74NhaYZD0qw675dpNECzqC WdneJ2QbngzebtarGQR1A2q7GyA+GAk= X-Google-Smtp-Source: ABdhPJyDZUs7AOKTef6WnaWY7MRcj3JqWD5zHOq+F56uo1XcwXDb1F7k298rlakwJTcxIve7IdBp7g== X-Received: by 2002:a1c:2bc3:: with SMTP id r186mr2112203wmr.163.1605269455995; Fri, 13 Nov 2020 04:10:55 -0800 (PST) Received: from ylate.lan (atoulouse-654-1-426-233.w2-6.abo.wanadoo.fr. [2.6.209.233]) by smtp.googlemail.com with ESMTPSA id g138sm10083697wme.39.2020.11.13.04.10.54 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Fri, 13 Nov 2020 04:10:55 -0800 (PST) From: Alban Gruin To: git@vger.kernel.org Cc: Junio C Hamano , Phillip Wood , Alban Gruin Subject: [PATCH v4 07/12] merge-recursive: move better_branch_name() to merge.c Date: Fri, 13 Nov 2020 12:04:23 +0100 Message-Id: <20201113110428.21265-8-alban.gruin@gmail.com> X-Mailer: git-send-email 2.20.1 In-Reply-To: <20201113110428.21265-1-alban.gruin@gmail.com> References: <20201005122646.27994-1-alban.gruin@gmail.com> <20201113110428.21265-1-alban.gruin@gmail.com> MIME-Version: 1.0 Precedence: bulk List-ID: X-Mailing-List: git@vger.kernel.org better_branch_name() will be used by merge-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 be16ab3215..2d844576ea 100644 --- a/cache.h +++ b/cache.h @@ -1933,7 +1933,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 Fri Nov 13 11:04:24 2020 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Alban Gruin X-Patchwork-Id: 11903187 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org X-Spam-Level: X-Spam-Status: No, score=-12.6 required=3.0 tests=BAYES_00,DKIM_SIGNED, DKIM_VALID,DKIM_VALID_AU,FREEMAIL_FORGED_FROMDOMAIN,FREEMAIL_FROM, HEADER_FROM_DIFFERENT_DOMAINS,INCLUDES_PATCH,MAILING_LIST_MULTI,SIGNED_OFF_BY, SPF_HELO_NONE,SPF_PASS,URIBL_BLOCKED,USER_AGENT_GIT autolearn=ham autolearn_force=no version=3.4.0 Received: from mail.kernel.org (mail.kernel.org [198.145.29.99]) by smtp.lore.kernel.org (Postfix) with ESMTP id EA235C6369E for ; Fri, 13 Nov 2020 12:11:01 +0000 (UTC) Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by mail.kernel.org (Postfix) with ESMTP id AFB5022240 for ; Fri, 13 Nov 2020 12:11:01 +0000 (UTC) Authentication-Results: mail.kernel.org; dkim=pass (2048-bit key) header.d=gmail.com header.i=@gmail.com header.b="gxmGwfVw" Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1726618AbgKMMLA (ORCPT ); Fri, 13 Nov 2020 07:11:00 -0500 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:36906 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1726558AbgKMMK7 (ORCPT ); Fri, 13 Nov 2020 07:10:59 -0500 Received: from mail-wr1-x42a.google.com (mail-wr1-x42a.google.com [IPv6:2a00:1450:4864:20::42a]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id 47C26C0613D1 for ; Fri, 13 Nov 2020 04:10:59 -0800 (PST) Received: by mail-wr1-x42a.google.com with SMTP id 23so9578312wrc.8 for ; Fri, 13 Nov 2020 04:10:59 -0800 (PST) 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=d0nzshtNtD7SjI7l1q22L0Lp93ke/YHDRpGSv2fk3cw=; b=gxmGwfVwnOcgQuPYhh5YgkipdJbXNUmIXsibhWW5smNBHoevxjX/W0mjrbez8SL7hl wzGBKnia0XRo4TbxiKseaeDODqRa7NZhZCV+NAhPw6iCELUyecC0Z5b4sOgdyjFUjduA rJkfCXQZEk2BVRwpMQsTvhgGSxIvMEFzPOPt1fRAtuR3ezGSGovzFUAT42wjhPCvNZYN 7fAh42OAEyXkNrPzRqL3Iq+dxtDgYOcW+xHqkRhnhmS23TjIzHXP9eZyMCYKI/4dzs9H 9CLncj1pob77D0qZoAcLVY2gH18gYvluu42HpIY5/ZYKSX6ZyeqENSStHIajJqsxgrX7 TThA== 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=d0nzshtNtD7SjI7l1q22L0Lp93ke/YHDRpGSv2fk3cw=; b=lP/Wpb839aiISQtUbqC+ngN9LDVcJYFbsNcbfSk5lKKMitYMLwYKhZiHp6Ue5nk/so JQbF7rJG+erirTKbv9vUgHWxaxR74PJNE9EWt89HO0T0mdN0DFb5J6lfwPVNBjlsVH4m dEb+fNdGCwV6aXDO2INfWlVRnVdWnVFr0L/gs2Flp78gdWIcKWz6HiWF+RslllbJeZ06 8eVWSLw0qxJMA542Zvj9xTREj0RoERbGg46oykH9FHGZb1CHqvC0s1oTE5NI7dYanoa7 GEGM93dTonlduCZ4t6AO6FMzApmAJcGHKqVzLntrfUSxVqVh7Fl6dI165Bf3HSRvmQzF OaLw== X-Gm-Message-State: AOAM532+qxNU9WsrOCsSGcBsWgbpsblXiSDgPX3ZK0iASR1wL9oeNXAE 0Gx3FRwfnTpP/vjKzfqXKTiLq2GgArA= X-Google-Smtp-Source: ABdhPJwV3Z/mv54ZpDaxOXWDuW+2Fg9xguXcC5AGKtLrZ9/ENpOzi/97q1AtmDlM4lunIMbfbQbg/Q== X-Received: by 2002:adf:84a6:: with SMTP id 35mr3143170wrg.18.1605269457449; Fri, 13 Nov 2020 04:10:57 -0800 (PST) Received: from ylate.lan (atoulouse-654-1-426-233.w2-6.abo.wanadoo.fr. [2.6.209.233]) by smtp.googlemail.com with ESMTPSA id g138sm10083697wme.39.2020.11.13.04.10.56 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Fri, 13 Nov 2020 04:10:56 -0800 (PST) From: Alban Gruin To: git@vger.kernel.org Cc: Junio C Hamano , Phillip Wood , Alban Gruin Subject: [PATCH v4 08/12] merge-octopus: rewrite in C Date: Fri, 13 Nov 2020 12:04:24 +0100 Message-Id: <20201113110428.21265-9-alban.gruin@gmail.com> X-Mailer: git-send-email 2.20.1 In-Reply-To: <20201113110428.21265-1-alban.gruin@gmail.com> References: <20201005122646.27994-1-alban.gruin@gmail.com> <20201113110428.21265-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(). - The call to `merge-index', needed to invoke `git merge-one-file', is replaced by a call to merge_all_index(). 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..ca8f9f345d --- /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. + */ + +#define USE_THE_INDEX_COMPATIBILITY_MACROS +#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 (read_cache() < 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_octopus_usage); + else if (sep_seen && !head_arg) + head_arg = argv[i]; + else { + struct object_id oid; + struct commit *commit; + + if (get_oid(argv[i], &oid)) + die("object %s not found.", argv[i]); + + 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 2b34ea0b76..2ae27f4a80 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 "lockfile.h" #include "merge-strategies.h" @@ -370,3 +371,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_index(r->index, 0, 0, merge_one_file_func, 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 4f996261b4..05232a5a89 100644 --- a/merge-strategies.h +++ b/merge-strategies.h @@ -36,5 +36,8 @@ int merge_all_index(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 Fri Nov 13 11:04:25 2020 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Alban Gruin X-Patchwork-Id: 11903205 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org X-Spam-Level: X-Spam-Status: No, score=-12.6 required=3.0 tests=BAYES_00,DKIM_SIGNED, DKIM_VALID,DKIM_VALID_AU,FREEMAIL_FORGED_FROMDOMAIN,FREEMAIL_FROM, HEADER_FROM_DIFFERENT_DOMAINS,INCLUDES_PATCH,MAILING_LIST_MULTI,SIGNED_OFF_BY, SPF_HELO_NONE,SPF_PASS,USER_AGENT_GIT autolearn=ham autolearn_force=no version=3.4.0 Received: from mail.kernel.org (mail.kernel.org [198.145.29.99]) by smtp.lore.kernel.org (Postfix) with ESMTP id C5EFDC4742C for ; Fri, 13 Nov 2020 12:11:13 +0000 (UTC) Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by mail.kernel.org (Postfix) with ESMTP id 8A08422240 for ; Fri, 13 Nov 2020 12:11:13 +0000 (UTC) Authentication-Results: mail.kernel.org; dkim=pass (2048-bit key) header.d=gmail.com header.i=@gmail.com header.b="oxrRUPvL" Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1726654AbgKMMLL (ORCPT ); Fri, 13 Nov 2020 07:11:11 -0500 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:36920 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1726603AbgKMMLK (ORCPT ); Fri, 13 Nov 2020 07:11:10 -0500 Received: from mail-wm1-x343.google.com (mail-wm1-x343.google.com [IPv6:2a00:1450:4864:20::343]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id 230AAC0617A7 for ; Fri, 13 Nov 2020 04:11:00 -0800 (PST) Received: by mail-wm1-x343.google.com with SMTP id h62so8248052wme.3 for ; Fri, 13 Nov 2020 04:11:00 -0800 (PST) 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=3pdkU+TcWfmw3HAdbGVR8mr5o0BL0LqEIUu3y24P5vM=; b=oxrRUPvLPU7FQyJ+Af7JRguYXSj95T/9SuoQBZ8rdwBECeuqpWsTMF7hSDEYTdysMS BEMPvkGnqr3Bl64gaDyzu1nSwkfDMEyxeRhhMLbS1g4PuMWO+6ZhZB51AMbNlDLbmFmp /TVWsecRI5TAYYuCyQv+T3Jn0h5WJr6FuMdJlqOxKxe6+LaHCZIrqXXhaBPq2eXBCVP/ /Vn4ke0T3YePX0glpf3QA71a1lmftJGY5155i783a3kp74uRSt6x51rg2sFq8bRhBEsZ rm6Y9b2MpiIAdyKBFOBBrVgTaL5joJgMaAOyiyNhHTZvs1TIOIgE2Ge7TURdZy99JwaS SU2Q== 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=3pdkU+TcWfmw3HAdbGVR8mr5o0BL0LqEIUu3y24P5vM=; b=eH0GqkMXe27Igr1TXufQV0st5aJPZkMhYdM504kcZZcJSom6T6+GtD6DtZOeCNF4wj 6RNlifJuTUkJhb61GHRV8DMEvx7m2KAi4W/3++BWmq8o0cDlVJcL5uA/xYoREo53veII OH9V0rsnAQeaFg9RAyGTRvKariL9Id+Ijx9ms2d4JFglT0BbUzWM6ovJYeZlDEL86+IX AkedEyKLGS0rgAtWzaU3+qcoAZkhbbd26yNKUhACKBLle50VGlmkhcgfWVeRAPyxh79y YDGcM+VA2MoRcbZEYPXdBbJUfTzZvk2RRpvSWU32W7FUGgXhEShTXkHdiQLiHFBEhx0h XdnQ== X-Gm-Message-State: AOAM533LlQVq5zNuAnIOmBHRpmFynlXlCGNtvK9yHaZ4szxg6jjf0/k/ IDMdK+HbvCv91MDlRZJIk7F30rSvFDU= X-Google-Smtp-Source: ABdhPJyogB+I2Mg6lZ1Gq2Ru0shKRuukd6Sc7ZtYC2qr8wjc+yYtgI9PHz/t76xa97oLMJGHJFdOCA== X-Received: by 2002:a05:600c:2cb4:: with SMTP id h20mr2241277wmc.119.1605269458565; Fri, 13 Nov 2020 04:10:58 -0800 (PST) Received: from ylate.lan (atoulouse-654-1-426-233.w2-6.abo.wanadoo.fr. [2.6.209.233]) by smtp.googlemail.com with ESMTPSA id g138sm10083697wme.39.2020.11.13.04.10.57 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Fri, 13 Nov 2020 04:10:57 -0800 (PST) From: Alban Gruin To: git@vger.kernel.org Cc: Junio C Hamano , Phillip Wood , Alban Gruin Subject: [PATCH v4 09/12] merge: use the "resolve" strategy without forking Date: Fri, 13 Nov 2020 12:04:25 +0100 Message-Id: <20201113110428.21265-10-alban.gruin@gmail.com> X-Mailer: git-send-email 2.20.1 In-Reply-To: <20201113110428.21265-1-alban.gruin@gmail.com> References: <20201005122646.27994-1-alban.gruin@gmail.com> <20201113110428.21265-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 Fri Nov 13 11:04:26 2020 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Alban Gruin X-Patchwork-Id: 11903195 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org X-Spam-Level: X-Spam-Status: No, score=-12.6 required=3.0 tests=BAYES_00,DKIM_SIGNED, DKIM_VALID,DKIM_VALID_AU,FREEMAIL_FORGED_FROMDOMAIN,FREEMAIL_FROM, HEADER_FROM_DIFFERENT_DOMAINS,INCLUDES_PATCH,MAILING_LIST_MULTI,SIGNED_OFF_BY, SPF_HELO_NONE,SPF_PASS,USER_AGENT_GIT autolearn=ham autolearn_force=no version=3.4.0 Received: from mail.kernel.org (mail.kernel.org [198.145.29.99]) by smtp.lore.kernel.org (Postfix) with ESMTP id C6BE2C388F7 for ; Fri, 13 Nov 2020 12:11:04 +0000 (UTC) Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by mail.kernel.org (Postfix) with ESMTP id 8F77F2224B for ; Fri, 13 Nov 2020 12:11:04 +0000 (UTC) Authentication-Results: mail.kernel.org; dkim=pass (2048-bit key) header.d=gmail.com header.i=@gmail.com header.b="vCDH9m2T" Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1726619AbgKMMLD (ORCPT ); Fri, 13 Nov 2020 07:11:03 -0500 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:36906 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1726237AbgKMMLB (ORCPT ); Fri, 13 Nov 2020 07:11:01 -0500 Received: from mail-wm1-x343.google.com (mail-wm1-x343.google.com [IPv6:2a00:1450:4864:20::343]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id 874C3C0613D1 for ; Fri, 13 Nov 2020 04:11:01 -0800 (PST) Received: by mail-wm1-x343.google.com with SMTP id a3so8232912wmb.5 for ; Fri, 13 Nov 2020 04:11:01 -0800 (PST) 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=88UgrApuDK/5WFwxAwEQqOcvRWzJ5zO7ae5kWhBPjVk=; b=vCDH9m2TZ85Eyg+xnFt4JjbEYWY/++vhPC4u9wTuskWrBVeSUdcsLcB5ZPh1hMRGHD ZWBdXTP9MrRgzdN6MxeyYneWQUOC2QTKCUzgzZRg5hFdoQKernvrXeELTKn/GxnssG66 zrtjOhopDBkx3jivrrpnaSn5gzpDa6WNUWPYYDREG7HCkEZ5rI04zd/8mgvbAzgLO7YH NZTnFRYBftIZf/WhaXntc4tzpcC+tsOi5Bp5dEAf1Xv4O+xW1SVaVjVmb4yXmnMlkslF hKi0nF4oxCtzcpYkNq8zU8lsDXv5tvJc8kuoR+uBXr4Y6vfhh+1vHd2rSP8KitkPqRPP 9+PA== 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=88UgrApuDK/5WFwxAwEQqOcvRWzJ5zO7ae5kWhBPjVk=; b=ETu3exW7aAgE5UscSm0X+BohV4GpWV2DCjHq6Y85vm/YjDm5RKT3+TFKAFHlfZ8OKR oHMbafuSi7sTMnRD0URQhUQJdXrcQ19soHJEROGf5KCHZHdX4X5uclhKTfCUbqTyfbUD NM+8YZGgDLvMc3Inmk1IEsUA46TZ3fvSVMLYYbZxxcE089Tn57w8FKtQ/LC2kpS2ZSAL dy1VpVChUO13tHpqTDrmLQ/8/IhzW0cSZ/H6S5mXqgg3n8B6r0YLTsQbrY5cVuEp6A/8 llHcOpla0Cjeg9M6D4lCMpDBMHVU6K277KJL+PApiBEYT3n0nGkBM1sBk+avSu4IdGrx OW5Q== X-Gm-Message-State: AOAM532W36+yW88FNxay++ENZTp54ActJaktnVOUGYvazS6ZA2v77cMB m//XEUcIT3qs5ynK30WQiggzxt7iJ9U= X-Google-Smtp-Source: ABdhPJytEhn6o1ZqoBIHh7Abs9Un/JQCieZVV0YM8CgHOPuBj8enwYt2BSZ2ps19/84B3MRbA++kwA== X-Received: by 2002:a1c:c2c3:: with SMTP id s186mr2311462wmf.160.1605269460060; Fri, 13 Nov 2020 04:11:00 -0800 (PST) Received: from ylate.lan (atoulouse-654-1-426-233.w2-6.abo.wanadoo.fr. [2.6.209.233]) by smtp.googlemail.com with ESMTPSA id g138sm10083697wme.39.2020.11.13.04.10.58 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Fri, 13 Nov 2020 04:10:59 -0800 (PST) From: Alban Gruin To: git@vger.kernel.org Cc: Junio C Hamano , Phillip Wood , Alban Gruin Subject: [PATCH v4 10/12] merge: use the "octopus" strategy without forking Date: Fri, 13 Nov 2020 12:04:26 +0100 Message-Id: <20201113110428.21265-11-alban.gruin@gmail.com> X-Mailer: git-send-email 2.20.1 In-Reply-To: <20201113110428.21265-1-alban.gruin@gmail.com> References: <20201005122646.27994-1-alban.gruin@gmail.com> <20201113110428.21265-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 Fri Nov 13 11:04:27 2020 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Alban Gruin X-Patchwork-Id: 11903203 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org X-Spam-Level: X-Spam-Status: No, score=-12.6 required=3.0 tests=BAYES_00,DKIM_SIGNED, DKIM_VALID,DKIM_VALID_AU,FREEMAIL_FORGED_FROMDOMAIN,FREEMAIL_FROM, HEADER_FROM_DIFFERENT_DOMAINS,INCLUDES_PATCH,MAILING_LIST_MULTI,SIGNED_OFF_BY, SPF_HELO_NONE,SPF_PASS,USER_AGENT_GIT autolearn=ham autolearn_force=no version=3.4.0 Received: from mail.kernel.org (mail.kernel.org [198.145.29.99]) by smtp.lore.kernel.org (Postfix) with ESMTP id 3D28BC4742C for ; Fri, 13 Nov 2020 12:11:09 +0000 (UTC) Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by mail.kernel.org (Postfix) with ESMTP id 07AD72224B for ; Fri, 13 Nov 2020 12:11:09 +0000 (UTC) Authentication-Results: mail.kernel.org; dkim=pass (2048-bit key) header.d=gmail.com header.i=@gmail.com header.b="nWbzRD+/" Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1726634AbgKMMLI (ORCPT ); Fri, 13 Nov 2020 07:11:08 -0500 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:36926 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1726603AbgKMMLH (ORCPT ); Fri, 13 Nov 2020 07:11:07 -0500 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 A9220C061A04 for ; Fri, 13 Nov 2020 04:11:02 -0800 (PST) Received: by mail-wr1-x442.google.com with SMTP id j7so9616305wrp.3 for ; Fri, 13 Nov 2020 04:11:02 -0800 (PST) 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=RUfvN0pl5K/WuXCV4D53cIPGvmeqL7bcfgCSQ17fPJA=; b=nWbzRD+/SDKe20Cl2jyPX9inFyHVuA7ViDJ7XXueqf3Vv4cjKCANmjqsyLuaV+Kbwx 8+NkgeSzIjw4Ufl5DPnCzeDHr6FUQxMh7YQsO3cpZHV/6YQSnK+ZkfmzQwkK9fhySHCV kCiXXmEGeJ9Vbm3gc6syw6IC6rqlxh0sTEQYOYBLGYyU8VqPKoo6TCDDBdnnvfmHocSY Bncp+MJJu2Wi9vc3XEHuw8zcjQQFI3u3pXGhyaJn8eMoAdSmb72AfXtQntknsyXLrcC7 kzs+lFJMPQOq8usADidW88rPAF/wy+Ze47KJiU0wQPH21VsDynXm/eDpQgLQBumU0gTg pD7Q== 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=RUfvN0pl5K/WuXCV4D53cIPGvmeqL7bcfgCSQ17fPJA=; b=SaqtFSlJA52F9DMt0K1XGIl9yrNRWEug0goaH3+fkrsZJNgxcBkqNOuFKRvPQUQT4F GAITv7aAVz2W1IGcVMZ6EEhAm+Kb8cIprXzKYfwOSbIc8p/FqoOXyuR75fhdbMt2hj22 lXso6wsoHyqoKmMTGJnyacu7TNi2mIP/21TFKxShfN0RfyxLre8dX1Sr6RefTjF5R+Ui VZYnDGuumSrllAtARpL8fc+YpMYRiEN8pMRtIv3DLlRKJuBQG2a7C53EO7WMZlgkGuSa Xn9xF1vUCBvOU9QK/xNq8V3lAp48WQC8ZU0zrWPgNwK2yWrR9EIKQsjr09ps7v44347n 21GQ== X-Gm-Message-State: AOAM533i78PvSMvRcTNZ16Z6EQfsAs/8NuAAfrmJAhDzYxZ83gIlMFA8 3aFTtZZj3nrPTKOM/LsX+y7i1R01mSg= X-Google-Smtp-Source: ABdhPJz72akDP/UpafHjKyClTQxueq4ndjHfDx8wh7w90Tk8K870X3jam2vrL+j95cWyVRqELkpvnA== X-Received: by 2002:a5d:448a:: with SMTP id j10mr2975367wrq.33.1605269461250; Fri, 13 Nov 2020 04:11:01 -0800 (PST) Received: from ylate.lan (atoulouse-654-1-426-233.w2-6.abo.wanadoo.fr. [2.6.209.233]) by smtp.googlemail.com with ESMTPSA id g138sm10083697wme.39.2020.11.13.04.11.00 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Fri, 13 Nov 2020 04:11:00 -0800 (PST) From: Alban Gruin To: git@vger.kernel.org Cc: Junio C Hamano , Phillip Wood , Alban Gruin Subject: [PATCH v4 11/12] sequencer: use the "resolve" strategy without forking Date: Fri, 13 Nov 2020 12:04:27 +0100 Message-Id: <20201113110428.21265-12-alban.gruin@gmail.com> X-Mailer: git-send-email 2.20.1 In-Reply-To: <20201113110428.21265-1-alban.gruin@gmail.com> References: <20201005122646.27994-1-alban.gruin@gmail.com> <20201113110428.21265-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 Fri Nov 13 11:04:28 2020 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Alban Gruin X-Patchwork-Id: 11903201 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org X-Spam-Level: X-Spam-Status: No, score=-12.6 required=3.0 tests=BAYES_00,DKIM_SIGNED, DKIM_VALID,DKIM_VALID_AU,FREEMAIL_FORGED_FROMDOMAIN,FREEMAIL_FROM, HEADER_FROM_DIFFERENT_DOMAINS,INCLUDES_PATCH,MAILING_LIST_MULTI,SIGNED_OFF_BY, SPF_HELO_NONE,SPF_PASS,USER_AGENT_GIT autolearn=ham autolearn_force=no version=3.4.0 Received: from mail.kernel.org (mail.kernel.org [198.145.29.99]) by smtp.lore.kernel.org (Postfix) with ESMTP id 5A792C56202 for ; Fri, 13 Nov 2020 12:11:06 +0000 (UTC) Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by mail.kernel.org (Postfix) with ESMTP id 150962224C for ; Fri, 13 Nov 2020 12:11:06 +0000 (UTC) Authentication-Results: mail.kernel.org; dkim=pass (2048-bit key) header.d=gmail.com header.i=@gmail.com header.b="nTaKp0NC" Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1726625AbgKMMLF (ORCPT ); Fri, 13 Nov 2020 07:11:05 -0500 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:36906 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1726237AbgKMMLE (ORCPT ); Fri, 13 Nov 2020 07:11:04 -0500 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 AD11AC0613D1 for ; Fri, 13 Nov 2020 04:11:03 -0800 (PST) Received: by mail-wr1-x442.google.com with SMTP id r17so9634936wrw.1 for ; Fri, 13 Nov 2020 04:11:03 -0800 (PST) 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=K9YVjZ1L8kzbu2itpBCJA99lobPJTsxMd/HON2LJPvg=; b=nTaKp0NCkq6Np5oBpIY3JsTtV+r/B6wnSrgW2RzhZYJbdk43NU+hoEObHAj7XXTH+p UtvgdLrMlt6YHl2P4W7vCGTgGIZWrLRVIcOCW27i4iNhgxmen9EtbOzy/kHToH6FehfQ z0YfbxnzPFWZ5zkwQAde0EhYI3C6CMStLmVAHlKEbo86YcrNiGYnCpKo1spxaq4a0IVh zNMP/0lK65P/LHiy1/WIb1CVFwNJjuCiTddmyK8MksLnFP74BtzaKt3iVrDOiUcdaHFS pORj5h9hVcRuFem3jYBiXNr3EOu2oNIXkAXjWIduaMuoRAnd98c+STIlyo2NdCW+KUpn h8OA== 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=K9YVjZ1L8kzbu2itpBCJA99lobPJTsxMd/HON2LJPvg=; b=DkJP1C6QsH6gqw+D6yxmeplQ86yU4Snhy2AswVRkIQHR5PUSYZXUhtGOEV1LhiWOGY i6o1wsuIYppxMd5GshzC9aA625LNW7SY/jTcWmJdJk5HPyEPQApogccJESTSU5bWgMSr rHo7vEecCU6mwryOzA7/acbE/ch/S9aspcAWExJqrV+zC9yVhD5wqrwksWJe9z2Xv6Sg 3B5B5mGbDYWciGY9UtSDzGo82gfXoV6XuNe8yCq2XOHmF5m4zFu/zNA2LYZEKvZK0byx mu5nFkdNxC6ZV0dO+X5N6n4+jlee+gCv8hE20JFqE17GkKG9OIdf/3pIoM5Ng7HECs20 +89w== X-Gm-Message-State: AOAM532Mjs/1cikRsJwVsxjn1baSa6J3e2R+MAEj6TOciGz1rBIpuB6y YLIjStMhVA5Iqqh7Xvj8KwVR/SXfFY4= X-Google-Smtp-Source: ABdhPJylmlLU1NdphYDMvKroaGh44auuQlPDOUgJ+CqgFyqlaNdZQ87T73qdzlpwe0zWDTVvREMk6w== X-Received: by 2002:adf:f349:: with SMTP id e9mr3084719wrp.110.1605269462267; Fri, 13 Nov 2020 04:11:02 -0800 (PST) Received: from ylate.lan (atoulouse-654-1-426-233.w2-6.abo.wanadoo.fr. [2.6.209.233]) by smtp.googlemail.com with ESMTPSA id g138sm10083697wme.39.2020.11.13.04.11.01 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Fri, 13 Nov 2020 04:11:01 -0800 (PST) From: Alban Gruin To: git@vger.kernel.org Cc: Junio C Hamano , Phillip Wood , Alban Gruin Subject: [PATCH v4 12/12] sequencer: use the "octopus" merge strategy without forking Date: Fri, 13 Nov 2020 12:04:28 +0100 Message-Id: <20201113110428.21265-13-alban.gruin@gmail.com> X-Mailer: git-send-email 2.20.1 In-Reply-To: <20201113110428.21265-1-alban.gruin@gmail.com> References: <20201005122646.27994-1-alban.gruin@gmail.com> <20201113110428.21265-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,