From patchwork Tue Nov 9 03:00:25 2021 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 8bit X-Patchwork-Submitter: Anders Kaseorg X-Patchwork-Id: 12609629 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 mail.kernel.org (mail.kernel.org [198.145.29.99]) by smtp.lore.kernel.org (Postfix) with ESMTP id 160E5C433F5 for ; Tue, 9 Nov 2021 03:01:29 +0000 (UTC) Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by mail.kernel.org (Postfix) with ESMTP id F16C56120A for ; Tue, 9 Nov 2021 03:01:28 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S242283AbhKIDEM (ORCPT ); Mon, 8 Nov 2021 22:04:12 -0500 Received: from outgoing-auth-1.mit.edu ([18.9.28.11]:42745 "EHLO outgoing.mit.edu" rhost-flags-OK-OK-OK-FAIL) by vger.kernel.org with ESMTP id S242265AbhKIDD7 (ORCPT ); Mon, 8 Nov 2021 22:03:59 -0500 Received: from localhost (198-27-191-186.fiber.dynamic.sonic.net [198.27.191.186]) (authenticated bits=0) (User authenticated as andersk@ATHENA.MIT.EDU) by outgoing.mit.edu (8.14.7/8.12.4) with ESMTP id 1A930tXD005286 (version=TLSv1/SSLv3 cipher=AES256-GCM-SHA384 bits=256 verify=NOT); Mon, 8 Nov 2021 22:00:57 -0500 From: Anders Kaseorg To: Junio C Hamano Cc: Jeff King , git@vger.kernel.org, Andreas Heiduk , Johannes Schindelin , Anders Kaseorg Subject: [PATCH v4 1/4] fetch: Protect branches checked out in all worktrees Date: Mon, 8 Nov 2021 19:00:25 -0800 Message-Id: <20211109030028.2196416-1-andersk@mit.edu> X-Mailer: git-send-email 2.33.1 In-Reply-To: References: MIME-Version: 1.0 Precedence: bulk List-ID: X-Mailing-List: git@vger.kernel.org Refuse to fetch into the currently checked out branch of any working tree, not just the current one. Fixes this previously reported bug: https://public-inbox.org/git/cb957174-5e9a-5603-ea9e-ac9b58a2eaad@mathema.de As a side effect of using find_shared_symref, we’ll also refuse the fetch when we’re on a detached HEAD because we’re rebasing or bisecting on the branch in question. This seems like a sensible change. Signed-off-by: Anders Kaseorg --- builtin/fetch.c | 28 ++++++++++++++-------------- t/t5516-fetch-push.sh | 18 ++++++++++++++++++ 2 files changed, 32 insertions(+), 14 deletions(-) diff --git a/builtin/fetch.c b/builtin/fetch.c index f7abbc31ff..0ef2170ef9 100644 --- a/builtin/fetch.c +++ b/builtin/fetch.c @@ -28,6 +28,7 @@ #include "promisor-remote.h" #include "commit-graph.h" #include "shallow.h" +#include "worktree.h" #define FORCED_UPDATES_DELAY_WARNING_IN_MS (10 * 1000) @@ -854,7 +855,7 @@ static int update_local_ref(struct ref *ref, int summary_width) { struct commit *current = NULL, *updated; - struct branch *current_branch = branch_get(NULL); + const struct worktree *wt; const char *pretty_ref = prettify_refname(ref->name); int fast_forward = 0; @@ -868,16 +869,18 @@ static int update_local_ref(struct ref *ref, return 0; } - if (current_branch && - !strcmp(ref->name, current_branch->name) && - !(update_head_ok || is_bare_repository()) && + if (!update_head_ok && + (wt = find_shared_symref("HEAD", ref->name)) && + !wt->is_bare && !is_null_oid(&ref->old_oid)) { /* * If this is the head, and it's not okay to update * the head, and the old value of the head isn't empty... */ format_display(display, '!', _("[rejected]"), - _("can't fetch in current branch"), + wt->is_current ? + _("can't fetch in current branch") : + _("checked out in another worktree"), remote, pretty_ref, summary_width); return 1; } @@ -1387,16 +1390,13 @@ static int prune_refs(struct refspec *rs, struct ref *ref_map, static void check_not_current_branch(struct ref *ref_map) { - struct branch *current_branch = branch_get(NULL); - - if (is_bare_repository() || !current_branch) - return; - + const struct worktree *wt; for (; ref_map; ref_map = ref_map->next) - if (ref_map->peer_ref && !strcmp(current_branch->refname, - ref_map->peer_ref->name)) - die(_("Refusing to fetch into current branch %s " - "of non-bare repository"), current_branch->refname); + if (ref_map->peer_ref && + (wt = find_shared_symref("HEAD", ref_map->peer_ref->name))) + die(_("Refusing to fetch into branch '%s' " + "checked out at '%s'"), + ref_map->peer_ref->name, wt->path); } static int truncate_fetch_head(void) diff --git a/t/t5516-fetch-push.sh b/t/t5516-fetch-push.sh index 8212ca56dc..2c2d6fa6e7 100755 --- a/t/t5516-fetch-push.sh +++ b/t/t5516-fetch-push.sh @@ -1771,4 +1771,22 @@ test_expect_success 'denyCurrentBranch and worktrees' ' git -C cloned push origin HEAD:new-wt && test_must_fail git -C cloned push --delete origin new-wt ' + +test_expect_success 'refuse fetch to current branch of worktree' ' + test_when_finished "git worktree remove --force wt" && + git worktree add wt && + test_commit apple && + test_must_fail git fetch . HEAD:wt && + git fetch -u . HEAD:wt +' + +test_expect_success 'refuse fetch to current branch of bare repository worktree' ' + test_when_finished "rm -fr bare.git" && + git clone --bare . bare.git && + git -C bare.git worktree add wt && + test_commit banana && + test_must_fail git -C bare.git fetch .. HEAD:wt && + git -C bare.git fetch -u .. HEAD:wt +' + test_done From patchwork Tue Nov 9 03:00:26 2021 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 8bit X-Patchwork-Submitter: Anders Kaseorg X-Patchwork-Id: 12609631 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 mail.kernel.org (mail.kernel.org [198.145.29.99]) by smtp.lore.kernel.org (Postfix) with ESMTP id 7434BC433EF for ; Tue, 9 Nov 2021 03:01:39 +0000 (UTC) Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by mail.kernel.org (Postfix) with ESMTP id 5D05B6120A for ; Tue, 9 Nov 2021 03:01:39 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S242271AbhKIDEX (ORCPT ); Mon, 8 Nov 2021 22:04:23 -0500 Received: from outgoing-auth-1.mit.edu ([18.9.28.11]:42844 "EHLO outgoing.mit.edu" rhost-flags-OK-OK-OK-FAIL) by vger.kernel.org with ESMTP id S242270AbhKIDEX (ORCPT ); Mon, 8 Nov 2021 22:04:23 -0500 Received: from localhost (198-27-191-186.fiber.dynamic.sonic.net [198.27.191.186]) (authenticated bits=0) (User authenticated as andersk@ATHENA.MIT.EDU) by outgoing.mit.edu (8.14.7/8.12.4) with ESMTP id 1A931Q5B005553 (version=TLSv1/SSLv3 cipher=AES256-GCM-SHA384 bits=256 verify=NOT); Mon, 8 Nov 2021 22:01:28 -0500 From: Anders Kaseorg To: Junio C Hamano Cc: Jeff King , git@vger.kernel.org, Andreas Heiduk , Johannes Schindelin , Anders Kaseorg Subject: [PATCH v4 2/4] receive-pack: Clean dead code from update_worktree() Date: Mon, 8 Nov 2021 19:00:26 -0800 Message-Id: <20211109030028.2196416-2-andersk@mit.edu> X-Mailer: git-send-email 2.33.1 In-Reply-To: <20211109030028.2196416-1-andersk@mit.edu> References: <20211109030028.2196416-1-andersk@mit.edu> MIME-Version: 1.0 Precedence: bulk List-ID: X-Mailing-List: git@vger.kernel.org update_worktree() can only be called with a non-NULL worktree parameter, because that’s the only case where we set do_update_worktree = 1. worktree->path is always initialized to non-NULL. Signed-off-by: Anders Kaseorg --- builtin/receive-pack.c | 20 +++++--------------- 1 file changed, 5 insertions(+), 15 deletions(-) diff --git a/builtin/receive-pack.c b/builtin/receive-pack.c index 49b846d960..cf575280fc 100644 --- a/builtin/receive-pack.c +++ b/builtin/receive-pack.c @@ -1449,29 +1449,19 @@ static const char *push_to_checkout(unsigned char *hash, static const char *update_worktree(unsigned char *sha1, const struct worktree *worktree) { - const char *retval, *work_tree, *git_dir = NULL; + const char *retval, *git_dir; struct strvec env = STRVEC_INIT; - if (worktree && worktree->path) - work_tree = worktree->path; - else if (git_work_tree_cfg) - work_tree = git_work_tree_cfg; - else - work_tree = ".."; - if (is_bare_repository()) return "denyCurrentBranch = updateInstead needs a worktree"; - if (worktree) - git_dir = get_worktree_git_dir(worktree); - if (!git_dir) - git_dir = get_git_dir(); + git_dir = get_worktree_git_dir(worktree); strvec_pushf(&env, "GIT_DIR=%s", absolute_path(git_dir)); if (!hook_exists(push_to_checkout_hook)) - retval = push_to_deploy(sha1, &env, work_tree); + retval = push_to_deploy(sha1, &env, worktree->path); else - retval = push_to_checkout(sha1, &env, work_tree); + retval = push_to_checkout(sha1, &env, worktree->path); strvec_clear(&env); return retval; @@ -1579,7 +1569,7 @@ static const char *update(struct command *cmd, struct shallow_info *si) } if (do_update_worktree) { - ret = update_worktree(new_oid->hash, find_shared_symref("HEAD", name)); + ret = update_worktree(new_oid->hash, worktree); if (ret) return ret; } From patchwork Tue Nov 9 03:00:27 2021 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 8bit X-Patchwork-Submitter: Anders Kaseorg X-Patchwork-Id: 12609633 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 mail.kernel.org (mail.kernel.org [198.145.29.99]) by smtp.lore.kernel.org (Postfix) with ESMTP id 85E30C433F5 for ; Tue, 9 Nov 2021 03:01:51 +0000 (UTC) Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by mail.kernel.org (Postfix) with ESMTP id 66938610A0 for ; Tue, 9 Nov 2021 03:01:51 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S242288AbhKIDEf (ORCPT ); Mon, 8 Nov 2021 22:04:35 -0500 Received: from outgoing-auth-1.mit.edu ([18.9.28.11]:42859 "EHLO outgoing.mit.edu" rhost-flags-OK-OK-OK-FAIL) by vger.kernel.org with ESMTP id S242286AbhKIDE1 (ORCPT ); Mon, 8 Nov 2021 22:04:27 -0500 Received: from localhost (198-27-191-186.fiber.dynamic.sonic.net [198.27.191.186]) (authenticated bits=0) (User authenticated as andersk@ATHENA.MIT.EDU) by outgoing.mit.edu (8.14.7/8.12.4) with ESMTP id 1A931UDP005600 (version=TLSv1/SSLv3 cipher=AES256-GCM-SHA384 bits=256 verify=NOT); Mon, 8 Nov 2021 22:01:32 -0500 From: Anders Kaseorg To: Junio C Hamano Cc: Jeff King , git@vger.kernel.org, Andreas Heiduk , Johannes Schindelin , Anders Kaseorg Subject: [PATCH v4 3/4] receive-pack: Protect current branch for bare repository worktree Date: Mon, 8 Nov 2021 19:00:27 -0800 Message-Id: <20211109030028.2196416-3-andersk@mit.edu> X-Mailer: git-send-email 2.33.1 In-Reply-To: <20211109030028.2196416-1-andersk@mit.edu> References: <20211109030028.2196416-1-andersk@mit.edu> MIME-Version: 1.0 Precedence: bulk List-ID: X-Mailing-List: git@vger.kernel.org A bare repository won’t have a working tree at "..", but it may still have separate working trees created with git worktree. We should protect the current branch of such working trees from being updated or deleted, according to receive.denyCurrentBranch. Signed-off-by: Anders Kaseorg --- builtin/receive-pack.c | 4 +--- t/t5516-fetch-push.sh | 12 ++++++++++++ 2 files changed, 13 insertions(+), 3 deletions(-) diff --git a/builtin/receive-pack.c b/builtin/receive-pack.c index cf575280fc..5a3c6d8423 100644 --- a/builtin/receive-pack.c +++ b/builtin/receive-pack.c @@ -1452,8 +1452,6 @@ static const char *update_worktree(unsigned char *sha1, const struct worktree *w const char *retval, *git_dir; struct strvec env = STRVEC_INIT; - if (is_bare_repository()) - return "denyCurrentBranch = updateInstead needs a worktree"; git_dir = get_worktree_git_dir(worktree); strvec_pushf(&env, "GIT_DIR=%s", absolute_path(git_dir)); @@ -1476,7 +1474,7 @@ static const char *update(struct command *cmd, struct shallow_info *si) struct object_id *old_oid = &cmd->old_oid; struct object_id *new_oid = &cmd->new_oid; int do_update_worktree = 0; - const struct worktree *worktree = is_bare_repository() ? NULL : find_shared_symref("HEAD", name); + const struct worktree *worktree = find_shared_symref("HEAD", name); /* only refs/... are allowed */ if (!starts_with(name, "refs/") || check_refname_format(name + 5, 0)) { diff --git a/t/t5516-fetch-push.sh b/t/t5516-fetch-push.sh index 2c2d6fa6e7..06cd34b0db 100755 --- a/t/t5516-fetch-push.sh +++ b/t/t5516-fetch-push.sh @@ -1772,6 +1772,18 @@ test_expect_success 'denyCurrentBranch and worktrees' ' test_must_fail git -C cloned push --delete origin new-wt ' +test_expect_success 'denyCurrentBranch and bare repository worktrees' ' + test_when_finished "rm -fr bare.git" && + git clone --bare . bare.git && + git -C bare.git worktree add wt && + test_commit grape && + test_config -C bare.git receive.denyCurrentBranch refuse && + test_must_fail git push bare.git HEAD:wt && + test_config -C bare.git receive.denyCurrentBranch updateInstead && + git push bare.git HEAD:wt && + test_must_fail git push --delete bare.git wt +' + test_expect_success 'refuse fetch to current branch of worktree' ' test_when_finished "git worktree remove --force wt" && git worktree add wt && From patchwork Tue Nov 9 03:00:28 2021 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Anders Kaseorg X-Patchwork-Id: 12609635 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 mail.kernel.org (mail.kernel.org [198.145.29.99]) by smtp.lore.kernel.org (Postfix) with ESMTP id 9A08CC433EF for ; Tue, 9 Nov 2021 03:01:52 +0000 (UTC) Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by mail.kernel.org (Postfix) with ESMTP id 84B206120A for ; Tue, 9 Nov 2021 03:01:52 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S242289AbhKIDEg (ORCPT ); Mon, 8 Nov 2021 22:04:36 -0500 Received: from outgoing-auth-1.mit.edu ([18.9.28.11]:42872 "EHLO outgoing.mit.edu" rhost-flags-OK-OK-OK-FAIL) by vger.kernel.org with ESMTP id S242285AbhKIDEb (ORCPT ); Mon, 8 Nov 2021 22:04:31 -0500 Received: from localhost (198-27-191-186.fiber.dynamic.sonic.net [198.27.191.186]) (authenticated bits=0) (User authenticated as andersk@ATHENA.MIT.EDU) by outgoing.mit.edu (8.14.7/8.12.4) with ESMTP id 1A931ZuH005659 (version=TLSv1/SSLv3 cipher=AES256-GCM-SHA384 bits=256 verify=NOT); Mon, 8 Nov 2021 22:01:37 -0500 From: Anders Kaseorg To: Junio C Hamano Cc: Jeff King , git@vger.kernel.org, Andreas Heiduk , Johannes Schindelin , Anders Kaseorg Subject: [PATCH v4 4/4] branch: Protect branches checked out in all worktrees Date: Mon, 8 Nov 2021 19:00:28 -0800 Message-Id: <20211109030028.2196416-4-andersk@mit.edu> X-Mailer: git-send-email 2.33.1 In-Reply-To: <20211109030028.2196416-1-andersk@mit.edu> References: <20211109030028.2196416-1-andersk@mit.edu> MIME-Version: 1.0 Precedence: bulk List-ID: X-Mailing-List: git@vger.kernel.org Refuse to force-move a branch over the currently checked out branch of any working tree, not just the current one. Signed-off-by: Anders Kaseorg --- branch.c | 10 ++++++---- t/t3200-branch.sh | 7 +++++++ 2 files changed, 13 insertions(+), 4 deletions(-) diff --git a/branch.c b/branch.c index 07a46430b3..581f0c02c2 100644 --- a/branch.c +++ b/branch.c @@ -199,7 +199,7 @@ int validate_branchname(const char *name, struct strbuf *ref) */ int validate_new_branchname(const char *name, struct strbuf *ref, int force) { - const char *head; + const struct worktree *wt; if (!validate_branchname(name, ref)) return 0; @@ -208,9 +208,11 @@ int validate_new_branchname(const char *name, struct strbuf *ref, int force) die(_("A branch named '%s' already exists."), ref->buf + strlen("refs/heads/")); - head = resolve_ref_unsafe("HEAD", 0, NULL, NULL); - if (!is_bare_repository() && head && !strcmp(head, ref->buf)) - die(_("Cannot force update the current branch.")); + wt = find_shared_symref("HEAD", ref->buf); + if (wt && !wt->is_bare) + die(_("Cannot force update the branch '%s'" + "checked out at '%s'."), + ref->buf + strlen("refs/heads/"), wt->path); return 1; } diff --git a/t/t3200-branch.sh b/t/t3200-branch.sh index e575ffb4ff..4c868bf971 100755 --- a/t/t3200-branch.sh +++ b/t/t3200-branch.sh @@ -168,6 +168,13 @@ test_expect_success 'git branch -M foo bar should fail when bar is checked out' test_must_fail git branch -M bar foo ' +test_expect_success 'git branch -M foo bar should fail when bar is checked out in worktree' ' + git branch -f bar && + test_when_finished "git worktree remove wt && git branch -D wt" && + git worktree add wt && + test_must_fail git branch -M bar wt +' + test_expect_success 'git branch -M baz bam should succeed when baz is checked out' ' git checkout -b baz && git branch bam &&