From patchwork Tue Nov 9 23:09:38 2021 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 8bit X-Patchwork-Submitter: Anders Kaseorg X-Patchwork-Id: 12611185 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 B447CC433F5 for ; Tue, 9 Nov 2021 23:10:00 +0000 (UTC) Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by mail.kernel.org (Postfix) with ESMTP id 92FDC61131 for ; Tue, 9 Nov 2021 23:10:00 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S240795AbhKIXMq (ORCPT ); Tue, 9 Nov 2021 18:12:46 -0500 Received: from outgoing-auth-1.mit.edu ([18.9.28.11]:52866 "EHLO outgoing.mit.edu" rhost-flags-OK-OK-OK-FAIL) by vger.kernel.org with ESMTP id S232159AbhKIXMp (ORCPT ); Tue, 9 Nov 2021 18:12:45 -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 1A9N9mKq014709 (version=TLSv1/SSLv3 cipher=AES256-GCM-SHA384 bits=256 verify=NOT); Tue, 9 Nov 2021 18:09:50 -0500 From: Anders Kaseorg To: Junio C Hamano Cc: Johannes Schindelin , Jeff King , git@vger.kernel.org, Andreas Heiduk , Anders Kaseorg Subject: [PATCH v5 1/4] fetch: Protect branches checked out in all worktrees Date: Tue, 9 Nov 2021 15:09:38 -0800 Message-Id: <20211109230941.2518143-1-andersk@mit.edu> X-Mailer: git-send-email 2.33.1 In-Reply-To: <2f983e36-532f-ac87-9ade-fba4c6b9d276@mit.edu> References: <2f983e36-532f-ac87-9ade-fba4c6b9d276@mit.edu> 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 Signed-off-by: Anders Kaseorg --- builtin/fetch.c | 29 +++++++++++++++-------------- t/t5516-fetch-push.sh | 18 ++++++++++++++++++ 2 files changed, 33 insertions(+), 14 deletions(-) diff --git a/builtin/fetch.c b/builtin/fetch.c index f7abbc31ff..ed8a906717 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,14 @@ 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)) && + !wt->is_bare) + 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..f07e32126f 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 branch -D 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 23:09:39 2021 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 8bit X-Patchwork-Submitter: Anders Kaseorg X-Patchwork-Id: 12611191 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 57B48C433F5 for ; Tue, 9 Nov 2021 23:10:37 +0000 (UTC) Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by mail.kernel.org (Postfix) with ESMTP id 3C7E761105 for ; Tue, 9 Nov 2021 23:10:37 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S243060AbhKIXNW (ORCPT ); Tue, 9 Nov 2021 18:13:22 -0500 Received: from outgoing-auth-1.mit.edu ([18.9.28.11]:52985 "EHLO outgoing.mit.edu" rhost-flags-OK-OK-OK-FAIL) by vger.kernel.org with ESMTP id S242659AbhKIXNU (ORCPT ); Tue, 9 Nov 2021 18:13:20 -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 1A9NADPW014856 (version=TLSv1/SSLv3 cipher=AES256-GCM-SHA384 bits=256 verify=NOT); Tue, 9 Nov 2021 18:10:15 -0500 From: Anders Kaseorg To: Junio C Hamano Cc: Johannes Schindelin , Jeff King , git@vger.kernel.org, Andreas Heiduk , Anders Kaseorg Subject: [PATCH v5 2/4] receive-pack: Clean dead code from update_worktree() Date: Tue, 9 Nov 2021 15:09:39 -0800 Message-Id: <20211109230941.2518143-2-andersk@mit.edu> X-Mailer: git-send-email 2.33.1 In-Reply-To: <20211109230941.2518143-1-andersk@mit.edu> References: <2f983e36-532f-ac87-9ade-fba4c6b9d276@mit.edu> <20211109230941.2518143-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 | 21 +++++++-------------- 1 file changed, 7 insertions(+), 14 deletions(-) diff --git a/builtin/receive-pack.c b/builtin/receive-pack.c index 49b846d960..542431e692 100644 --- a/builtin/receive-pack.c +++ b/builtin/receive-pack.c @@ -1449,29 +1449,22 @@ 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 (!worktree || !worktree->path) + BUG("worktree->path must be non-NULL"); 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 +1572,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 23:09:40 2021 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 8bit X-Patchwork-Submitter: Anders Kaseorg X-Patchwork-Id: 12611187 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 02B64C433F5 for ; Tue, 9 Nov 2021 23:10:29 +0000 (UTC) Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by mail.kernel.org (Postfix) with ESMTP id DA1BB610F8 for ; Tue, 9 Nov 2021 23:10:28 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S241204AbhKIXNO (ORCPT ); Tue, 9 Nov 2021 18:13:14 -0500 Received: from outgoing-auth-1.mit.edu ([18.9.28.11]:52961 "EHLO outgoing.mit.edu" rhost-flags-OK-OK-OK-FAIL) by vger.kernel.org with ESMTP id S232159AbhKIXNN (ORCPT ); Tue, 9 Nov 2021 18:13:13 -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 1A9NAHpd014870 (version=TLSv1/SSLv3 cipher=AES256-GCM-SHA384 bits=256 verify=NOT); Tue, 9 Nov 2021 18:10:18 -0500 From: Anders Kaseorg To: Junio C Hamano Cc: Johannes Schindelin , Jeff King , git@vger.kernel.org, Andreas Heiduk , Anders Kaseorg Subject: [PATCH v5 3/4] receive-pack: Protect current branch for bare repository worktree Date: Tue, 9 Nov 2021 15:09:40 -0800 Message-Id: <20211109230941.2518143-3-andersk@mit.edu> X-Mailer: git-send-email 2.33.1 In-Reply-To: <20211109230941.2518143-1-andersk@mit.edu> References: <2f983e36-532f-ac87-9ade-fba4c6b9d276@mit.edu> <20211109230941.2518143-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 | 6 +++--- t/t5516-fetch-push.sh | 14 ++++++++++++++ 2 files changed, 17 insertions(+), 3 deletions(-) diff --git a/builtin/receive-pack.c b/builtin/receive-pack.c index 542431e692..04a2ec6abc 100644 --- a/builtin/receive-pack.c +++ b/builtin/receive-pack.c @@ -1455,7 +1455,7 @@ static const char *update_worktree(unsigned char *sha1, const struct worktree *w if (!worktree || !worktree->path) BUG("worktree->path must be non-NULL"); - if (is_bare_repository()) + if (worktree->is_bare) return "denyCurrentBranch = updateInstead needs a worktree"; git_dir = get_worktree_git_dir(worktree); @@ -1479,7 +1479,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)) { @@ -1491,7 +1491,7 @@ static const char *update(struct command *cmd, struct shallow_info *si) free(namespaced_name); namespaced_name = strbuf_detach(&namespaced_name_buf, NULL); - if (worktree) { + if (worktree && !worktree->is_bare) { switch (deny_current_branch) { case DENY_IGNORE: break; diff --git a/t/t5516-fetch-push.sh b/t/t5516-fetch-push.sh index f07e32126f..4847793a1c 100755 --- a/t/t5516-fetch-push.sh +++ b/t/t5516-fetch-push.sh @@ -1769,9 +1769,23 @@ test_expect_success 'denyCurrentBranch and worktrees' ' test_must_fail git -C cloned push origin HEAD:new-wt && test_config receive.denyCurrentBranch updateInstead && git -C cloned push origin HEAD:new-wt && + test_path_exists new-wt/first.t && 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_path_exists bare.git/wt/grape.t && + 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 branch -D wt" && git worktree add wt && From patchwork Tue Nov 9 23:09:41 2021 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Anders Kaseorg X-Patchwork-Id: 12611189 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 68227C433F5 for ; Tue, 9 Nov 2021 23:10:35 +0000 (UTC) Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by mail.kernel.org (Postfix) with ESMTP id 46F1161105 for ; Tue, 9 Nov 2021 23:10:35 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S242977AbhKIXNU (ORCPT ); Tue, 9 Nov 2021 18:13:20 -0500 Received: from outgoing-auth-1.mit.edu ([18.9.28.11]:52979 "EHLO outgoing.mit.edu" rhost-flags-OK-OK-OK-FAIL) by vger.kernel.org with ESMTP id S242425AbhKIXNS (ORCPT ); Tue, 9 Nov 2021 18:13:18 -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 1A9NAKLX014889 (version=TLSv1/SSLv3 cipher=AES256-GCM-SHA384 bits=256 verify=NOT); Tue, 9 Nov 2021 18:10:22 -0500 From: Anders Kaseorg To: Junio C Hamano Cc: Johannes Schindelin , Jeff King , git@vger.kernel.org, Andreas Heiduk , Anders Kaseorg Subject: [PATCH v5 4/4] branch: Protect branches checked out in all worktrees Date: Tue, 9 Nov 2021 15:09:41 -0800 Message-Id: <20211109230941.2518143-4-andersk@mit.edu> X-Mailer: git-send-email 2.33.1 In-Reply-To: <20211109230941.2518143-1-andersk@mit.edu> References: <2f983e36-532f-ac87-9ade-fba4c6b9d276@mit.edu> <20211109230941.2518143-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 &&