From patchwork Thu Dec 28 09:57:31 2023 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Patrick Steinhardt X-Patchwork-Id: 13505777 Received: from out1-smtp.messagingengine.com (out1-smtp.messagingengine.com [66.111.4.25]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id C021B6AA2 for ; Thu, 28 Dec 2023 09:57:39 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; dmarc=none (p=none dis=none) header.from=pks.im Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=pks.im Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=pks.im header.i=@pks.im header.b="p7WnTrYl"; dkim=pass (2048-bit key) header.d=messagingengine.com header.i=@messagingengine.com header.b="vqb8rIFr" Received: from compute2.internal (compute2.nyi.internal [10.202.2.46]) by mailout.nyi.internal (Postfix) with ESMTP id DA7205C0089; Thu, 28 Dec 2023 04:57:38 -0500 (EST) Received: from mailfrontend2 ([10.202.2.163]) by compute2.internal (MEProxy); Thu, 28 Dec 2023 04:57:38 -0500 DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=pks.im; h=cc:cc :content-type:content-type:date:date:from:from:in-reply-to :in-reply-to:message-id:mime-version:references:reply-to:subject :subject:to:to; s=fm2; t=1703757458; x=1703843858; bh=wgmWzHXUNE sMqAgViqXe+mlFAT4T1MC0+tcWR0vphXU=; b=p7WnTrYl95qaURqhH83HGuuftS Yn0Iaubox65R2wTT0iQwZ5BN4RIvbI9LCzPxyKNMlapat/Kk2PRaBhFqC/g7iw1C IOuD4isJfesHzIyHv7pCas7yNmThqRyR8z/67ZvoJhLZVyXBT9SymqpXU2AEK1fn MJnZC2zIIN/J5dYFDsvy9iXgkTbdx3tHnpBGbL266zqxM7eBuPB+IKIM3kMNDHON l75HHBCCYvdkuQTWVsl7/aGUytUN4lNXEZmfxojNqV5EYnEGkkwDOb0+LCZNdYtu F568Zj24KwxQQpxHFQF0WLnQP+oT+9GLCeajWauG337kypE1C9oTb3lrnnFg== DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d= messagingengine.com; h=cc:cc:content-type:content-type:date:date :feedback-id:feedback-id:from:from:in-reply-to:in-reply-to :message-id:mime-version:references:reply-to:subject:subject:to :to:x-me-proxy:x-me-proxy:x-me-sender:x-me-sender:x-sasl-enc; s= fm2; t=1703757458; x=1703843858; bh=wgmWzHXUNEsMqAgViqXe+mlFAT4T 1MC0+tcWR0vphXU=; b=vqb8rIFrcviFHqPzfGmz/VIHmNHRYhrERVawUED//EjS IedQScF8YFd25ThTZd45y2Q+MvEY2DsDRJA5S42tNDeKLiAmYRm1Aq4fhHoEiPaK HOmNRhei7oW+3tvhAGjgudpmWForKRNK2a5PSNOw4UJwKDN6wt9GHqn9O31lNOwx chNub/IVpfkrUnrYoQAqe5a8IYoYjuSU0iHnWotUOxltlUjU5TL0ET1rCyzf+3Bo YIOeBDFnF60ZjJ3DQnlCi1z4vbgeUQ69vIrf9BDrEqR10h5NhPRPFXpdN5O2FLfC 8bQwwYfgOoV1nQ4fdJB3ESEB/gFWRx+ifFkwlHFgZw== X-ME-Sender: X-ME-Received: X-ME-Proxy-Cause: gggruggvucftvghtrhhoucdtuddrgedvkedrvdefuddguddtucetufdoteggodetrfdotf fvucfrrhhofhhilhgvmecuhfgrshhtofgrihhlpdfqfgfvpdfurfetoffkrfgpnffqhgen uceurghilhhouhhtmecufedttdenucesvcftvggtihhpihgvnhhtshculddquddttddmne cujfgurhepfffhvfevuffkfhggtggujgesghdtreertddtvdenucfhrhhomheprfgrthhr ihgtkhcuufhtvghinhhhrghrughtuceophhssehpkhhsrdhimheqnecuggftrfgrthhtvg hrnhepueektdevtdffveeljeetgfehheeigeekleduvdeffeeghefgledttdehjeelffet necuvehluhhsthgvrhfuihiivgepudenucfrrghrrghmpehmrghilhhfrhhomhepphhsse hpkhhsrdhimh X-ME-Proxy: Feedback-ID: i197146af:Fastmail Received: by mail.messagingengine.com (Postfix) with ESMTPA; Thu, 28 Dec 2023 04:57:37 -0500 (EST) Received: by vm-mail (OpenSMTPD) with ESMTPSA id 948ee963 (TLSv1.3:TLS_AES_256_GCM_SHA384:256:NO); Thu, 28 Dec 2023 09:55:19 +0000 (UTC) Date: Thu, 28 Dec 2023 10:57:31 +0100 From: Patrick Steinhardt To: git@vger.kernel.org Cc: Karthik Nayak , Junio C Hamano Subject: [PATCH v2 02/12] worktree: skip reading HEAD when repairing worktrees Message-ID: References: Precedence: bulk X-Mailing-List: git@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Disposition: inline In-Reply-To: When calling `git init --separate-git-dir=` on a preexisting repository, we move the Git directory of that repository to the new path specified by the user. If there are worktrees present in the repository, we need to repair the worktrees so that their gitlinks point to the new location of the repository. This repair logic will load repositories via `get_worktrees()`, which will enumerate up and initialize all worktrees. Part of initialization is logic that we resolve their respective worktree HEADs, even though that information may not actually be needed in the end by all callers. In the context of git-init(1) this is about to become a problem, because we do not have a repository that was set up via `setup_git_directory()` or friends. Consequentially, it is not yet fully initialized at the time of calling `repair_worktrees()`, and properly setting up all parts of the repository in `init_db()` before we repair worktrees is not an easy thing to do. While this is okay right now where we only have a single reference backend in Git, once we gain a second one we would be trying to look up the worktree HEADs before we have figured out the reference format, which does not work. We do not require the worktree HEADs at all to repair worktrees. So let's fix this issue by skipping over the step that reads them. Signed-off-by: Patrick Steinhardt --- worktree.c | 24 ++++++++++++++++-------- 1 file changed, 16 insertions(+), 8 deletions(-) diff --git a/worktree.c b/worktree.c index a56a6c2a3d..9702ed0308 100644 --- a/worktree.c +++ b/worktree.c @@ -51,7 +51,7 @@ static void add_head_info(struct worktree *wt) /** * get the main worktree */ -static struct worktree *get_main_worktree(void) +static struct worktree *get_main_worktree(int skip_reading_head) { struct worktree *worktree = NULL; struct strbuf worktree_path = STRBUF_INIT; @@ -70,11 +70,13 @@ static struct worktree *get_main_worktree(void) */ worktree->is_bare = (is_bare_repository_cfg == 1) || is_bare_repository(); - add_head_info(worktree); + if (!skip_reading_head) + add_head_info(worktree); return worktree; } -static struct worktree *get_linked_worktree(const char *id) +static struct worktree *get_linked_worktree(const char *id, + int skip_reading_head) { struct worktree *worktree = NULL; struct strbuf path = STRBUF_INIT; @@ -93,7 +95,8 @@ static struct worktree *get_linked_worktree(const char *id) CALLOC_ARRAY(worktree, 1); worktree->path = strbuf_detach(&worktree_path, NULL); worktree->id = xstrdup(id); - add_head_info(worktree); + if (!skip_reading_head) + add_head_info(worktree); done: strbuf_release(&path); @@ -118,7 +121,7 @@ static void mark_current_worktree(struct worktree **worktrees) free(git_dir); } -struct worktree **get_worktrees(void) +static struct worktree **get_worktrees_internal(int skip_reading_head) { struct worktree **list = NULL; struct strbuf path = STRBUF_INIT; @@ -128,7 +131,7 @@ struct worktree **get_worktrees(void) ALLOC_ARRAY(list, alloc); - list[counter++] = get_main_worktree(); + list[counter++] = get_main_worktree(skip_reading_head); strbuf_addf(&path, "%s/worktrees", get_git_common_dir()); dir = opendir(path.buf); @@ -137,7 +140,7 @@ struct worktree **get_worktrees(void) while ((d = readdir_skip_dot_and_dotdot(dir)) != NULL) { struct worktree *linked = NULL; - if ((linked = get_linked_worktree(d->d_name))) { + if ((linked = get_linked_worktree(d->d_name, skip_reading_head))) { ALLOC_GROW(list, counter + 1, alloc); list[counter++] = linked; } @@ -151,6 +154,11 @@ struct worktree **get_worktrees(void) return list; } +struct worktree **get_worktrees(void) +{ + return get_worktrees_internal(0); +} + const char *get_worktree_git_dir(const struct worktree *wt) { if (!wt) @@ -591,7 +599,7 @@ static void repair_noop(int iserr UNUSED, void repair_worktrees(worktree_repair_fn fn, void *cb_data) { - struct worktree **worktrees = get_worktrees(); + struct worktree **worktrees = get_worktrees_internal(1); struct worktree **wt = worktrees + 1; /* +1 skips main worktree */ if (!fn)