From patchwork Tue Mar 1 20:24:24 2022 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Victoria Dye X-Patchwork-Id: 12765142 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by smtp.lore.kernel.org (Postfix) with ESMTP id 1C910C433EF for ; Tue, 1 Mar 2022 20:26:15 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S238258AbiCAU0y (ORCPT ); Tue, 1 Mar 2022 15:26:54 -0500 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:50456 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S238379AbiCAU0Y (ORCPT ); Tue, 1 Mar 2022 15:26:24 -0500 Received: from mail-wm1-x330.google.com (mail-wm1-x330.google.com [IPv6:2a00:1450:4864:20::330]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id EAF058C7F3 for ; Tue, 1 Mar 2022 12:24:34 -0800 (PST) Received: by mail-wm1-x330.google.com with SMTP id p4so8169707wmg.1 for ; Tue, 01 Mar 2022 12:24:34 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20210112; h=message-id:in-reply-to:references:from:date:subject:fcc :content-transfer-encoding:mime-version:to:cc; bh=GS3guX4JeL6g22B1VqhKzTS5zc/tR36UdzmLu842dCU=; b=nQswpv6/xBEilzFMmt0yKwKdYpTpaR/9DenzuK7JBtV54hg4aWSHwBibx692O/eCCf J49zOt81dlFYqWY476YBEGNUsPey3sEjaIRqWY8hB78bpTj4SChAQxKeKcrseIA9ju// 5UKOVbtoa98w8oH0O5t1AmBoh/hs2G54Il+UR3IdKizcWJfT8QaTJodtOiKD/NEO8S64 Dcdfv1GiYnhgvaYaeSMaatlKNisFSwqieUH+owBiosXHwrLfW6wKG6Bw8tuBkpIlrhTl HhYFxxiMyT21z9dK3U/m/WWYb17u/wbUBwdybQgWNL9eHN3rW6OIxGX7Nas5jMBtnh/E CYmw== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20210112; h=x-gm-message-state:message-id:in-reply-to:references:from:date :subject:fcc:content-transfer-encoding:mime-version:to:cc; bh=GS3guX4JeL6g22B1VqhKzTS5zc/tR36UdzmLu842dCU=; b=mvoZMkw5IbubG+h7EpsFkZmxlA5ya+kl8GHhCTfIH6FpoG8HNJ0yoYwS6aGfNex7U4 dh6cEBXHSqYMO6BeW2Gl209HR5NUy45RfJ3V38bC7LbSemOpUwGx+utZRg2XRO/6+JG4 fxOoxot4Ve95VBCgi5pl/2ZX/jkBQqnAEM2+/EKT/1VzmtbjXhVo7gXmqhH1P8frbmuO xPuBxflnf9Gul+Tyt4kwcRe5/6HK5gNYPk4RXIxDfyae9kiPBumdZC1GdLqnSCD5UQl8 LRWwp4CYXCH/x+bSI/UWmjmCd5AJLjJOVaYimTiOOu2zbMQpITmrRw5HUfbrrSUGCffq hHhA== X-Gm-Message-State: AOAM533f6vGaFpcxT47zi++PndzrVFPxqs28IKGjyYfNMa+3/WXIkboz Z0mjMersKiUjPEwr84rF35GwaAeFt5o= X-Google-Smtp-Source: ABdhPJykBPzp3Awg/54bcno/yiTOeM98PVOR3ROjnjS+qKMHoTw8fARkTm+LdThyfZVfB5KeDwnUWg== X-Received: by 2002:a1c:f719:0:b0:381:ba:5247 with SMTP id v25-20020a1cf719000000b0038100ba5247mr18016024wmh.183.1646166273357; Tue, 01 Mar 2022 12:24:33 -0800 (PST) Received: from [127.0.0.1] ([13.74.141.28]) by smtp.gmail.com with ESMTPSA id f16-20020adff590000000b001f0122f63e1sm2979031wro.85.2022.03.01.12.24.32 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Tue, 01 Mar 2022 12:24:32 -0800 (PST) Message-Id: <744668eeece68a8cfe98b91c50d1cadb6988b993.1646166271.git.gitgitgadget@gmail.com> In-Reply-To: References: Date: Tue, 01 Mar 2022 20:24:24 +0000 Subject: [PATCH v3 1/8] sparse-index: prevent repo root from becoming sparse Fcc: Sent MIME-Version: 1.0 To: git@vger.kernel.org Cc: newren@gmail.com, gitster@pobox.com, Derrick Stolee , =?utf-8?b?w4Z2YXIgQXJuZmrDtnI=?= =?utf-8?b?w7A=?= Bjarmason , Victoria Dye , Victoria Dye Precedence: bulk List-ID: X-Mailing-List: git@vger.kernel.org From: Victoria Dye From: Victoria Dye Prevent the repository root from being collapsed into a sparse directory by treating an empty path as "inside the sparse-checkout". When collapsing a sparse index (e.g. in 'git sparse-checkout reapply'), the root directory typically could not become a sparse directory due to the presence of in-cone root-level files and directories. However, if no such in-cone files or directories were present, there was no explicit check signaling that the "repository root path" (an empty string, in the case of 'convert_to_sparse(...)') was in-cone, and a sparse directory index entry would be created from the repository root directory. The documentation in Documentation/git-sparse-checkout.txt explicitly states that the files in the root directory are expected to be in-cone for a cone-mode sparse-checkout. Collapsing the root into a sparse directory entry violates that assumption, as sparse directory entries are expected to be outside the sparse cone and have SKIP_WORKTREE enabled. This invalid state in turn causes issues with commands that interact with the index, e.g. 'git status'. Treating an empty (root) path as in-cone prevents the creation of a root sparse directory in 'convert_to_sparse(...)'. Because the repository root is otherwise never compared with sparse patterns (in both cone-mode and non-cone sparse-checkouts), the new check does not cause additional changes to how sparse patterns are applied. Helped-by: Derrick Stolee Signed-off-by: Victoria Dye --- dir.c | 7 ++++--- t/t1092-sparse-checkout-compatibility.sh | 18 ++++++++++++++++++ 2 files changed, 22 insertions(+), 3 deletions(-) diff --git a/dir.c b/dir.c index d91295f2bcd..a136377eb49 100644 --- a/dir.c +++ b/dir.c @@ -1463,10 +1463,11 @@ static int path_in_sparse_checkout_1(const char *path, const char *end, *slash; /* - * We default to accepting a path if there are no patterns or - * they are of the wrong type. + * We default to accepting a path if the path is empty, there are no + * patterns, or the patterns are of the wrong type. */ - if (init_sparse_checkout_patterns(istate) || + if (!*path || + init_sparse_checkout_patterns(istate) || (require_cone_mode && !istate->sparse_checkout_patterns->use_cone_patterns)) return 1; diff --git a/t/t1092-sparse-checkout-compatibility.sh b/t/t1092-sparse-checkout-compatibility.sh index f3a059e5af5..9ef7cd80885 100755 --- a/t/t1092-sparse-checkout-compatibility.sh +++ b/t/t1092-sparse-checkout-compatibility.sh @@ -244,6 +244,24 @@ test_expect_success 'expanded in-memory index matches full index' ' test_sparse_match git ls-files --stage ' +test_expect_success 'root directory cannot be sparse' ' + init_repos && + + # Remove all in-cone files and directories from the index, collapse index + # with `git sparse-checkout reapply` + git -C sparse-index rm -r . && + git -C sparse-index sparse-checkout reapply && + + # Verify sparse directories still present, root directory is not sparse + cat >expect <<-EOF && + folder1/ + folder2/ + x/ + EOF + git -C sparse-index ls-files --sparse >actual && + test_cmp expect actual +' + test_expect_success 'status with options' ' init_repos && test_sparse_match ls && From patchwork Tue Mar 1 20:24:25 2022 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Victoria Dye X-Patchwork-Id: 12765144 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by smtp.lore.kernel.org (Postfix) with ESMTP id 12E10C433FE for ; Tue, 1 Mar 2022 20:26:20 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S238408AbiCAU07 (ORCPT ); Tue, 1 Mar 2022 15:26:59 -0500 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:49912 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S238385AbiCAU0a (ORCPT ); Tue, 1 Mar 2022 15:26:30 -0500 Received: from mail-wm1-x332.google.com (mail-wm1-x332.google.com [IPv6:2a00:1450:4864:20::332]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id 481858D69B for ; Tue, 1 Mar 2022 12:24:35 -0800 (PST) Received: by mail-wm1-x332.google.com with SMTP id r65so562593wma.2 for ; Tue, 01 Mar 2022 12:24:35 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20210112; h=message-id:in-reply-to:references:from:date:subject:fcc :content-transfer-encoding:mime-version:to:cc; bh=g1HUFkbhfUBZN6xi/xbSLkpwawNhxPTM9wfs8BMBgzo=; b=FTXfpHjlbMg4dYNgOVzaLYKzG79eoQztJ6tXpFp5llgFBNWhpRsbkvl2qTDPs6pdnI YBGljoJBL/qP1Ix4PQYHmKEDpYpGyKXwb4mPJxmJh+7zIfGWfH7ArFmiPJjG9Dl3+cUE QG55d8/cUr2AAsssoj8/eS483y6nLo1Xz0G7o3A8Yc/YmEKWa4FufgBelg7yh0xto6Mx o7VtasY7lsthIIh1hr5tuyBXAwe1e8as2SGRNjvRPHyZoJJP9EC//S0dkPEkTA5GfHoA Ir2KZlQu/LzzNDp+k43Oew5/1X4p/uLRq9Fe8DDy012Mj8w2v24IXXHIg+Gu9hnyfJhx dugA== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20210112; h=x-gm-message-state:message-id:in-reply-to:references:from:date :subject:fcc:content-transfer-encoding:mime-version:to:cc; bh=g1HUFkbhfUBZN6xi/xbSLkpwawNhxPTM9wfs8BMBgzo=; b=jxw1TUflcMQpvkTwpC7SCMob1fUHoMuxzH0Uvyt2+ow8EshxEzhsNMxxvgE6azMmNU jgMqawSPW3+bHnoE1xND7ml7pJJK13kSgs9pjQt+0oUq94gKigaQPtH8rIIdnCoPJW9T PQUJI/V99h/CBugPrBVUv6GAY7vdRLHmzySwCgGYirSEQcecCzbs8WyLNULISqeZWl0p kFMBWVI9wEGuS3Am23NWp24Qbc/wiGJ/Yr+hgvZCF7hdF0KHQEWvfA1Zq8g2fg1LTNf6 N5LayQtI8mElcEL5vgOjBCbMgVDF2YsuG7vbTCG55ec3A9AiMLjaxwG0rH0Er49fuQ04 qJ/A== X-Gm-Message-State: AOAM530uUWx/3P9d7gp423S5+q1/AzBGx7zYm85FJ3GMFMKoFap+3Whh puzFairbffb5SW9DdANb8ywfsVZxOb8= X-Google-Smtp-Source: ABdhPJz9SVJPgUO/FEX3heYmvgrKOmg1U/MQ0Z4uv1AHzFMySXnPk/H9FiuOCD6bhhFXYL4EE8GFuw== X-Received: by 2002:a05:600c:3d99:b0:381:546c:8195 with SMTP id bi25-20020a05600c3d9900b00381546c8195mr10668012wmb.112.1646166274181; Tue, 01 Mar 2022 12:24:34 -0800 (PST) Received: from [127.0.0.1] ([13.74.141.28]) by smtp.gmail.com with ESMTPSA id t8-20020a5d6908000000b001e3169cc6afsm14804348wru.94.2022.03.01.12.24.33 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Tue, 01 Mar 2022 12:24:33 -0800 (PST) Message-Id: <26f4d30bd9546cf940ddd6827ddfc271c99b6665.1646166271.git.gitgitgadget@gmail.com> In-Reply-To: References: Date: Tue, 01 Mar 2022 20:24:25 +0000 Subject: [PATCH v3 2/8] status: fix nested sparse directory diff in sparse index Fcc: Sent MIME-Version: 1.0 To: git@vger.kernel.org Cc: newren@gmail.com, gitster@pobox.com, Derrick Stolee , =?utf-8?b?w4Z2YXIgQXJuZmrDtnI=?= =?utf-8?b?w7A=?= Bjarmason , Victoria Dye , Victoria Dye Precedence: bulk List-ID: X-Mailing-List: git@vger.kernel.org From: Victoria Dye From: Victoria Dye Enable the 'recursive' diff option for the diff executed as part of 'git status'. Without the 'recursive' enabled, 'git status' reports index changes incorrectly when the following conditions were met: * sparse index is enabled * there is a difference between the index and HEAD in a file inside a *subdirectory* of a sparse directory * the sparse directory index entry is *not* expanded in-core Because it is not recursive by default, the diff in 'git status' reports changes only at the level of files and directories that are immediate children of a sparse directory, rather than recursing into directories with changes to identify the modified file(s). As a result, 'git status' reports the immediate subdirectory itself as "modified". Example: $ git init $ mkdir -p sparse/sub $ echo test >sparse/sub/foo $ git add . $ git commit -m "commit 1" $ echo somethingelse >sparse/sub/foo $ git add . $ git commit -a -m "commit 2" $ git sparse-checkout set --cone --sparse-index 'sparse' $ git reset --soft HEAD~1 $ git status On branch master You are in a sparse checkout. Changes to be committed: (use "git restore --staged ..." to unstage) modified: sparse/sub Enabling the 'recursive' diff option in 'wt_status_collect_changes_index' corrects this issue by allowing the diff to recurse into subdirectories of sparse directories to find modified files. Given the same repository setup as the example above, the corrected result of `git status` is: $ git status On branch master You are in a sparse checkout. Changes to be committed: (use "git restore --staged ..." to unstage) modified: sparse/sub/foo Signed-off-by: Victoria Dye --- t/t1092-sparse-checkout-compatibility.sh | 7 +++++++ wt-status.c | 9 +++++++++ 2 files changed, 16 insertions(+) diff --git a/t/t1092-sparse-checkout-compatibility.sh b/t/t1092-sparse-checkout-compatibility.sh index 9ef7cd80885..b1dcaa0e642 100755 --- a/t/t1092-sparse-checkout-compatibility.sh +++ b/t/t1092-sparse-checkout-compatibility.sh @@ -278,6 +278,13 @@ test_expect_success 'status with options' ' test_all_match git status --porcelain=v2 -uno ' +test_expect_success 'status with diff in unexpanded sparse directory' ' + init_repos && + test_all_match git checkout rename-base && + test_all_match git reset --soft rename-out-to-out && + test_all_match git status --porcelain=v2 +' + test_expect_success 'status reports sparse-checkout' ' init_repos && git -C sparse-checkout status >full && diff --git a/wt-status.c b/wt-status.c index 335e723a71e..7da8bbe261a 100644 --- a/wt-status.c +++ b/wt-status.c @@ -651,6 +651,15 @@ static void wt_status_collect_changes_index(struct wt_status *s) rev.diffopt.detect_rename = s->detect_rename >= 0 ? s->detect_rename : rev.diffopt.detect_rename; rev.diffopt.rename_limit = s->rename_limit >= 0 ? s->rename_limit : rev.diffopt.rename_limit; rev.diffopt.rename_score = s->rename_score >= 0 ? s->rename_score : rev.diffopt.rename_score; + + /* + * The `recursive` option must be enabled to allow the diff to recurse + * into subdirectories of sparse directory index entries. If it is not + * enabled, a subdirectory containing file(s) with changes is reported + * as "modified", rather than the modified files themselves. + */ + rev.diffopt.flags.recursive = 1; + copy_pathspec(&rev.prune_data, &s->pathspec); run_diff_index(&rev, 1); object_array_clear(&rev.pending); From patchwork Tue Mar 1 20:24:26 2022 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Victoria Dye X-Patchwork-Id: 12765145 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by smtp.lore.kernel.org (Postfix) with ESMTP id EF3EDC433F5 for ; Tue, 1 Mar 2022 20:26:21 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S238326AbiCAU1B (ORCPT ); Tue, 1 Mar 2022 15:27:01 -0500 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:49910 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S238308AbiCAU0k (ORCPT ); Tue, 1 Mar 2022 15:26:40 -0500 Received: from mail-wr1-x42c.google.com (mail-wr1-x42c.google.com [IPv6:2a00:1450:4864:20::42c]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id CEC43888C3 for ; Tue, 1 Mar 2022 12:24:36 -0800 (PST) Received: by mail-wr1-x42c.google.com with SMTP id d3so22336643wrf.1 for ; Tue, 01 Mar 2022 12:24:36 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20210112; h=message-id:in-reply-to:references:from:date:subject:fcc :content-transfer-encoding:mime-version:to:cc; bh=ql7OrUv2dimnvaZBSchTpW1zo/+46L/f+KWulvTkios=; b=MkEkupKHdtdTqC6InYYm+pcioeqD7ysFvdIiMbl/USFns0ZzlWjnry7PwbMrmeGj1Y 4TpkRdRdWjUHPW72jqTupn9yCyh7PIVli9yIU2BRie0k2pCJ1mXtWF/7i0OhRJDPSemr hrdoAnOHxvv6/RyB2WMBzFeHTDJM0yrQP4uUEdZc+0NwmWOnywLUTLbfoDX8Gslq4PVZ XkFceDtn0KxBBHFQig9LaYYhEWMT7S+kfJrDcbffMZThPxEOh8X0VlNG+hjAS9/MGxrr ubANOPudIpjcgcVcfqZ0Y0AmgxQFjtS6OVIUYRkoMX1sNGXIuckXExKolrG/48X8n7cQ LgNg== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20210112; h=x-gm-message-state:message-id:in-reply-to:references:from:date :subject:fcc:content-transfer-encoding:mime-version:to:cc; bh=ql7OrUv2dimnvaZBSchTpW1zo/+46L/f+KWulvTkios=; b=c8NYY+IgqKXndDZvVHmPYZsj1Cui3dvw9vaGH8sRPHsPu09zqzerinbp/niNFLJ6/S CnqiP9VegFTxm8R5b3X4qc+PMqi84gIsZ3++HWFSR2htAQPKtTvSCkTmnbeklGKkKJrm ffbnROIAwLDg4ofwLURawjcBmTvbZlCnOjnLuhs2a7AY2SWZkpYFIeioSJykKtvxZY8E teqiHnBgbIla/AwD3+tjgYNTatZVSob3elsx0CX5/lpeLBwA7AiVSidS2UxIAwHdRom6 O0+ydZtInoSRS3A7HHcfpLLVKjcxRNP0MdCgWo6WXLmE7PvTRJej2+072Bjc2+JEauGS Xyew== X-Gm-Message-State: AOAM532nTwTSdUIk1O+mvIwpkcOJ78gLUTXn3oMlDJqvre3J/oOpF00Z j/uiSaka495rgVDQzC/D8KPKC7Gz9pI= X-Google-Smtp-Source: ABdhPJzlCkdbGnwuUam7aLoliEOosAdf2clPEfbdwMZjc3nAIxo6BohUqMmzhc2bUjH01llfWwlIQA== X-Received: by 2002:a05:6000:50a:b0:1e3:5af:153e with SMTP id a10-20020a056000050a00b001e305af153emr20699535wrf.385.1646166275029; Tue, 01 Mar 2022 12:24:35 -0800 (PST) Received: from [127.0.0.1] ([13.74.141.28]) by smtp.gmail.com with ESMTPSA id v14-20020a7bcb4e000000b0034492fa24c6sm3419003wmj.34.2022.03.01.12.24.34 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Tue, 01 Mar 2022 12:24:34 -0800 (PST) Message-Id: In-Reply-To: References: Date: Tue, 01 Mar 2022 20:24:26 +0000 Subject: [PATCH v3 3/8] read-tree: explicitly disallow prefixes with a leading '/' Fcc: Sent MIME-Version: 1.0 To: git@vger.kernel.org Cc: newren@gmail.com, gitster@pobox.com, Derrick Stolee , =?utf-8?b?w4Z2YXIgQXJuZmrDtnI=?= =?utf-8?b?w7A=?= Bjarmason , Victoria Dye , Victoria Dye Precedence: bulk List-ID: X-Mailing-List: git@vger.kernel.org From: Victoria Dye From: Victoria Dye Exit with an error if a prefix provided to `git read-tree --prefix` begins with '/'. In most cases, prefixes like this result in an "invalid path" error; however, the repository root would be interpreted as valid when specified as '--prefix=/'. This is due to leniency around trailing directory separators on prefixes (e.g., allowing both '--prefix=my-dir' and '--prefix=my-dir/') - the '/' in the prefix is actually the *trailing* slash, although it could be misinterpreted as a *leading* slash. To remove the confusing repo root-as-'/' case and make it clear that prefixes should not begin with '/', exit with an error if the first character of the provided prefix is '/'. Helped-by: Elijah Newren Signed-off-by: Victoria Dye --- builtin/read-tree.c | 4 ++++ t/t1003-read-tree-prefix.sh | 10 ++++++++++ 2 files changed, 14 insertions(+) diff --git a/builtin/read-tree.c b/builtin/read-tree.c index 2109c4c9e5c..c1a401971c2 100644 --- a/builtin/read-tree.c +++ b/builtin/read-tree.c @@ -166,6 +166,10 @@ int cmd_read_tree(int argc, const char **argv, const char *cmd_prefix) if (1 < opts.merge + opts.reset + prefix_set) die("Which one? -m, --reset, or --prefix?"); + /* Prefix should not start with a directory separator */ + if (opts.prefix && opts.prefix[0] == '/') + die("Invalid prefix, prefix cannot start with '/'"); + if (opts.reset) opts.reset = UNPACK_RESET_OVERWRITE_UNTRACKED; diff --git a/t/t1003-read-tree-prefix.sh b/t/t1003-read-tree-prefix.sh index e0db2066f31..c860c08ecb4 100755 --- a/t/t1003-read-tree-prefix.sh +++ b/t/t1003-read-tree-prefix.sh @@ -25,4 +25,14 @@ test_expect_success 'read-tree --prefix' ' cmp expect actual ' +test_expect_success 'read-tree --prefix with leading slash exits with error' ' + git rm -rf . && + test_must_fail git read-tree --prefix=/two/ $tree && + git read-tree --prefix=two/ $tree && + + git rm -rf . && + test_must_fail git read-tree --prefix=/ $tree && + git read-tree --prefix= $tree +' + test_done From patchwork Tue Mar 1 20:24:27 2022 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 8bit X-Patchwork-Submitter: Victoria Dye X-Patchwork-Id: 12765150 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by smtp.lore.kernel.org (Postfix) with ESMTP id EC1A4C433FE for ; Tue, 1 Mar 2022 20:26:34 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S238386AbiCAU1O (ORCPT ); Tue, 1 Mar 2022 15:27:14 -0500 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:49750 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S236863AbiCAU0p (ORCPT ); Tue, 1 Mar 2022 15:26:45 -0500 Received: from mail-wr1-x42b.google.com (mail-wr1-x42b.google.com [IPv6:2a00:1450:4864:20::42b]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id 987008EB43 for ; Tue, 1 Mar 2022 12:24:39 -0800 (PST) Received: by mail-wr1-x42b.google.com with SMTP id d17so22276450wrc.9 for ; Tue, 01 Mar 2022 12:24:39 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20210112; h=message-id:in-reply-to:references:from:date:subject:mime-version :content-transfer-encoding:fcc:to:cc; bh=c9yWbLZW8HFt+k72kqua9y2FZXPRLsuIJ24GnVy1oak=; b=NNJZWWziRx6oScGpfr9mS3TZ02AnTjoqckdL0kVHufFbBNJnaOju6C09lnWQlrS8cD 36OH1Ls7wUe1grmAZiEfYmckFtgTzgXS1CKr/OxecaMY3MGeB37ZDU8K/27reQMZ8bRy iHqn7TViVKV3UYHX/K1XvyQ7fVTxG2g5B9NCuRPVEzuXWalfs95pk0b96AbKmvbsd+Av fu8fxBp5ZEXu+6p+vCWxf+JFPaFkxkHeDE9kMnsbEFkW1I5I1lYUjcJVKndSKl3vu+LE ucS8GJ0UipHjW2Do396N8GWLl4MgmgTrQJn/xrpVASoGVNJNqqn6Job8xwRMafGYSRp1 dWcQ== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20210112; h=x-gm-message-state:message-id:in-reply-to:references:from:date :subject:mime-version:content-transfer-encoding:fcc:to:cc; bh=c9yWbLZW8HFt+k72kqua9y2FZXPRLsuIJ24GnVy1oak=; b=BiPqm109v7eyu2CitJ00ZCZD0dzJosvnxo6VuVrqnRfbGEJ2cfDnm/rAcraAYnjm/J PEZMVXhJCGwOuuvdIDmX/4dkzV3/GpxhEqCLK/Vr2TN0rypTKtOfS+8CQPMBSEHUeOHw hlBYLewdFjLnj3rM4mFStEzfTUQpWapeHChAuuADzWuxWoGjDl+9ubTVKYb0fohS/Xy+ Bxkbo9NpPgjU6IKkcsvUaTMHcFNGJs+/haIfSVeUKfxov/9Optu87MH+ICb3Sd7W+rIm PPtoGD88wv5SWpkCYHUwy13HvBoNiao1bDuhZJ4iUF9M+VnIIAQKpvdY42JEdr4ynmak mmdA== X-Gm-Message-State: AOAM5334FuDAU5a5UBAdXCm/VbWcopwaZKhAFi7gIxbcy30nMC1UqvYy tqi2LfhxBZRUS0uwRQHsdB+3FVCsmfQ= X-Google-Smtp-Source: ABdhPJzb6MpHfEOt2RjotYZRymtZzH9scTfNO4YT/hwkSQbS3NjQ6GT+0oTMVpsNex9KFChBje+6GA== X-Received: by 2002:adf:ef81:0:b0:1f0:95f:30a7 with SMTP id d1-20020adfef81000000b001f0095f30a7mr3779828wro.636.1646166275918; Tue, 01 Mar 2022 12:24:35 -0800 (PST) Received: from [127.0.0.1] ([13.74.141.28]) by smtp.gmail.com with ESMTPSA id j3-20020a5d6043000000b001f0247bbdf7sm956647wrt.64.2022.03.01.12.24.35 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Tue, 01 Mar 2022 12:24:35 -0800 (PST) Message-Id: <90ebcb7b8ff4b4f1ba09abcbe636d639fa597e74.1646166271.git.gitgitgadget@gmail.com> In-Reply-To: References: Date: Tue, 01 Mar 2022 20:24:27 +0000 Subject: [PATCH v3 4/8] read-tree: expand sparse checkout test coverage MIME-Version: 1.0 Fcc: Sent To: git@vger.kernel.org Cc: newren@gmail.com, gitster@pobox.com, Derrick Stolee , =?utf-8?b?w4Z2YXIgQXJuZmrDtnI=?= =?utf-8?b?w7A=?= Bjarmason , Victoria Dye , Victoria Dye Precedence: bulk List-ID: X-Mailing-List: git@vger.kernel.org From: Victoria Dye From: Victoria Dye Add tests focused on how 'git read-tree' behaves in sparse checkouts. Extra emphasis is placed on interactions with files outside the sparse cone, e.g. merges with out-of-cone conflicts. Helped-by: Ævar Arnfjörð Bjarmason Signed-off-by: Victoria Dye --- t/perf/p2000-sparse-operations.sh | 1 + t/t1092-sparse-checkout-compatibility.sh | 87 ++++++++++++++++++++++++ 2 files changed, 88 insertions(+) diff --git a/t/perf/p2000-sparse-operations.sh b/t/perf/p2000-sparse-operations.sh index 2a7106b9495..382716cfca9 100755 --- a/t/perf/p2000-sparse-operations.sh +++ b/t/perf/p2000-sparse-operations.sh @@ -117,6 +117,7 @@ test_perf_on_all git diff test_perf_on_all git diff --cached test_perf_on_all git blame $SPARSE_CONE/a test_perf_on_all git blame $SPARSE_CONE/f3/a +test_perf_on_all git read-tree -mu HEAD test_perf_on_all git checkout-index -f --all test_perf_on_all git update-index --add --remove $SPARSE_CONE/a diff --git a/t/t1092-sparse-checkout-compatibility.sh b/t/t1092-sparse-checkout-compatibility.sh index b1dcaa0e642..9bb5aeb979c 100755 --- a/t/t1092-sparse-checkout-compatibility.sh +++ b/t/t1092-sparse-checkout-compatibility.sh @@ -819,6 +819,93 @@ test_expect_success 'update-index --cacheinfo' ' test_cmp expect sparse-checkout-out ' +for MERGE_TREES in "base HEAD update-folder2" \ + "update-folder1 update-folder2" \ + "update-folder2" +do + test_expect_success "'read-tree -mu $MERGE_TREES' with files outside sparse definition" ' + init_repos && + + # Although the index matches, without --no-sparse-checkout, outside-of- + # definition files will not exist on disk for sparse checkouts + test_all_match git read-tree -mu $MERGE_TREES && + test_all_match git status --porcelain=v2 && + test_path_is_missing sparse-checkout/folder2 && + test_path_is_missing sparse-index/folder2 && + + test_all_match git read-tree --reset -u HEAD && + test_all_match git status --porcelain=v2 && + + test_all_match git read-tree -mu --no-sparse-checkout $MERGE_TREES && + test_all_match git status --porcelain=v2 && + test_cmp sparse-checkout/folder2/a sparse-index/folder2/a && + test_cmp sparse-checkout/folder2/a full-checkout/folder2/a + + ' +done + +test_expect_success 'read-tree --merge with edit/edit conflicts in sparse directories' ' + init_repos && + + # Merge of multiple changes to same directory (but not same files) should + # succeed + test_all_match git read-tree -mu base rename-base update-folder1 && + test_all_match git status --porcelain=v2 && + + test_all_match git reset --hard && + + test_all_match git read-tree -mu rename-base update-folder2 && + test_all_match git status --porcelain=v2 && + + test_all_match git reset --hard && + + test_all_match test_must_fail git read-tree -mu base update-folder1 rename-out-to-in && + test_all_match test_must_fail git read-tree -mu rename-out-to-in update-folder1 +' + +test_expect_success 'read-tree --prefix' ' + init_repos && + + # If files differing between the index and target exist + # inside the prefix, `read-tree --prefix` should fail + test_all_match test_must_fail git read-tree --prefix=deep/ deepest && + test_all_match test_must_fail git read-tree --prefix=folder1/ update-folder1 && + + # If no differing index entries exist matching the prefix, + # `read-tree --prefix` updates the index successfully + test_all_match git rm -rf deep/deeper1/deepest/ && + test_all_match git read-tree --prefix=deep/deeper1/deepest -u deepest && + test_all_match git status --porcelain=v2 && + + test_all_match git rm -rf --sparse folder1/ && + test_all_match git read-tree --prefix=folder1/ -u update-folder1 && + test_all_match git status --porcelain=v2 && + + test_all_match git rm -rf --sparse folder2/0 && + test_all_match git read-tree --prefix=folder2/0/ -u rename-out-to-out && + test_all_match git status --porcelain=v2 +' + +test_expect_success 'read-tree --merge with directory-file conflicts' ' + init_repos && + + test_all_match git checkout -b test-branch rename-base && + + # Although the index matches, without --no-sparse-checkout, outside-of- + # definition files will not exist on disk for sparse checkouts + test_sparse_match git read-tree -mu rename-out-to-out && + test_sparse_match git status --porcelain=v2 && + test_path_is_missing sparse-checkout/folder2 && + test_path_is_missing sparse-index/folder2 && + + test_sparse_match git read-tree --reset -u HEAD && + test_sparse_match git status --porcelain=v2 && + + test_sparse_match git read-tree -mu --no-sparse-checkout rename-out-to-out && + test_sparse_match git status --porcelain=v2 && + test_cmp sparse-checkout/folder2/0/1 sparse-index/folder2/0/1 +' + test_expect_success 'merge, cherry-pick, and rebase' ' init_repos && From patchwork Tue Mar 1 20:24:28 2022 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Victoria Dye X-Patchwork-Id: 12765149 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by smtp.lore.kernel.org (Postfix) with ESMTP id 356F6C433F5 for ; Tue, 1 Mar 2022 20:26:33 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S235399AbiCAU1N (ORCPT ); Tue, 1 Mar 2022 15:27:13 -0500 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:50882 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S238396AbiCAU0q (ORCPT ); Tue, 1 Mar 2022 15:26:46 -0500 Received: from mail-wr1-x42f.google.com (mail-wr1-x42f.google.com [IPv6:2a00:1450:4864:20::42f]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id 50D338F61B for ; Tue, 1 Mar 2022 12:24:41 -0800 (PST) Received: by mail-wr1-x42f.google.com with SMTP id t11so1311295wrm.5 for ; Tue, 01 Mar 2022 12:24:41 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20210112; h=message-id:in-reply-to:references:from:date:subject:fcc :content-transfer-encoding:mime-version:to:cc; bh=lgcgVoMVx+nLmbesIjkdMYJ1oZbkOITvLIpr6PYRAR4=; b=FJCv5u1niLvkDKQsGEFX83emRIh0MDuXhgCKysg5BcRpsjCnaezIqwxacAL2ODEhbM Pr2j2YY+bFE2+ns6gj2mSKXvnlex1n5EivKIrulY2d9SnNFDGLxdwXgvhNUyzEj3Yrdk orBr0yiH7Qm/31v86GvB9tKPpWnEna/Vvqe6SmRbj252165urbTMmWOCbQoCYm4b1aRN O1hyy1bHdFh57j66t/W0H6btv1z7dUoz68HytSAmlD0Fiw/b1FBKX/fM8hRAA1eLt2oq 25qZV7K8OmgfZHUQMkkDVW9H6s6fEX3K9qj+dHa+ohHC08GScC3oOvndre7Od33XZnrc Rq9w== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20210112; h=x-gm-message-state:message-id:in-reply-to:references:from:date :subject:fcc:content-transfer-encoding:mime-version:to:cc; bh=lgcgVoMVx+nLmbesIjkdMYJ1oZbkOITvLIpr6PYRAR4=; b=P98KSM7++B4LmHyywFU53nakK/i8nH6kfo4hh2BfbPCTy/+GZ/q97jQNAwGrRgE6s9 COzL44zxY92vNJhou0ueIn3sY92byps0wHkMVaHJwE5+KrrouPGTkDJETE3KAJleJYYP 3VTMCUViu7Qz5Rf22mq/cDDXXOvtmQpJdGjjtXmmu7UYL0uPO0Ln7ZavpXdquAmdNVTf xrDS9WQamSHVEqH4igZHuGemmXsJX4+OrGgGRm4kUldOAR1Mdw2QAB2ZHnWwdLpBUKDu P2qmXcjYWwqq2ToQrgdxH+sIps/jt+SSz2srqf8PO6xaejaEYuGFSl+fq2aCqy/uBa6N Butg== X-Gm-Message-State: AOAM533J+bPyYByiNihlyGgO87U7LH1lgBf++diYPcfDgkZ1NoJ7g/8o N6w3A5iaTG+NkXbudCyiq9tgAyUX/FM= X-Google-Smtp-Source: ABdhPJxuB2Enr8S6pqQ3jmh9csUaQPmGxyDE+m1W9WbldB3vzj+DKN8VsQDVkQrW5f1k/409omfRnw== X-Received: by 2002:a05:6000:128c:b0:1ea:99b7:80e with SMTP id f12-20020a056000128c00b001ea99b7080emr19739767wrx.540.1646166276681; Tue, 01 Mar 2022 12:24:36 -0800 (PST) Received: from [127.0.0.1] ([13.74.141.28]) by smtp.gmail.com with ESMTPSA id 11-20020a05600c22cb00b00382a960b17csm1614464wmg.7.2022.03.01.12.24.36 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Tue, 01 Mar 2022 12:24:36 -0800 (PST) Message-Id: <015618a9f292fc6eb20b21d40619cade343a9a0d.1646166271.git.gitgitgadget@gmail.com> In-Reply-To: References: Date: Tue, 01 Mar 2022 20:24:28 +0000 Subject: [PATCH v3 5/8] read-tree: integrate with sparse index Fcc: Sent MIME-Version: 1.0 To: git@vger.kernel.org Cc: newren@gmail.com, gitster@pobox.com, Derrick Stolee , =?utf-8?b?w4Z2YXIgQXJuZmrDtnI=?= =?utf-8?b?w7A=?= Bjarmason , Victoria Dye , Victoria Dye Precedence: bulk List-ID: X-Mailing-List: git@vger.kernel.org From: Victoria Dye From: Victoria Dye Enable use of sparse index in 'git read-tree'. The integration in this patch is limited only to usage of 'read-tree' that does not need additional functional changes for the sparse index to behave as expected (i.e., produce the same user-facing results as a non-sparse index sparse-checkout). To ensure no unexpected behavior occurs, the index is explicitly expanded when: * '--no-sparse-checkout' is specified (because it disables sparse-checkout) * '--prefix' is specified (if the prefix is inside a sparse directory, the prefixed tree cannot be properly traversed) * two or more arguments are specified ('twoway_merge' and 'threeway_merge' do not yet support merging sparse directories) Signed-off-by: Victoria Dye --- builtin/read-tree.c | 21 +++++++++++++++++++-- t/t1092-sparse-checkout-compatibility.sh | 11 +++++++++++ 2 files changed, 30 insertions(+), 2 deletions(-) diff --git a/builtin/read-tree.c b/builtin/read-tree.c index c1a401971c2..0a52cab7752 100644 --- a/builtin/read-tree.c +++ b/builtin/read-tree.c @@ -160,8 +160,6 @@ int cmd_read_tree(int argc, const char **argv, const char *cmd_prefix) argc = parse_options(argc, argv, cmd_prefix, read_tree_options, read_tree_usage, 0); - hold_locked_index(&lock_file, LOCK_DIE_ON_ERROR); - prefix_set = opts.prefix ? 1 : 0; if (1 < opts.merge + opts.reset + prefix_set) die("Which one? -m, --reset, or --prefix?"); @@ -173,6 +171,11 @@ int cmd_read_tree(int argc, const char **argv, const char *cmd_prefix) if (opts.reset) opts.reset = UNPACK_RESET_OVERWRITE_UNTRACKED; + prepare_repo_settings(the_repository); + the_repository->settings.command_requires_full_index = 0; + + hold_locked_index(&lock_file, LOCK_DIE_ON_ERROR); + /* * NEEDSWORK * @@ -214,6 +217,10 @@ int cmd_read_tree(int argc, const char **argv, const char *cmd_prefix) if (opts.merge && !opts.index_only) setup_work_tree(); + /* TODO: audit sparse index behavior in unpack_trees */ + if (opts.skip_sparse_checkout || opts.prefix) + ensure_full_index(&the_index); + if (opts.merge) { switch (stage - 1) { case 0: @@ -223,11 +230,21 @@ int cmd_read_tree(int argc, const char **argv, const char *cmd_prefix) opts.fn = opts.prefix ? bind_merge : oneway_merge; break; case 2: + /* + * TODO: update twoway_merge to handle edit/edit conflicts in + * sparse directories. + */ + ensure_full_index(&the_index); opts.fn = twoway_merge; opts.initial_checkout = is_cache_unborn(); break; case 3: default: + /* + * TODO: update threeway_merge to handle edit/edit conflicts in + * sparse directories. + */ + ensure_full_index(&the_index); opts.fn = threeway_merge; break; } diff --git a/t/t1092-sparse-checkout-compatibility.sh b/t/t1092-sparse-checkout-compatibility.sh index 9bb5aeb979c..86241b01a59 100755 --- a/t/t1092-sparse-checkout-compatibility.sh +++ b/t/t1092-sparse-checkout-compatibility.sh @@ -1409,6 +1409,17 @@ test_expect_success 'sparse index is not expanded: fetch/pull' ' ensure_not_expanded pull full base ' +test_expect_success 'sparse index is not expanded: read-tree' ' + init_repos && + + ensure_not_expanded checkout -b test-branch update-folder1 && + for MERGE_TREES in "update-folder2" + do + ensure_not_expanded read-tree -mu $MERGE_TREES && + ensure_not_expanded reset --hard || return 1 + done +' + test_expect_success 'ls-files' ' init_repos && From patchwork Tue Mar 1 20:24:29 2022 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Victoria Dye X-Patchwork-Id: 12765147 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by smtp.lore.kernel.org (Postfix) with ESMTP id 8C644C4332F for ; Tue, 1 Mar 2022 20:26:28 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S237095AbiCAU1H (ORCPT ); Tue, 1 Mar 2022 15:27:07 -0500 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:50888 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S238232AbiCAU0q (ORCPT ); Tue, 1 Mar 2022 15:26:46 -0500 Received: from mail-wr1-x431.google.com (mail-wr1-x431.google.com [IPv6:2a00:1450:4864:20::431]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id 9D1448F62B for ; Tue, 1 Mar 2022 12:24:41 -0800 (PST) Received: by mail-wr1-x431.google.com with SMTP id j17so22375192wrc.0 for ; Tue, 01 Mar 2022 12:24:41 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20210112; h=message-id:in-reply-to:references:from:date:subject:fcc :content-transfer-encoding:mime-version:to:cc; bh=9DBogxSaFTyTsGIWfubnq62UOyMlN/cANTvCvx2wkGI=; b=UG19Dx7hiBfPTQ1pIPqdnCBJQfPRye+apL0Kq7GEcug3PwU4GVR8uQh6iwd+ZGX4hd p31wVVFT62g8OqkO2aWdS9XS4QNppHkMGC0e710bgus4NLwldnFbDTN0OpeAyfwTiGok eqI1N+lFfDGPZokfNweNVuJSgIcoq+xl1qlcAMll0l98kOcFHCgPIObTCaVw3GazjLmo eaiTi9/1jqqn2elx+kl3ysVaIll3ygU5HatL+DuqVDp61xa4InAaY8JCQUp5I45z253V JhHNsx8YA3aa4++47MEdwRNMGi5EyBJf5zuod+KkiNbW3D4td43WkjNbUVfhY1u2N+lB yNaA== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20210112; h=x-gm-message-state:message-id:in-reply-to:references:from:date :subject:fcc:content-transfer-encoding:mime-version:to:cc; bh=9DBogxSaFTyTsGIWfubnq62UOyMlN/cANTvCvx2wkGI=; b=EsObW3D5Ooxaaj5orMyCK9g4FUX5TIOSuSceBBejUIpnj48+rjLDLoC7MiNJNgrhta 4kwqWSO56kq3FWgWM189NEaYyAzqpIIYuaZPqyJ4koat3iJgNlf08bIseNvANropY4JI npp4ddB91fCf1mTdZGRA7Bci1pilCQU5tllKdCLrPWj+huGQizGO+lhuxBjWehZCn6n3 c27ZGAYzvWpFTWrLngg41vLJ2bnJVMUOdOB2M5EunGQ4OojEolRw3omm+Jy5VBu2zp4/ DOdf4vB87AkQAOt44vS4jV6rma1DzCecbuG19dS2bICYqtmqawpapKLroSM4qY8k2Q7h t/lg== X-Gm-Message-State: AOAM532XWAHvdVvZ+bAR/aBNvfdMtAw7Mi74fH+CgBSIl4NumWI3JFBd RVkh4KRMwRYyWWVgsjjhkyLsafdANe4= X-Google-Smtp-Source: ABdhPJwQhbhVNPL0Cu6m7J5n4wUKWHgLBGM1fqUmkWUzGzKJn+aIftCOGuFxwgnXYrRHuqCtyW9nww== X-Received: by 2002:a5d:5983:0:b0:1e5:7dd6:710 with SMTP id n3-20020a5d5983000000b001e57dd60710mr21647445wri.392.1646166277580; Tue, 01 Mar 2022 12:24:37 -0800 (PST) Received: from [127.0.0.1] ([13.74.141.28]) by smtp.gmail.com with ESMTPSA id e4-20020a05600c218400b003818133ab4dsm3359775wme.14.2022.03.01.12.24.37 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Tue, 01 Mar 2022 12:24:37 -0800 (PST) Message-Id: <1a9365c3bc5b810a60593612bfba97a8b0c1d657.1646166271.git.gitgitgadget@gmail.com> In-Reply-To: References: Date: Tue, 01 Mar 2022 20:24:29 +0000 Subject: [PATCH v3 6/8] read-tree: narrow scope of index expansion for '--prefix' Fcc: Sent MIME-Version: 1.0 To: git@vger.kernel.org Cc: newren@gmail.com, gitster@pobox.com, Derrick Stolee , =?utf-8?b?w4Z2YXIgQXJuZmrDtnI=?= =?utf-8?b?w7A=?= Bjarmason , Victoria Dye , Victoria Dye Precedence: bulk List-ID: X-Mailing-List: git@vger.kernel.org From: Victoria Dye From: Victoria Dye When 'git read-tree' is provided with a prefix, expand the index only if the prefix is equivalent to a sparse directory or contained within one. If the index is not expanded in these cases, 'ce_in_traverse_path' will indicate that the relevant sparse directory is not in the prefix/traverse path, skipping past it and not unpacking the appropriate tree(s). If the prefix is in-cone, its sparse subdirectories (if any) will be traversed correctly without index expansion. The behavior of 'git read-tree' with prefixes 1) inside of cone, 2) equal to a sparse directory, and 3) inside a sparse directory are all tested as part of the 't/t1092-sparse-checkout-compatibility.sh' test 'read-tree --prefix', ensuring that the sparse index case works the way it did prior to this change as well as matching non-sparse index sparse-checkout. Helped-by: Elijah Newren Signed-off-by: Victoria Dye --- builtin/read-tree.c | 3 +- t/t1092-sparse-checkout-compatibility.sh | 8 ++++- unpack-trees.c | 38 ++++++++++++++++++++++++ 3 files changed, 46 insertions(+), 3 deletions(-) diff --git a/builtin/read-tree.c b/builtin/read-tree.c index 0a52cab7752..ec6d038242a 100644 --- a/builtin/read-tree.c +++ b/builtin/read-tree.c @@ -217,8 +217,7 @@ int cmd_read_tree(int argc, const char **argv, const char *cmd_prefix) if (opts.merge && !opts.index_only) setup_work_tree(); - /* TODO: audit sparse index behavior in unpack_trees */ - if (opts.skip_sparse_checkout || opts.prefix) + if (opts.skip_sparse_checkout) ensure_full_index(&the_index); if (opts.merge) { diff --git a/t/t1092-sparse-checkout-compatibility.sh b/t/t1092-sparse-checkout-compatibility.sh index 86241b01a59..d98558f3238 100755 --- a/t/t1092-sparse-checkout-compatibility.sh +++ b/t/t1092-sparse-checkout-compatibility.sh @@ -1417,7 +1417,13 @@ test_expect_success 'sparse index is not expanded: read-tree' ' do ensure_not_expanded read-tree -mu $MERGE_TREES && ensure_not_expanded reset --hard || return 1 - done + done && + + rm -rf sparse-index/deep/deeper2 && + ensure_not_expanded add . && + ensure_not_expanded commit -m "test" && + + ensure_not_expanded read-tree --prefix=deep/deeper2 -u deepest ' test_expect_success 'ls-files' ' diff --git a/unpack-trees.c b/unpack-trees.c index 360844bda3a..f3667d85ec5 100644 --- a/unpack-trees.c +++ b/unpack-trees.c @@ -1693,6 +1693,41 @@ static void populate_from_existing_patterns(struct unpack_trees_options *o, o->pl = pl; } +static void update_sparsity_for_prefix(const char *prefix, + struct index_state *istate) +{ + int prefix_len = strlen(prefix); + struct strbuf ce_prefix = STRBUF_INIT; + + if (!istate->sparse_index) + return; + + while (prefix_len > 0 && prefix[prefix_len - 1] == '/') + prefix_len--; + + if (prefix_len <= 0) + BUG("Invalid prefix passed to update_sparsity_for_prefix"); + + strbuf_grow(&ce_prefix, prefix_len + 1); + strbuf_add(&ce_prefix, prefix, prefix_len); + strbuf_addch(&ce_prefix, '/'); + + /* + * If the prefix points to a sparse directory or a path inside a sparse + * directory, the index should be expanded. This is accomplished in one + * of two ways: + * - if the prefix is inside a sparse directory, it will be expanded by + * the 'ensure_full_index(...)' call in 'index_name_pos(...)'. + * - if the prefix matches an existing sparse directory entry, + * 'index_name_pos(...)' will return its index position, triggering + * the 'ensure_full_index(...)' below. + */ + if (!path_in_cone_mode_sparse_checkout(ce_prefix.buf, istate) && + index_name_pos(istate, ce_prefix.buf, ce_prefix.len) >= 0) + ensure_full_index(istate); + + strbuf_release(&ce_prefix); +} static int verify_absent(const struct cache_entry *, enum unpack_trees_error_types, @@ -1739,6 +1774,9 @@ int unpack_trees(unsigned len, struct tree_desc *t, struct unpack_trees_options setup_standard_excludes(o->dir); } + if (o->prefix) + update_sparsity_for_prefix(o->prefix, o->src_index); + if (!core_apply_sparse_checkout || !o->update) o->skip_sparse_checkout = 1; if (!o->skip_sparse_checkout && !o->pl) { From patchwork Tue Mar 1 20:24:30 2022 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Victoria Dye X-Patchwork-Id: 12765148 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by smtp.lore.kernel.org (Postfix) with ESMTP id 69A99C433FE for ; Tue, 1 Mar 2022 20:26:30 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S238356AbiCAU1J (ORCPT ); Tue, 1 Mar 2022 15:27:09 -0500 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:49874 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S237398AbiCAU0s (ORCPT ); Tue, 1 Mar 2022 15:26:48 -0500 Received: from mail-wr1-x42c.google.com (mail-wr1-x42c.google.com [IPv6:2a00:1450:4864:20::42c]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id C857D8F634 for ; Tue, 1 Mar 2022 12:24:41 -0800 (PST) Received: by mail-wr1-x42c.google.com with SMTP id n14so22274457wrq.7 for ; Tue, 01 Mar 2022 12:24:41 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20210112; h=message-id:in-reply-to:references:from:date:subject:fcc :content-transfer-encoding:mime-version:to:cc; bh=lLJFoJr581XS1Vf5pgj6Oq3aJj6KyBnKtN0B6INs+94=; b=V6GO4FsPSiyi7cBrNRxd1Re5FfCy3//OEsgr12AzkJvJ5Ir+ZYlei+59LRsNGLMPBY Za+euVqIGAWkG2e4znKuY9i4P5uYxm1r32Sdl+E0rB9dBEH4xszZh76601afFEQJ8cf0 xPZ0xrWd8nglNQRAmsruZfEHRC71Bp99iuAUwfcOzBBA/eBysTkONzekK2/L6gM3emxI 2yx0GxrKQcP5PpQXr/St9EVTmaqZx15TSK7w52akLgpy08okredtHHMf33SJQvUBPx+7 zWOqhEtCNWgTiwrR57mfN7oXO43Yh461h1kP0ujedspOuPatVzchVH802FLmb6/1WGOK X8xA== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20210112; h=x-gm-message-state:message-id:in-reply-to:references:from:date :subject:fcc:content-transfer-encoding:mime-version:to:cc; bh=lLJFoJr581XS1Vf5pgj6Oq3aJj6KyBnKtN0B6INs+94=; b=0qq9TcHorIGaXeziUR9lzhSlpiSQ+jjX3KEkFeHgEqOJSlhZA+z63UF1bCzBkdj2es 4nRk0u5h/AiNy78bhe8TuYJoI1Q2GexJRmYzsyEdznekzjAwnm1Rp04BAD6PPeWKf2F/ LqiwZUrJVAhLiA8WTSaEA9H63DC2CeDYGgTAkzUvyFznE6Fa/lCfWOPh5oLKwq6VHF6g LjHkJJr0L2v2w4izVuksSwwKa+pvKkmGCBXVCPz+JuZmRl98zmKTOBXj3vgZ1Tk++Qxi j6aWOnHg3DSi01Z2YLhY7Kyfz/HCaNKGd2u1PrutSTWRtOTcBZbdkt298EyCeSJt+kQf 0mFQ== X-Gm-Message-State: AOAM53208dbE8L7iwqPj2ehza6VTgS8LDb9WDGPzjreB1ECkd98tgjug 114P9tThIaMKByUWxq+iWqMqgkMQXLk= X-Google-Smtp-Source: ABdhPJx7a7hz5UebDtCmxFYI+VNDPXgqp50EFeUpclDt9+pw0aZLZXI+a0FGwPS01x8AqufcZAk3sQ== X-Received: by 2002:adf:d1e9:0:b0:1ea:7d0f:69c7 with SMTP id g9-20020adfd1e9000000b001ea7d0f69c7mr21451857wrd.373.1646166278380; Tue, 01 Mar 2022 12:24:38 -0800 (PST) Received: from [127.0.0.1] ([13.74.141.28]) by smtp.gmail.com with ESMTPSA id f9-20020adffcc9000000b001e9e8163a46sm20730877wrs.54.2022.03.01.12.24.37 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Tue, 01 Mar 2022 12:24:38 -0800 (PST) Message-Id: <71bec3ddad1a086ba9b40ce6b69ad0ad9371cc75.1646166271.git.gitgitgadget@gmail.com> In-Reply-To: References: Date: Tue, 01 Mar 2022 20:24:30 +0000 Subject: [PATCH v3 7/8] read-tree: make two-way merge sparse-aware Fcc: Sent MIME-Version: 1.0 To: git@vger.kernel.org Cc: newren@gmail.com, gitster@pobox.com, Derrick Stolee , =?utf-8?b?w4Z2YXIgQXJuZmrDtnI=?= =?utf-8?b?w7A=?= Bjarmason , Victoria Dye , Victoria Dye Precedence: bulk List-ID: X-Mailing-List: git@vger.kernel.org From: Victoria Dye From: Victoria Dye Enable two-way merge with 'git read-tree' without expanding the sparse index. When in a sparse index, a two-way merge will trivially succeed as long as there are not changes to the same sparse directory in multiple trees (i.e., sparse directory-level "edit-edit" conflicts). If there are such conflicts, the merge will fail despite the possibility that individual files could merge cleanly. In order to resolve these "edit-edit" conflicts, "conflicted" sparse directories are - rather than rejected - merged by traversing their associated trees by OID. For each child of the sparse directory: 1. Files are merged as normal (see Documentation/git-read-tree.txt for details). 2. Subdirectories are treated as sparse directories and merged in 'twoway_merge'. If there are no conflicts, they are merged according to the rules in Documentation/git-read-tree.txt; otherwise, the subdirectory is recursively traversed and merged. This process allows sparse directories to be individually merged at the necessary depth *without* expanding a full index. The 't/t1092-sparse-checkout-compatibility.sh' test 'read-tree --merge with edit/edit conflicts in sparse directories' tests two-way merges with 1) changes inside sparse directories that do not conflict and 2) changes that do conflict (with the correct file(s) reported in the error message). Additionally, add two-way merge cases to 'sparse index is not expanded: read-tree' to confirm that the index is not expanded regardless of whether edit/edit conflicts are present in a sparse directory. Signed-off-by: Victoria Dye --- builtin/read-tree.c | 5 -- t/t1092-sparse-checkout-compatibility.sh | 4 +- unpack-trees.c | 75 ++++++++++++++++++++++++ 3 files changed, 78 insertions(+), 6 deletions(-) diff --git a/builtin/read-tree.c b/builtin/read-tree.c index ec6d038242a..9227f07ab15 100644 --- a/builtin/read-tree.c +++ b/builtin/read-tree.c @@ -229,11 +229,6 @@ int cmd_read_tree(int argc, const char **argv, const char *cmd_prefix) opts.fn = opts.prefix ? bind_merge : oneway_merge; break; case 2: - /* - * TODO: update twoway_merge to handle edit/edit conflicts in - * sparse directories. - */ - ensure_full_index(&the_index); opts.fn = twoway_merge; opts.initial_checkout = is_cache_unborn(); break; diff --git a/t/t1092-sparse-checkout-compatibility.sh b/t/t1092-sparse-checkout-compatibility.sh index d98558f3238..61dc2ea777c 100755 --- a/t/t1092-sparse-checkout-compatibility.sh +++ b/t/t1092-sparse-checkout-compatibility.sh @@ -1413,7 +1413,9 @@ test_expect_success 'sparse index is not expanded: read-tree' ' init_repos && ensure_not_expanded checkout -b test-branch update-folder1 && - for MERGE_TREES in "update-folder2" + for MERGE_TREES in "base update-folder2" \ + "base rename-base" \ + "update-folder2" do ensure_not_expanded read-tree -mu $MERGE_TREES && ensure_not_expanded reset --hard || return 1 diff --git a/unpack-trees.c b/unpack-trees.c index f3667d85ec5..0c2a678cd6d 100644 --- a/unpack-trees.c +++ b/unpack-trees.c @@ -1360,6 +1360,42 @@ static int is_sparse_directory_entry(struct cache_entry *ce, return sparse_dir_matches_path(ce, info, name); } +static int unpack_sparse_callback(int n, unsigned long mask, unsigned long dirmask, struct name_entry *names, struct traverse_info *info) +{ + struct cache_entry *src[MAX_UNPACK_TREES + 1] = { NULL, }; + struct unpack_trees_options *o = info->data; + int ret; + + assert(o->merge); + + /* + * Unlike in 'unpack_callback', where src[0] is derived from the index when + * merging, src[0] is a transient cache entry derived from the first tree + * provided. Create the temporary entry as if it came from a non-sparse index. + */ + if (!is_null_oid(&names[0].oid)) { + src[0] = create_ce_entry(info, &names[0], 0, + &o->result, 1, + dirmask & (1ul << 0)); + src[0]->ce_flags |= (CE_SKIP_WORKTREE | CE_NEW_SKIP_WORKTREE); + } + + /* + * 'unpack_single_entry' assumes that src[0] is derived directly from + * the index, rather than from an entry in 'names'. This is *not* true when + * merging a sparse directory, in which case names[0] is the "index" source + * entry. To match the expectations of 'unpack_single_entry', shift past the + * "index" tree (i.e., names[0]) and adjust 'names', 'n', 'mask', and + * 'dirmask' accordingly. + */ + ret = unpack_single_entry(n - 1, mask >> 1, dirmask >> 1, src, names + 1, info); + + if (src[0]) + discard_cache_entry(src[0]); + + return ret >= 0 ? mask : -1; +} + /* * Note that traverse_by_cache_tree() duplicates some logic in this function * without actually calling it. If you change the logic here you may need to @@ -2472,6 +2508,37 @@ static int merged_entry(const struct cache_entry *ce, return 1; } +static int merged_sparse_dir(const struct cache_entry * const *src, int n, + struct unpack_trees_options *o) +{ + struct tree_desc t[MAX_UNPACK_TREES + 1]; + void * tree_bufs[MAX_UNPACK_TREES + 1]; + struct traverse_info info; + int i, ret; + + /* + * Create the tree traversal information for traversing into *only* the + * sparse directory. + */ + setup_traverse_info(&info, src[0]->name); + info.fn = unpack_sparse_callback; + info.data = o; + info.show_all_errors = o->show_all_errors; + info.pathspec = o->pathspec; + + /* Get the tree descriptors of the sparse directory in each of the merging trees */ + for (i = 0; i < n; i++) + tree_bufs[i] = fill_tree_descriptor(o->src_index->repo, &t[i], + src[i] && !is_null_oid(&src[i]->oid) ? &src[i]->oid : NULL); + + ret = traverse_trees(o->src_index, n, t, &info); + + for (i = 0; i < n; i++) + free(tree_bufs[i]); + + return ret; +} + static int deleted_entry(const struct cache_entry *ce, const struct cache_entry *old, struct unpack_trees_options *o) @@ -2742,6 +2809,14 @@ int twoway_merge(const struct cache_entry * const *src, * reject the merge instead. */ return merged_entry(newtree, current, o); + } else if (S_ISSPARSEDIR(current->ce_mode)) { + /* + * The sparse directories differ, but we don't know whether that's + * because of two different files in the directory being modified + * (can be trivially merged) or if there is a real file conflict. + * Merge the sparse directory by OID to compare file-by-file. + */ + return merged_sparse_dir(src, 3, o); } else return reject_merge(current, o); } From patchwork Tue Mar 1 20:24:31 2022 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Victoria Dye X-Patchwork-Id: 12765146 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by smtp.lore.kernel.org (Postfix) with ESMTP id D982CC433FE for ; Tue, 1 Mar 2022 20:26:25 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S238389AbiCAU1E (ORCPT ); Tue, 1 Mar 2022 15:27:04 -0500 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:50134 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S230144AbiCAU0s (ORCPT ); Tue, 1 Mar 2022 15:26:48 -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 93C8E8F63E for ; Tue, 1 Mar 2022 12:24:42 -0800 (PST) Received: by mail-wr1-x42a.google.com with SMTP id m6so5087179wrr.10 for ; Tue, 01 Mar 2022 12:24:42 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20210112; h=message-id:in-reply-to:references:from:date:subject:fcc :content-transfer-encoding:mime-version:to:cc; bh=H9bNahYcVt/ihTGOw2n84IRXC5Bf/4XszC0K41jHOqQ=; b=OgQy4VbtaiqKSLFPQFGfv78dEGb37wNew8ycpwvwqwEWgLorqQ+BstlJ472BfTvNfv ygnJ2AkYxQ89PCFXk/7vTpyWK8+MqDk6FIZipnc7scIUpprlB72SUHPiivnI0dy/BdlS +cpTs72XZOl7bKmW+ibqegxEx/33mVbZ2NHamQR9R1EVWmIEhlo9e3m/bmzzj4HVP2nu 2wWxxRgFaJA553zCcz6HmxiwqlvkIdyN6ywc7ezWuAGBKAMK37Y0HmWw0ULDJtE9sMrj Hri2rRwg62MbStnzf04kTgTmU5IQnOHUJyiosyT5azab+b+3lrMDs8IdsZGBj+f9nzFW iBSg== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20210112; h=x-gm-message-state:message-id:in-reply-to:references:from:date :subject:fcc:content-transfer-encoding:mime-version:to:cc; bh=H9bNahYcVt/ihTGOw2n84IRXC5Bf/4XszC0K41jHOqQ=; b=DkCvsxUz2q4sn0yXOsjCF9tFqHTNBCBWJuv5gqSDCb4quAehpBcKPczN66cLSIXdTo RlZ9zGkZBdHGw99ESE2LxtwgftKZU1DsZj8rok64R74bak4UwJMdU1LIHZS6LRO49+IL k+6VjFbv4mB0t7mM6IFt1jJG3DfRHOmQ/RHRRCNX93noU09zE+jNcb1YejvGLzjIWyVC rxf+945K34g3M3r3suuPkcWvC14hBV6lqgsO4a7UxMeKqHkSxm0X/tODesravqrCYKdB sFRiO4tTd3mtv0tTytS21kkwayizTyMoMDbPuJcRerK400GYLjTkNjwGIXC4wfIDnT9S AL0g== X-Gm-Message-State: AOAM5320x2AlezbiULmn7oSPI7AfCZyCreyf8u5mm+qrQgJeAOLDAnEi c7VIrO6WEJvd2PxA6jEQ5TOTfDQSEes= X-Google-Smtp-Source: ABdhPJw6DttkBEOBuDHrYfgp5faSgrDwxK1gVGOCWntbSwRuSop9lbRxJTERuQ1uet740LBTKfGTZA== X-Received: by 2002:a05:6000:2c6:b0:1f0:77e:4ed2 with SMTP id o6-20020a05600002c600b001f0077e4ed2mr3778581wry.330.1646166279297; Tue, 01 Mar 2022 12:24:39 -0800 (PST) Received: from [127.0.0.1] ([13.74.141.28]) by smtp.gmail.com with ESMTPSA id d8-20020adfe888000000b001e060f07236sm14460637wrm.14.2022.03.01.12.24.38 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Tue, 01 Mar 2022 12:24:38 -0800 (PST) Message-Id: <6bc11325dd14a67121cf5f5a8e20d83e1d7f4047.1646166271.git.gitgitgadget@gmail.com> In-Reply-To: References: Date: Tue, 01 Mar 2022 20:24:31 +0000 Subject: [PATCH v3 8/8] read-tree: make three-way merge sparse-aware Fcc: Sent MIME-Version: 1.0 To: git@vger.kernel.org Cc: newren@gmail.com, gitster@pobox.com, Derrick Stolee , =?utf-8?b?w4Z2YXIgQXJuZmrDtnI=?= =?utf-8?b?w7A=?= Bjarmason , Victoria Dye , Victoria Dye Precedence: bulk List-ID: X-Mailing-List: git@vger.kernel.org From: Victoria Dye From: Victoria Dye Enable use of 'merged_sparse_dir' in 'threeway_merge'. As with two-way merge, the contents of each conflicted sparse directory are merged without referencing the index, avoiding sparse index expansion. As with two-way merge, the 't/t1092-sparse-checkout-compatibility.sh' test 'read-tree --merge with edit/edit conflicts in sparse directories' confirms that three-way merges with edit/edit changes (both with and without conflicts) inside a sparse directory result in the correct index state or error message. To ensure the index is not unnecessarily expanded, add three-way merge cases to 'sparse index is not expanded: read-tree'. Signed-off-by: Victoria Dye --- builtin/read-tree.c | 5 ---- t/t1092-sparse-checkout-compatibility.sh | 4 ++- unpack-trees.c | 34 ++++++++++++++++++------ 3 files changed, 29 insertions(+), 14 deletions(-) diff --git a/builtin/read-tree.c b/builtin/read-tree.c index 9227f07ab15..9f1f33e9546 100644 --- a/builtin/read-tree.c +++ b/builtin/read-tree.c @@ -234,11 +234,6 @@ int cmd_read_tree(int argc, const char **argv, const char *cmd_prefix) break; case 3: default: - /* - * TODO: update threeway_merge to handle edit/edit conflicts in - * sparse directories. - */ - ensure_full_index(&the_index); opts.fn = threeway_merge; break; } diff --git a/t/t1092-sparse-checkout-compatibility.sh b/t/t1092-sparse-checkout-compatibility.sh index 61dc2ea777c..8be8e3c06a6 100755 --- a/t/t1092-sparse-checkout-compatibility.sh +++ b/t/t1092-sparse-checkout-compatibility.sh @@ -1413,7 +1413,9 @@ test_expect_success 'sparse index is not expanded: read-tree' ' init_repos && ensure_not_expanded checkout -b test-branch update-folder1 && - for MERGE_TREES in "base update-folder2" \ + for MERGE_TREES in "base HEAD update-folder2" \ + "base HEAD rename-base" \ + "base update-folder2" \ "base rename-base" \ "update-folder2" do diff --git a/unpack-trees.c b/unpack-trees.c index 0c2a678cd6d..b876caca0d1 100644 --- a/unpack-trees.c +++ b/unpack-trees.c @@ -2643,16 +2643,24 @@ int threeway_merge(const struct cache_entry * const *stages, */ /* #14, #14ALT, #2ALT */ if (remote && !df_conflict_head && head_match && !remote_match) { - if (index && !same(index, remote) && !same(index, head)) - return reject_merge(index, o); + if (index && !same(index, remote) && !same(index, head)) { + if (S_ISSPARSEDIR(index->ce_mode)) + return merged_sparse_dir(stages, 4, o); + else + return reject_merge(index, o); + } return merged_entry(remote, index, o); } /* * If we have an entry in the index cache, then we want to * make sure that it matches head. */ - if (index && !same(index, head)) - return reject_merge(index, o); + if (index && !same(index, head)) { + if (S_ISSPARSEDIR(index->ce_mode)) + return merged_sparse_dir(stages, 4, o); + else + return reject_merge(index, o); + } if (head) { /* #5ALT, #15 */ @@ -2714,11 +2722,21 @@ int threeway_merge(const struct cache_entry * const *stages, } - /* Below are "no merge" cases, which require that the index be - * up-to-date to avoid the files getting overwritten with - * conflict resolution files. - */ + /* Handle "no merge" cases (see t/t1000-read-tree-m-3way.sh) */ if (index) { + /* + * If we've reached the "no merge" cases and we're merging + * a sparse directory, we may have an "edit/edit" conflict that + * can be resolved by individually merging directory contents. + */ + if (S_ISSPARSEDIR(index->ce_mode)) + return merged_sparse_dir(stages, 4, o); + + /* + * If we're not merging a sparse directory, ensure the index is + * up-to-date to avoid files getting overwritten with conflict + * resolution files + */ if (verify_uptodate(index, o)) return -1; }