From patchwork Fri May 24 10:14:30 2024 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Patrick Steinhardt X-Patchwork-Id: 13673018 Received: from fout4-smtp.messagingengine.com (fout4-smtp.messagingengine.com [103.168.172.147]) (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 110B485659 for ; Fri, 24 May 2024 10:14:34 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=103.168.172.147 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1716545675; cv=none; b=LUo+SX9EBAVHeXMdy0PZaD8WYDcuQ8m9YLMkbgFWgGpIkn91dsunVhsqgLnhiU/6BqK/lc6hA0ZyjqWrgdoTknNO+WJP/MMmvQvbk5nS22QQvkFS094CMP13MPvZgIF3j3+OoRy7LD+P5muorzUnkeZY7hjrGegEU7c2sDuw0+g= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1716545675; c=relaxed/simple; bh=XqbeWE0+0wUg15Sw5OY0kCqP3dd56ZH0ciLt2GQF0Vc=; h=Date:From:To:Cc:Subject:Message-ID:References:MIME-Version: Content-Type:Content-Disposition:In-Reply-To; b=UNwUJS8jG+uPBK6QUfxSxnbvRKVS9nTGoEpu5uiPthUoK9WUaZGsjds9KnuYIsBh5ON4vLPLH5XXoZxUm5zbv04gISUWN89vQI/0WRq58sv+sEgn9edPnIAhNtbh42g24lN6kqtTwbFUFpFVJAMUWcR64+01sBC7duQoWuwoheI= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=reject dis=none) header.from=pks.im; spf=pass smtp.mailfrom=pks.im; dkim=pass (2048-bit key) header.d=pks.im header.i=@pks.im header.b=Kb49RSgP; dkim=pass (2048-bit key) header.d=messagingengine.com header.i=@messagingengine.com header.b=DvNFtp2Y; arc=none smtp.client-ip=103.168.172.147 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=reject 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="Kb49RSgP"; dkim=pass (2048-bit key) header.d=messagingengine.com header.i=@messagingengine.com header.b="DvNFtp2Y" Received: from compute6.internal (compute6.nyi.internal [10.202.2.47]) by mailfout.nyi.internal (Postfix) with ESMTP id 594D113800DA; Fri, 24 May 2024 06:14:33 -0400 (EDT) Received: from mailfrontend1 ([10.202.2.162]) by compute6.internal (MEProxy); Fri, 24 May 2024 06:14:33 -0400 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=fm1; t=1716545673; x=1716632073; bh=Y5hZK2vs3r qw+cu0Fn0d2S8saugV6bBkGK40Ait2+dg=; b=Kb49RSgPcPdXQyog1ZfYkmCJOW +qjentYhQf0/B6QrPZbWvQECBBH+IyRzHl7hquqHZKY6AyE2+SaRTH4WXfaT+FY3 GNwXALJHozo2C46U5mvem4+K90XGjUgl8HZROZemUQSiHSy70HlU56YaxqjuzEDI 0tuMCWxtc1BOVBp31YOMNYu7ecmn3mOmNbJG2ayMrVqFgfQI5Yvy835lTZXn5c3H SHhTUPQX857MDLYSvMTcxFcC45Z8FuoMBRVO3x6G7gAyhA+DbgZIc5rmwNPR+GiF TOD56YUh1PfkH4npRdNar7L8fVb6DH9sARFXqm0CQmiZNGnY8B6w7oNwbc8A== 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= fm1; t=1716545673; x=1716632073; bh=Y5hZK2vs3rqw+cu0Fn0d2S8saugV 6bBkGK40Ait2+dg=; b=DvNFtp2YiA746AdBwTlYEJFmNOEUlUvsa1Sif12zA9dN nnyyh9xDNC+ftJmxrZWbRSZ4X/q4892rN5kLr98DV1arMiUigB2Ll5gXhWlgBNXH IXYiS0Egkypk9s7pGiOR1Fy88pVLYYurgX3rJkhZXUN1/w+HsngkSirUTkwUZrWY e8fPTIeqHfr0c4cHZJrXNP8zFtYoFFd2yLX2ozR5S9ds4uGZpYoijWqFmpAq0FIO kv8kobFlXjqsuioKgZW4O0UEg2yCIce8FQYn9c43M0MoS4V2macUwxpLhtOkJeLY zk1KdzwcyrUrz2JnW/NfS0jfYuRLyWDImOb46OgCbg== X-ME-Sender: X-ME-Received: X-ME-Proxy-Cause: gggruggvucftvghtrhhoucdtuddrgedvledrvdeikedgvdefucetufdoteggodetrfdotf fvucfrrhhofhhilhgvmecuhfgrshhtofgrihhlpdfqfgfvpdfurfetoffkrfgpnffqhgen uceurghilhhouhhtmecufedttdenucesvcftvggtihhpihgvnhhtshculddquddttddmne cujfgurhepfffhvfevuffkfhggtggujgesghdtreertddtvdenucfhrhhomheprfgrthhr ihgtkhcuufhtvghinhhhrghrughtuceophhssehpkhhsrdhimheqnecuggftrfgrthhtvg hrnhepueektdevtdffveeljeetgfehheeigeekleduvdeffeeghefgledttdehjeelffet necuvehluhhsthgvrhfuihiivgeptdenucfrrghrrghmpehmrghilhhfrhhomhepphhsse hpkhhsrdhimh X-ME-Proxy: Feedback-ID: i197146af:Fastmail Received: by mail.messagingengine.com (Postfix) with ESMTPA; Fri, 24 May 2024 06:14:32 -0400 (EDT) Received: by localhost (OpenSMTPD) with ESMTPSA id 1cd63e2f (TLSv1.3:TLS_AES_256_GCM_SHA384:256:NO); Fri, 24 May 2024 10:14:29 +0000 (UTC) Date: Fri, 24 May 2024 12:14:30 +0200 From: Patrick Steinhardt To: git@vger.kernel.org Cc: Eric Sunshine , Junio C Hamano Subject: [PATCH v2 1/9] setup: unset ref storage when reinitializing repository version Message-ID: <8b11127daf4c1d06eed4a0c83dd3dc981ffdc728.1716545235.git.ps@pks.im> 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 reinitializing a repository's version we may end up unsetting the hash algorithm when it matches the default hash algorithm. If we didn't do that then the previously configured value might remain intact. While the same issue exists for the ref storage extension, we don't do this here. This has been fine for most of the part because it is not supported to re-initialize a repository with a different ref storage format anyway. We're about to introduce a new command to migrate ref storages though, so this is about to become an issue there. Prepare for this and unset the ref storage format when reinitializing a repoistory with the "files" format. Signed-off-by: Patrick Steinhardt --- setup.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/setup.c b/setup.c index 7975230ffb..8c84ec9d4b 100644 --- a/setup.c +++ b/setup.c @@ -2028,6 +2028,8 @@ void initialize_repository_version(int hash_algo, if (ref_storage_format != REF_STORAGE_FORMAT_FILES) git_config_set("extensions.refstorage", ref_storage_format_to_name(ref_storage_format)); + else if (reinit) + git_config_set_gently("extensions.refstorage", NULL); } static int is_reinit(void) From patchwork Fri May 24 10:14:34 2024 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Patrick Steinhardt X-Patchwork-Id: 13673019 Received: from fhigh2-smtp.messagingengine.com (fhigh2-smtp.messagingengine.com [103.168.172.153]) (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 897BD2B9BE for ; Fri, 24 May 2024 10:14:39 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=103.168.172.153 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1716545681; cv=none; b=oaq5CJKJeUo66+3raVll38Ennl5LI2itdH8YOewgsV32gDuGuWV/GsMqC+rdfQP0f4OX1wzPvZqGVuRAJlHkLrbpVwVEcqTqydlu8OykYMAqrilcL6P2/6oapwKvl5Mm1g1DDBKid4pU6ZxfVYTvBtBk40/Ryz6P09dqtqVmGWU= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1716545681; c=relaxed/simple; bh=sCstjH5bhG2vuUAPy1Ux4/i1gmNPGR2iqMQ4CQs+4YM=; h=Date:From:To:Cc:Subject:Message-ID:References:MIME-Version: Content-Type:Content-Disposition:In-Reply-To; b=G7uYjugIRpkKku7SbGTRewEPiVArYp63zDwuyNIhg/DD+XWVdycJi3XFKvJF5nnuywABw6kVihiYAgOjaU5YVDa8VWhFRNM42vGERJDq2UQy5sX9hxxTYMd7A/GIUQDU404kfytyRlvNsqLrIwo/vbNGTqCVzhDOW/u3njfFYLM= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=reject dis=none) header.from=pks.im; spf=pass smtp.mailfrom=pks.im; dkim=pass (2048-bit key) header.d=pks.im header.i=@pks.im header.b=dt2B2oCA; dkim=pass (2048-bit key) header.d=messagingengine.com header.i=@messagingengine.com header.b=QDN2QEOT; arc=none smtp.client-ip=103.168.172.153 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=reject 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="dt2B2oCA"; dkim=pass (2048-bit key) header.d=messagingengine.com header.i=@messagingengine.com header.b="QDN2QEOT" Received: from compute6.internal (compute6.nyi.internal [10.202.2.47]) by mailfhigh.nyi.internal (Postfix) with ESMTP id 99AAD114012B; Fri, 24 May 2024 06:14:38 -0400 (EDT) Received: from mailfrontend1 ([10.202.2.162]) by compute6.internal (MEProxy); Fri, 24 May 2024 06:14:38 -0400 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=fm1; t=1716545678; x=1716632078; bh=DSI2uEoRqK 21j+mR6gAyV2zejo43W3AiVpunrkwMEbQ=; b=dt2B2oCAFrzkqRkxLdWA2Ke+nn Uo4GA4k8rY7/QrWSL3hw7+aMu1CaO37JiMYcLQNWDSSEFQF00Bka2CYcxjRTp2e3 qAhGsy9JPyFgps1iYlMENjtvroKpnSWh1NbjWsT7olkr7Sz/Kd+UH7EklZdaw8dH NRD/wBYIMM8TtN0gkFhqINRsE298+MmflSv7DYIqe99kDJlW5q/9CvQjUrIHKq71 k9MaEzz0nBBlIIch9OdVgftieQz51o8jWZhwAWw7M8yEdBOQNXSbF7Ig8bHhVJEe jSWUBq5E8LrByKhjPqEbtFMlW5RlVripZy+v1ZhN71/+ddZroQ65BPFgL7tg== 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= fm1; t=1716545678; x=1716632078; bh=DSI2uEoRqK21j+mR6gAyV2zejo43 W3AiVpunrkwMEbQ=; b=QDN2QEOTFgnGGLFZXe2OywMjarto66SGmLuO2PbqaxcA l7DvyGvjqK+h8tfMO0mnVB02ce5S8Wjp6VFX1oPv1nSJd0/J8g3uiV8ekCp3d7qN JoOIRAeNZ7DXdm0ZESWsPHHZSS58JBHHPlo6fJoFuWdsPQCSf58GT13HY1jSEw40 7pU/mspyoCoSBjboKHQqaNkNSFU97WfZbrfm+npbOoWkXBaRo4vZxnIrpTzMW69v 3ESfsVBNViXKYxsJRPTjnnc3+D292Iqj8fZuWffCj/DRcQbL1WPycSoOvPagJdh5 imkNEDNE70bynI3vpDBM/RPqaHnjgMUTqWtunIVJ8g== X-ME-Sender: X-ME-Received: X-ME-Proxy-Cause: gggruggvucftvghtrhhoucdtuddrgedvledrvdeikedgvdefucetufdoteggodetrfdotf fvucfrrhhofhhilhgvmecuhfgrshhtofgrihhlpdfqfgfvpdfurfetoffkrfgpnffqhgen uceurghilhhouhhtmecufedttdenucesvcftvggtihhpihgvnhhtshculddquddttddmne cujfgurhepfffhvfevuffkfhggtggujgesghdtreertddtvdenucfhrhhomheprfgrthhr ihgtkhcuufhtvghinhhhrghrughtuceophhssehpkhhsrdhimheqnecuggftrfgrthhtvg hrnhepueektdevtdffveeljeetgfehheeigeekleduvdeffeeghefgledttdehjeelffet necuvehluhhsthgvrhfuihiivgepudenucfrrghrrghmpehmrghilhhfrhhomhepphhsse hpkhhsrdhimh X-ME-Proxy: Feedback-ID: i197146af:Fastmail Received: by mail.messagingengine.com (Postfix) with ESMTPA; Fri, 24 May 2024 06:14:37 -0400 (EDT) Received: by localhost (OpenSMTPD) with ESMTPSA id 7835f357 (TLSv1.3:TLS_AES_256_GCM_SHA384:256:NO); Fri, 24 May 2024 10:14:34 +0000 (UTC) Date: Fri, 24 May 2024 12:14:34 +0200 From: Patrick Steinhardt To: git@vger.kernel.org Cc: Eric Sunshine , Junio C Hamano Subject: [PATCH v2 2/9] refs: convert ref storage format to an enum Message-ID: <25f740f395b469ce410fc708ed90bf4e2516ec69.1716545235.git.ps@pks.im> 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: The ref storage format is tracked as a simple unsigned integer, which makes it harder than necessary to discover what that integer actually is or where its values are defined. Convert the ref storage format to instead be an enum. Signed-off-by: Patrick Steinhardt --- builtin/clone.c | 2 +- builtin/init-db.c | 2 +- refs.c | 7 ++++--- refs.h | 10 ++++++++-- repository.c | 3 ++- repository.h | 10 ++++------ setup.c | 8 ++++---- setup.h | 9 +++++---- 8 files changed, 29 insertions(+), 22 deletions(-) diff --git a/builtin/clone.c b/builtin/clone.c index 1e07524c53..e808e02017 100644 --- a/builtin/clone.c +++ b/builtin/clone.c @@ -970,7 +970,7 @@ int cmd_clone(int argc, const char **argv, const char *prefix) int submodule_progress; int filter_submodules = 0; int hash_algo; - unsigned int ref_storage_format = REF_STORAGE_FORMAT_UNKNOWN; + enum ref_storage_format ref_storage_format = REF_STORAGE_FORMAT_UNKNOWN; const int do_not_override_repo_unix_permissions = -1; const char *template_dir; char *template_dir_dup = NULL; diff --git a/builtin/init-db.c b/builtin/init-db.c index 0170469b84..582dcf20f8 100644 --- a/builtin/init-db.c +++ b/builtin/init-db.c @@ -81,7 +81,7 @@ int cmd_init_db(int argc, const char **argv, const char *prefix) const char *ref_format = NULL; const char *initial_branch = NULL; int hash_algo = GIT_HASH_UNKNOWN; - unsigned int ref_storage_format = REF_STORAGE_FORMAT_UNKNOWN; + enum ref_storage_format ref_storage_format = REF_STORAGE_FORMAT_UNKNOWN; int init_shared_repository = -1; const struct option init_db_options[] = { OPT_STRING(0, "template", &template_dir, N_("template-directory"), diff --git a/refs.c b/refs.c index 31032588e0..e6db85a165 100644 --- a/refs.c +++ b/refs.c @@ -37,14 +37,15 @@ static const struct ref_storage_be *refs_backends[] = { [REF_STORAGE_FORMAT_REFTABLE] = &refs_be_reftable, }; -static const struct ref_storage_be *find_ref_storage_backend(unsigned int ref_storage_format) +static const struct ref_storage_be *find_ref_storage_backend( + enum ref_storage_format ref_storage_format) { if (ref_storage_format < ARRAY_SIZE(refs_backends)) return refs_backends[ref_storage_format]; return NULL; } -unsigned int ref_storage_format_by_name(const char *name) +enum ref_storage_format ref_storage_format_by_name(const char *name) { for (unsigned int i = 0; i < ARRAY_SIZE(refs_backends); i++) if (refs_backends[i] && !strcmp(refs_backends[i]->name, name)) @@ -52,7 +53,7 @@ unsigned int ref_storage_format_by_name(const char *name) return REF_STORAGE_FORMAT_UNKNOWN; } -const char *ref_storage_format_to_name(unsigned int ref_storage_format) +const char *ref_storage_format_to_name(enum ref_storage_format ref_storage_format) { const struct ref_storage_be *be = find_ref_storage_backend(ref_storage_format); if (!be) diff --git a/refs.h b/refs.h index fe7f0db35e..a7afa9bede 100644 --- a/refs.h +++ b/refs.h @@ -11,8 +11,14 @@ struct string_list; struct string_list_item; struct worktree; -unsigned int ref_storage_format_by_name(const char *name); -const char *ref_storage_format_to_name(unsigned int ref_storage_format); +enum ref_storage_format { + REF_STORAGE_FORMAT_UNKNOWN, + REF_STORAGE_FORMAT_FILES, + REF_STORAGE_FORMAT_REFTABLE, +}; + +enum ref_storage_format ref_storage_format_by_name(const char *name); +const char *ref_storage_format_to_name(enum ref_storage_format ref_storage_format); /* * Resolve a reference, recursively following symbolic refererences. diff --git a/repository.c b/repository.c index d29b0304fb..166863f852 100644 --- a/repository.c +++ b/repository.c @@ -124,7 +124,8 @@ void repo_set_compat_hash_algo(struct repository *repo, int algo) repo_read_loose_object_map(repo); } -void repo_set_ref_storage_format(struct repository *repo, unsigned int format) +void repo_set_ref_storage_format(struct repository *repo, + enum ref_storage_format format) { repo->ref_storage_format = format; } diff --git a/repository.h b/repository.h index 4bd8969005..a35cd77c35 100644 --- a/repository.h +++ b/repository.h @@ -1,6 +1,7 @@ #ifndef REPOSITORY_H #define REPOSITORY_H +#include "refs.h" #include "strmap.h" struct config_set; @@ -26,10 +27,6 @@ enum fetch_negotiation_setting { FETCH_NEGOTIATION_NOOP, }; -#define REF_STORAGE_FORMAT_UNKNOWN 0 -#define REF_STORAGE_FORMAT_FILES 1 -#define REF_STORAGE_FORMAT_REFTABLE 2 - struct repo_settings { int initialized; @@ -181,7 +178,7 @@ struct repository { const struct git_hash_algo *compat_hash_algo; /* Repository's reference storage format, as serialized on disk. */ - unsigned int ref_storage_format; + enum ref_storage_format ref_storage_format; /* A unique-id for tracing purposes. */ int trace2_repo_id; @@ -220,7 +217,8 @@ void repo_set_gitdir(struct repository *repo, const char *root, void repo_set_worktree(struct repository *repo, const char *path); void repo_set_hash_algo(struct repository *repo, int algo); void repo_set_compat_hash_algo(struct repository *repo, int compat_algo); -void repo_set_ref_storage_format(struct repository *repo, unsigned int format); +void repo_set_ref_storage_format(struct repository *repo, + enum ref_storage_format format); void initialize_repository(struct repository *repo); RESULT_MUST_BE_USED int repo_init(struct repository *r, const char *gitdir, const char *worktree); diff --git a/setup.c b/setup.c index 8c84ec9d4b..b49ee3e95f 100644 --- a/setup.c +++ b/setup.c @@ -1997,7 +1997,7 @@ static int needs_work_tree_config(const char *git_dir, const char *work_tree) } void initialize_repository_version(int hash_algo, - unsigned int ref_storage_format, + enum ref_storage_format ref_storage_format, int reinit) { char repo_version_string[10]; @@ -2044,7 +2044,7 @@ static int is_reinit(void) return ret; } -void create_reference_database(unsigned int ref_storage_format, +void create_reference_database(enum ref_storage_format ref_storage_format, const char *initial_branch, int quiet) { struct strbuf err = STRBUF_INIT; @@ -2243,7 +2243,7 @@ static void validate_hash_algorithm(struct repository_format *repo_fmt, int hash } static void validate_ref_storage_format(struct repository_format *repo_fmt, - unsigned int format) + enum ref_storage_format format) { const char *name = getenv("GIT_DEFAULT_REF_FORMAT"); @@ -2263,7 +2263,7 @@ static void validate_ref_storage_format(struct repository_format *repo_fmt, int init_db(const char *git_dir, const char *real_git_dir, const char *template_dir, int hash, - unsigned int ref_storage_format, + enum ref_storage_format ref_storage_format, const char *initial_branch, int init_shared_repository, unsigned int flags) { diff --git a/setup.h b/setup.h index b3fd3bf45a..cd8dbc2497 100644 --- a/setup.h +++ b/setup.h @@ -1,6 +1,7 @@ #ifndef SETUP_H #define SETUP_H +#include "refs.h" #include "string-list.h" int is_inside_git_dir(void); @@ -128,7 +129,7 @@ struct repository_format { int is_bare; int hash_algo; int compat_hash_algo; - unsigned int ref_storage_format; + enum ref_storage_format ref_storage_format; int sparse_index; char *work_tree; struct string_list unknown_extensions; @@ -192,13 +193,13 @@ const char *get_template_dir(const char *option_template); int init_db(const char *git_dir, const char *real_git_dir, const char *template_dir, int hash_algo, - unsigned int ref_storage_format, + enum ref_storage_format ref_storage_format, const char *initial_branch, int init_shared_repository, unsigned int flags); void initialize_repository_version(int hash_algo, - unsigned int ref_storage_format, + enum ref_storage_format ref_storage_format, int reinit); -void create_reference_database(unsigned int ref_storage_format, +void create_reference_database(enum ref_storage_format ref_storage_format, const char *initial_branch, int quiet); /* From patchwork Fri May 24 10:14:39 2024 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Patrick Steinhardt X-Patchwork-Id: 13673020 Received: from fhigh2-smtp.messagingengine.com (fhigh2-smtp.messagingengine.com [103.168.172.153]) (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 B511A85931 for ; Fri, 24 May 2024 10:14:43 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=103.168.172.153 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1716545685; cv=none; b=b3mxKq4AfZEAeLGAie9DgEbyBLS1D14xyVzAn/5uWOOoG0vSL8bFk5784FB5mUAtd3Iy63FUzLUiEJbBFPPxkygTd5PCr0tWIaDxzadMUZp8LT5iI0dZszb9b5DVpERSQhvImNgiXHKiyrmaxK2jU3oOZDqQ5k2rVbV5093tHqY= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1716545685; c=relaxed/simple; bh=tcvWuHriSlbhQ7lFE0/gpMcGo3S75njmnfkKqV8Y7pE=; h=Date:From:To:Cc:Subject:Message-ID:References:MIME-Version: Content-Type:Content-Disposition:In-Reply-To; b=p1h+zyBcZmqClWi8T6iUbhZWVVkNHsKV0ZlIJ9b0Jf1jQFWJGblrcswo/sR+CaEbYJQJKdviUv0kqfX6FomMkINNimxdWJOlnvoebFF9E9+Ci1HwiayW2YXgIOGTn1CFloyfWfh7nh6j4FzQA2Lawj8qQXGUsOB7c2Eat6DlCVI= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=reject dis=none) header.from=pks.im; spf=pass smtp.mailfrom=pks.im; dkim=pass (2048-bit key) header.d=pks.im header.i=@pks.im header.b=JESUXUS9; dkim=pass (2048-bit key) header.d=messagingengine.com header.i=@messagingengine.com header.b=QinNx/xw; arc=none smtp.client-ip=103.168.172.153 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=reject 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="JESUXUS9"; dkim=pass (2048-bit key) header.d=messagingengine.com header.i=@messagingengine.com header.b="QinNx/xw" Received: from compute4.internal (compute4.nyi.internal [10.202.2.44]) by mailfhigh.nyi.internal (Postfix) with ESMTP id D6FE5114012B; Fri, 24 May 2024 06:14:42 -0400 (EDT) Received: from mailfrontend1 ([10.202.2.162]) by compute4.internal (MEProxy); Fri, 24 May 2024 06:14:42 -0400 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=fm1; t=1716545682; x=1716632082; bh=LrayIHCNeI +Amd4et1/E6CHPKSfCB5Z/nG49Rl2Kt/s=; b=JESUXUS9u/s44Q9Ux3hvnoQ9zx 9ib+QZOaTh3pz1meaFKXIxgIaC+MMETi6TXx0IF0AE38r4t+BuCFSnKzE8aQ6P4x l36NO+7bI6YS29ybANx/RB3eHPJp03GjFHxnGEAKHnmrnMvbVSPiLEae79vGU3eb a5kddXaYkmcrVcHcZAL0/ZcHUWhNia1X03FwujuUXa/S4z2SMdAxWXkvnLgciLDz 5eO2T8oigFaIXfVkXe800Ji6AV0ilNUp6U2bzDZ1LP2aop0PYhSHUavDguKfQrFP y38YBZ9pi1t/MzE1imCshc+i1pDfjhSgwnfsr/Y54CZfY/R63ZvO822B3fxA== 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= fm1; t=1716545682; x=1716632082; bh=LrayIHCNeI+Amd4et1/E6CHPKSfC B5Z/nG49Rl2Kt/s=; b=QinNx/xwtWA39Fxh7vqAJrWDUJ9SPOWPa8U2BavDBdKm w4VnX44QCO9m6RwKqCSbEuG5E0BmTb36ByYoHX48LdRHMl/R0sA23j5NCGm3/UiQ m/lZrJOPONaWHvgFaTJDpLVHz4ULFiXB74iH1nAAXI+mfbVPdzSfTCT79DqsW++y hw+q2oWc87W0pLHJ7GwtoR/lpt91o8SKRsMeTt77CXdRbXipUO7hwICOOjIU4/Yw BVUZLdT0AAbVkk5ngQ7GcgFOhgmpdRrQACm2nadMnxs/catdNMydfsyIfyiRFLgt MDeDGBJ0AOrVOTMbOv39ZbZmY6BmAGnoZg0rrYrrVw== X-ME-Sender: X-ME-Received: X-ME-Proxy-Cause: gggruggvucftvghtrhhoucdtuddrgedvledrvdeikedgvdefucetufdoteggodetrfdotf fvucfrrhhofhhilhgvmecuhfgrshhtofgrihhlpdfqfgfvpdfurfetoffkrfgpnffqhgen uceurghilhhouhhtmecufedttdenucesvcftvggtihhpihgvnhhtshculddquddttddmne cujfgurhepfffhvfevuffkfhggtggujgesghdtreertddtvdenucfhrhhomheprfgrthhr ihgtkhcuufhtvghinhhhrghrughtuceophhssehpkhhsrdhimheqnecuggftrfgrthhtvg hrnhepueektdevtdffveeljeetgfehheeigeekleduvdeffeeghefgledttdehjeelffet necuvehluhhsthgvrhfuihiivgeptdenucfrrghrrghmpehmrghilhhfrhhomhepphhsse hpkhhsrdhimh X-ME-Proxy: Feedback-ID: i197146af:Fastmail Received: by mail.messagingengine.com (Postfix) with ESMTPA; Fri, 24 May 2024 06:14:41 -0400 (EDT) Received: by localhost (OpenSMTPD) with ESMTPSA id 57d89369 (TLSv1.3:TLS_AES_256_GCM_SHA384:256:NO); Fri, 24 May 2024 10:14:39 +0000 (UTC) Date: Fri, 24 May 2024 12:14:39 +0200 From: Patrick Steinhardt To: git@vger.kernel.org Cc: Eric Sunshine , Junio C Hamano Subject: [PATCH v2 3/9] refs: pass storage format to `ref_store_init()` explicitly Message-ID: <6e7b9764f6290fb8ffe5941e33b72081e1c9581f.1716545235.git.ps@pks.im> 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: We're about to introduce logic to migrate refs from one storage format to another one. This will require us to initialize a ref store with a different format than the one used by the passed-in repository. Prepare for this by accepting the desired ref storage format as parameter. Signed-off-by: Patrick Steinhardt --- refs.c | 17 ++++++++++------- 1 file changed, 10 insertions(+), 7 deletions(-) diff --git a/refs.c b/refs.c index e6db85a165..7c3f4df457 100644 --- a/refs.c +++ b/refs.c @@ -1894,13 +1894,14 @@ static struct ref_store *lookup_ref_store_map(struct strmap *map, * gitdir. */ static struct ref_store *ref_store_init(struct repository *repo, + enum ref_storage_format format, const char *gitdir, unsigned int flags) { const struct ref_storage_be *be; struct ref_store *refs; - be = find_ref_storage_backend(repo->ref_storage_format); + be = find_ref_storage_backend(format); if (!be) BUG("reference backend is unknown"); @@ -1922,7 +1923,8 @@ struct ref_store *get_main_ref_store(struct repository *r) if (!r->gitdir) BUG("attempting to get main_ref_store outside of repository"); - r->refs_private = ref_store_init(r, r->gitdir, REF_STORE_ALL_CAPS); + r->refs_private = ref_store_init(r, r->ref_storage_format, + r->gitdir, REF_STORE_ALL_CAPS); r->refs_private = maybe_debug_wrap_ref_store(r->gitdir, r->refs_private); return r->refs_private; } @@ -1982,7 +1984,8 @@ struct ref_store *repo_get_submodule_ref_store(struct repository *repo, free(subrepo); goto done; } - refs = ref_store_init(subrepo, submodule_sb.buf, + refs = ref_store_init(subrepo, the_repository->ref_storage_format, + submodule_sb.buf, REF_STORE_READ | REF_STORE_ODB); register_ref_store_map(&repo->submodule_ref_stores, "submodule", refs, submodule); @@ -2011,12 +2014,12 @@ struct ref_store *get_worktree_ref_store(const struct worktree *wt) struct strbuf common_path = STRBUF_INIT; strbuf_git_common_path(&common_path, wt->repo, "worktrees/%s", wt->id); - refs = ref_store_init(wt->repo, common_path.buf, - REF_STORE_ALL_CAPS); + refs = ref_store_init(wt->repo, wt->repo->ref_storage_format, + common_path.buf, REF_STORE_ALL_CAPS); strbuf_release(&common_path); } else { - refs = ref_store_init(wt->repo, wt->repo->commondir, - REF_STORE_ALL_CAPS); + refs = ref_store_init(wt->repo, the_repository->ref_storage_format, + wt->repo->commondir, REF_STORE_ALL_CAPS); } if (refs) From patchwork Fri May 24 10:14:44 2024 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Patrick Steinhardt X-Patchwork-Id: 13673021 Received: from fhigh2-smtp.messagingengine.com (fhigh2-smtp.messagingengine.com [103.168.172.153]) (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 0453984FAF for ; Fri, 24 May 2024 10:14:48 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=103.168.172.153 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1716545690; cv=none; b=Qo4q61GxibQHGqROCN4jte9kQDwet2IgaUY4DXJPmQhwlHMKKJEoxvipwz3TS8mozshfDeCdpXigoJJJoUw2Gswscpx8bZ/QQW8aSGp1xIKb2aSrhTw2D7ZYnIDwrMvCNTY/Xjtb/2OSSBwCrS/+Fi9iZNg1VTASwIGNGX6yeF0= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1716545690; c=relaxed/simple; bh=fXoRGu2pWuopzys3WnPQKe6ZDYDtwaGVLtcPrDn84Yo=; h=Date:From:To:Cc:Subject:Message-ID:References:MIME-Version: Content-Type:Content-Disposition:In-Reply-To; b=lLJ0zQQRygEu0/3Gpf4s3Dj89GKmvW8nKyg6Jc7rO3Lyl/Z6eK+/llIwviGxvLCS1vuHDtZqIa4JswZ+WEcjqX05FzEx778nKw92ayXNswre0Azdmxpsx2Qko8A4PDWjC71qCVy4o5+QgNvUSIfC5oIJIV5IrUTqq444sVP6YF4= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=reject dis=none) header.from=pks.im; spf=pass smtp.mailfrom=pks.im; dkim=pass (2048-bit key) header.d=pks.im header.i=@pks.im header.b=YTNyqZnZ; dkim=pass (2048-bit key) header.d=messagingengine.com header.i=@messagingengine.com header.b=GTjLneHx; arc=none smtp.client-ip=103.168.172.153 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=reject 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="YTNyqZnZ"; dkim=pass (2048-bit key) header.d=messagingengine.com header.i=@messagingengine.com header.b="GTjLneHx" Received: from compute1.internal (compute1.nyi.internal [10.202.2.41]) by mailfhigh.nyi.internal (Postfix) with ESMTP id 24E3B114012B; Fri, 24 May 2024 06:14:48 -0400 (EDT) Received: from mailfrontend1 ([10.202.2.162]) by compute1.internal (MEProxy); Fri, 24 May 2024 06:14:48 -0400 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=fm1; t=1716545688; x=1716632088; bh=NBDJXp7l1/ BoONU/nbQ9pQ0vRRsu1LtaZVn8327stvI=; b=YTNyqZnZVUK2j8nDALVd2SxuYB MuZbbNpaGLj7c7SiRcdJniyLOoMF0izNWy74W4o4x3t6qR4/FCXEEnI6EKQSYrPV Bh+aH5DDwIE3CsAqvnHNJEuaDdmdMe3d1s6saH0OxVlHV4THoNHqI05K9oHlEOpp Rh/m/jRmw9SzteV6+jy0hQHheMtphWIMWal9NmTViQXt0czRTOPQgPCTGe739kQs lt23ucDar1NRemkgTx9eIhDTvQ48pAAKfzzA9siGBNYEU8EqAc51NsOZdfCz3yr3 TpNBJDRL0crmkMRKx1Qcgk14EXqpoPCdutdWuPUMRTtDQz2ajgl/DYI6qgkA== 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= fm1; t=1716545688; x=1716632088; bh=NBDJXp7l1/BoONU/nbQ9pQ0vRRsu 1LtaZVn8327stvI=; b=GTjLneHxEteJVB1pgjk4SHXyWYxru1z4oM+3lEgR+gJv ud+4vmESt3FygjQ0k6RqUoUbA2bSVLxnfrUNISpBn4IiREnr3w85aQW7Upc1dhPf 82cmj8pH6FuyAzdyYghyHx3Jk2KKJ0tSFBbg4nSwohEeIjy/eBZUJiQRdWd7MIax e3ZDbi3B2EqHFWB/wqK/DPWOhMRFgAJeZI4bZ1sPAtpq2iGo6ZleGzFhn3/NrSr5 uLmb7Ld3oaR6f+y1yvl7JXVQNmEjzOtwIgC3R/ApbDi3iTXEWtq6ztbAt9gnutvh FBPNSzWnvgLBcEmq/Xt1yZHCpGHoX6FmGurYdDjvXA== X-ME-Sender: X-ME-Received: X-ME-Proxy-Cause: gggruggvucftvghtrhhoucdtuddrgedvledrvdeikedgvdefucetufdoteggodetrfdotf fvucfrrhhofhhilhgvmecuhfgrshhtofgrihhlpdfqfgfvpdfurfetoffkrfgpnffqhgen uceurghilhhouhhtmecufedttdenucesvcftvggtihhpihgvnhhtshculddquddttddmne cujfgurhepfffhvfevuffkfhggtggujgesghdtreertddtvdenucfhrhhomheprfgrthhr ihgtkhcuufhtvghinhhhrghrughtuceophhssehpkhhsrdhimheqnecuggftrfgrthhtvg hrnhepueektdevtdffveeljeetgfehheeigeekleduvdeffeeghefgledttdehjeelffet necuvehluhhsthgvrhfuihiivgeptdenucfrrghrrghmpehmrghilhhfrhhomhepphhsse hpkhhsrdhimh X-ME-Proxy: Feedback-ID: i197146af:Fastmail Received: by mail.messagingengine.com (Postfix) with ESMTPA; Fri, 24 May 2024 06:14:47 -0400 (EDT) Received: by localhost (OpenSMTPD) with ESMTPSA id cc81b625 (TLSv1.3:TLS_AES_256_GCM_SHA384:256:NO); Fri, 24 May 2024 10:14:43 +0000 (UTC) Date: Fri, 24 May 2024 12:14:44 +0200 From: Patrick Steinhardt To: git@vger.kernel.org Cc: Eric Sunshine , Junio C Hamano Subject: [PATCH v2 4/9] refs: allow to skip creation of reflog entries Message-ID: <03f4ac6ee7143f6b38e1eb95fb139c8e454136f5.1716545235.git.ps@pks.im> 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: The ref backends do not have any way to disable the creation of reflog entries. This will be required for upcoming ref format migration logic so that we do not create any entries that didn't exist in the original ref database. Provide a new `REF_SKIP_CREATE_REFLOG` flag that allows the caller to disable reflog entry creation. Signed-off-by: Patrick Steinhardt --- refs.c | 6 ++++++ refs.h | 8 +++++++- refs/files-backend.c | 4 ++++ refs/reftable-backend.c | 3 ++- t/helper/test-ref-store.c | 1 + 5 files changed, 20 insertions(+), 2 deletions(-) diff --git a/refs.c b/refs.c index 7c3f4df457..66e9585767 100644 --- a/refs.c +++ b/refs.c @@ -1194,6 +1194,12 @@ int ref_transaction_update(struct ref_transaction *transaction, { assert(err); + if ((flags & REF_FORCE_CREATE_REFLOG) && + (flags & REF_SKIP_CREATE_REFLOG)) { + strbuf_addstr(err, _("refusing to force and skip creation of reflog")); + return -1; + } + if (!(flags & REF_SKIP_REFNAME_VERIFICATION) && ((new_oid && !is_null_oid(new_oid)) ? check_refname_format(refname, REFNAME_ALLOW_ONELEVEL) : diff --git a/refs.h b/refs.h index a7afa9bede..50a2b3ab09 100644 --- a/refs.h +++ b/refs.h @@ -659,13 +659,19 @@ struct ref_transaction *ref_store_transaction_begin(struct ref_store *refs, */ #define REF_SKIP_REFNAME_VERIFICATION (1 << 11) +/* + * Skip creation of a reflog entry, even if it would have otherwise been + * created. + */ +#define REF_SKIP_CREATE_REFLOG (1 << 12) + /* * Bitmask of all of the flags that are allowed to be passed in to * ref_transaction_update() and friends: */ #define REF_TRANSACTION_UPDATE_ALLOWED_FLAGS \ (REF_NO_DEREF | REF_FORCE_CREATE_REFLOG | REF_SKIP_OID_VERIFICATION | \ - REF_SKIP_REFNAME_VERIFICATION) + REF_SKIP_REFNAME_VERIFICATION | REF_SKIP_CREATE_REFLOG) /* * Add a reference update to transaction. `new_oid` is the value that diff --git a/refs/files-backend.c b/refs/files-backend.c index 73380d7e99..bd0d63bcba 100644 --- a/refs/files-backend.c +++ b/refs/files-backend.c @@ -1750,6 +1750,9 @@ static int files_log_ref_write(struct files_ref_store *refs, { int logfd, result; + if (flags & REF_SKIP_CREATE_REFLOG) + return 0; + if (log_all_ref_updates == LOG_REFS_UNSET) log_all_ref_updates = is_bare_repository() ? LOG_REFS_NONE : LOG_REFS_NORMAL; @@ -2251,6 +2254,7 @@ static int split_head_update(struct ref_update *update, struct ref_update *new_update; if ((update->flags & REF_LOG_ONLY) || + (update->flags & REF_SKIP_CREATE_REFLOG) || (update->flags & REF_IS_PRUNING) || (update->flags & REF_UPDATE_VIA_HEAD)) return 0; diff --git a/refs/reftable-backend.c b/refs/reftable-backend.c index f6edfdf5b3..bffed9257f 100644 --- a/refs/reftable-backend.c +++ b/refs/reftable-backend.c @@ -1103,7 +1103,8 @@ static int write_transaction_table(struct reftable_writer *writer, void *cb_data if (ret) goto done; - } else if (u->flags & REF_HAVE_NEW && + } else if (!(u->flags & REF_SKIP_CREATE_REFLOG) && + (u->flags & REF_HAVE_NEW) && (u->flags & REF_FORCE_CREATE_REFLOG || should_write_log(&arg->refs->base, u->refname))) { struct reftable_log_record *log; diff --git a/t/helper/test-ref-store.c b/t/helper/test-ref-store.c index c9efd74c2b..ad24300170 100644 --- a/t/helper/test-ref-store.c +++ b/t/helper/test-ref-store.c @@ -126,6 +126,7 @@ static struct flag_definition transaction_flags[] = { FLAG_DEF(REF_FORCE_CREATE_REFLOG), FLAG_DEF(REF_SKIP_OID_VERIFICATION), FLAG_DEF(REF_SKIP_REFNAME_VERIFICATION), + FLAG_DEF(REF_SKIP_CREATE_REFLOG), { NULL, 0 } }; From patchwork Fri May 24 10:14:49 2024 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Patrick Steinhardt X-Patchwork-Id: 13673022 Received: from fhigh2-smtp.messagingengine.com (fhigh2-smtp.messagingengine.com [103.168.172.153]) (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 327462B9BE for ; Fri, 24 May 2024 10:14:53 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=103.168.172.153 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1716545695; cv=none; b=AETdkyXHEjmuKDPc/FrCWbZbq9/dcBQettfMT4+JNuaOldOm8WrZJpN4/8dSukbSYUiJXflvlQJiHjGMeVBzI/26IuId+L79FxT1h2S1YUXLArvfnwuJ1d4zqYSfmaVIpscouLnFnpYNRuuEmhJbXRAiCWHbsQT8zYTh7Tyd48I= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1716545695; c=relaxed/simple; bh=tDOZyRYvdcJCFh8SyUw1CEzx3n8K+Ts1aOxCPYmhav8=; h=Date:From:To:Cc:Subject:Message-ID:References:MIME-Version: Content-Type:Content-Disposition:In-Reply-To; b=DKkJ8w7CbocWfcqccrawmHdwh2XInwO+6GzYDwi//tF/3yudM1RWKl1pHC+nudsKlxk89CeL8pMzDA3RZOB7t6qzygLfjNH2L2ZXJ3U1R0oVMXPCS9BBtL3pZC3hDB2D9D6m7SEQ7aXgX7Vy2baL5WIXcDW+v0YX3emHR7NlUcQ= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=reject dis=none) header.from=pks.im; spf=pass smtp.mailfrom=pks.im; dkim=pass (2048-bit key) header.d=pks.im header.i=@pks.im header.b=ZT5L6UCU; dkim=pass (2048-bit key) header.d=messagingengine.com header.i=@messagingengine.com header.b=gvnZb22d; arc=none smtp.client-ip=103.168.172.153 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=reject 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="ZT5L6UCU"; dkim=pass (2048-bit key) header.d=messagingengine.com header.i=@messagingengine.com header.b="gvnZb22d" Received: from compute1.internal (compute1.nyi.internal [10.202.2.41]) by mailfhigh.nyi.internal (Postfix) with ESMTP id 4EFE311400AD; Fri, 24 May 2024 06:14:53 -0400 (EDT) Received: from mailfrontend1 ([10.202.2.162]) by compute1.internal (MEProxy); Fri, 24 May 2024 06:14:53 -0400 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=fm1; t=1716545693; x=1716632093; bh=vlonvWyQiC /Iua5t31YFed3cdn/ibG0IclVmQOLlYAg=; b=ZT5L6UCUiIkN2VDdzGpC79Tcfw /LqIZvuDJtD2u2IMPFBWeotWaQCfM51cit+Qe1bZKxMzdI/Xet4i1ONojCOGffAQ PX760H6BhSNbRrkhVUvyQqa1CCIYE723/w3VcZ4nednXI4Vc/1m0cYKktVfVx2Yo LLDvlgIZXAM6mBOo4M+AY5dDmNMe4o/tr4Q8onFPLigTAVB4Oqz8a2oXP/a7/okR WkYNtzUCwnghNtT1KQsjmgPYnvJ4h9mopSuuwmVHkLkqHc+rH26dxyBIKNiRp6a+ UX1kICWLmYucgM2wAcukmcOEsyzXwy3K6LwGo4RKP5Mmev90348WzMwQRuFw== 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= fm1; t=1716545693; x=1716632093; bh=vlonvWyQiC/Iua5t31YFed3cdn/i bG0IclVmQOLlYAg=; b=gvnZb22dlXIqvgEkww+RrWH0vX0oaUO81P7GABjlQ/Sn TsXRpYlFGoqqhyKZJWiOkWP9vvEi7HCX5R2SV0GLLFol+wnN2wqvs0wcIIn441Qk ZvTK2GmeiwuLAMOblaqwB5IF+bjtvNnSM8F+E03Tmdg+qTvrADp3FRl0KDzbtlm2 KG0smnM3702HavvmTsY0BGywfLRTdyUWCpBZF/0teTHZA6Eg7F3mM/HJmoptl7Ea twVtGLQiJwk1hoDajPmgd4QjM5iXnc3rHOCcpcwyv1IRmWeKJsI2q67rjd1ASJzt aJyoC4T8y8mBI/r5fFdSjR1h0UGFAVqnHfI8xrC4Cw== X-ME-Sender: X-ME-Received: X-ME-Proxy-Cause: gggruggvucftvghtrhhoucdtuddrgedvledrvdeikedgvdefucetufdoteggodetrfdotf fvucfrrhhofhhilhgvmecuhfgrshhtofgrihhlpdfqfgfvpdfurfetoffkrfgpnffqhgen uceurghilhhouhhtmecufedttdenucesvcftvggtihhpihgvnhhtshculddquddttddmne cujfgurhepfffhvfevuffkfhggtggujgesghdtreertddtvdenucfhrhhomheprfgrthhr ihgtkhcuufhtvghinhhhrghrughtuceophhssehpkhhsrdhimheqnecuggftrfgrthhtvg hrnhepueektdevtdffveeljeetgfehheeigeekleduvdeffeeghefgledttdehjeelffet necuvehluhhsthgvrhfuihiivgepudenucfrrghrrghmpehmrghilhhfrhhomhepphhsse hpkhhsrdhimh X-ME-Proxy: Feedback-ID: i197146af:Fastmail Received: by mail.messagingengine.com (Postfix) with ESMTPA; Fri, 24 May 2024 06:14:52 -0400 (EDT) Received: by localhost (OpenSMTPD) with ESMTPSA id a3d1f12a (TLSv1.3:TLS_AES_256_GCM_SHA384:256:NO); Fri, 24 May 2024 10:14:48 +0000 (UTC) Date: Fri, 24 May 2024 12:14:49 +0200 From: Patrick Steinhardt To: git@vger.kernel.org Cc: Eric Sunshine , Junio C Hamano Subject: [PATCH v2 5/9] refs/files: refactor `add_pseudoref_and_head_entries()` Message-ID: <71f31fe66ce8eb95fbbb8a646dad571ff57b8a72.1716545235.git.ps@pks.im> 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: The `add_pseudoref_and_head_entries()` function accepts both the ref store as well as a directory name as input. This is unnecessary though as the ref store already uniquely identifies the root directory of the ref store anyway. Furthermore, the function is misnamed now that we have clarified the meaning of pseudorefs as it doesn't add pseudorefs, but root refs. Rename it accordingly. Signed-off-by: Patrick Steinhardt --- refs/files-backend.c | 15 ++++++--------- 1 file changed, 6 insertions(+), 9 deletions(-) diff --git a/refs/files-backend.c b/refs/files-backend.c index bd0d63bcba..b4e5437ffe 100644 --- a/refs/files-backend.c +++ b/refs/files-backend.c @@ -324,16 +324,14 @@ static void loose_fill_ref_dir(struct ref_store *ref_store, } /* - * Add pseudorefs to the ref dir by parsing the directory for any files - * which follow the pseudoref syntax. + * Add root refs to the ref dir by parsing the directory for any files which + * follow the root ref syntax. */ -static void add_pseudoref_and_head_entries(struct ref_store *ref_store, - struct ref_dir *dir, - const char *dirname) +static void add_root_refs(struct files_ref_store *refs, + struct ref_dir *dir) { - struct files_ref_store *refs = - files_downcast(ref_store, REF_STORE_READ, "fill_ref_dir"); struct strbuf path = STRBUF_INIT, refname = STRBUF_INIT; + const char *dirname = refs->loose->root->name; struct dirent *de; size_t dirnamelen; DIR *d; @@ -388,8 +386,7 @@ static struct ref_cache *get_loose_ref_cache(struct files_ref_store *refs, dir = get_ref_dir(refs->loose->root); if (flags & DO_FOR_EACH_INCLUDE_ROOT_REFS) - add_pseudoref_and_head_entries(dir->cache->ref_store, dir, - refs->loose->root->name); + add_root_refs(refs, dir); /* * Add an incomplete entry for "refs/" (to be filled From patchwork Fri May 24 10:14:57 2024 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Patrick Steinhardt X-Patchwork-Id: 13673023 Received: from fhigh2-smtp.messagingengine.com (fhigh2-smtp.messagingengine.com [103.168.172.153]) (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 3491685C44 for ; Fri, 24 May 2024 10:15:01 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=103.168.172.153 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1716545702; cv=none; b=Huo74jxBkD1N2hC0c4SqlU8aZcMI2Fs1fX0ZqmiOJR/MHrJp4NRCxd7gUHhj8x/D4cqbMITkVh1CCLtBm0i3OjtSmGh6pCi9YesBa/MxTJofmeXalWT/QFOI1tKMqDlTPc+nvZmNXpXFVQpOlNHhEgqwHUuPuq0BSBG+s88IwGg= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1716545702; c=relaxed/simple; bh=AexhNgyUFV/yKEosPlpOpfS9slBZ33mqWWY4P5gsF38=; h=Date:From:To:Cc:Subject:Message-ID:References:MIME-Version: Content-Type:Content-Disposition:In-Reply-To; b=Ke7yY9Y2GzWS+chEJRjo12FyjUL+N1Hm4Z3GyN3vC7PUJv3tmzCoMyRx5aH+wzY63FifOOzapD5LJR9AEMUdNnyVS/DEQVkqdpcoQ/8U7vGxpnlZ/MgRoAN8E0KLXDldNef/UK2bwIsi/H4sXyzvSlad8yTnkjfp8lvtQYKisG4= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=reject dis=none) header.from=pks.im; spf=pass smtp.mailfrom=pks.im; dkim=pass (2048-bit key) header.d=pks.im header.i=@pks.im header.b=HvELSang; dkim=pass (2048-bit key) header.d=messagingengine.com header.i=@messagingengine.com header.b=YfyIbzyk; arc=none smtp.client-ip=103.168.172.153 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=reject 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="HvELSang"; dkim=pass (2048-bit key) header.d=messagingengine.com header.i=@messagingengine.com header.b="YfyIbzyk" Received: from compute6.internal (compute6.nyi.internal [10.202.2.47]) by mailfhigh.nyi.internal (Postfix) with ESMTP id 8971611401A9; Fri, 24 May 2024 06:15:00 -0400 (EDT) Received: from mailfrontend1 ([10.202.2.162]) by compute6.internal (MEProxy); Fri, 24 May 2024 06:15:00 -0400 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=fm1; t=1716545700; x=1716632100; bh=G/C+LQby/y axCHv8AEyLoTok+6w1WGr3bbgDUydAgoc=; b=HvELSangXD2V//t4Uu0h8oayMj lsxkycnqxEzPYgCU6tJaQgZ9R7AFz0fvWgTXCoHpApc2j82gn2qTeMASiz/0P1yt rW/7g/oTCxMTOrqN4Ga/D46w76zsgrGIN8MbpE5UPIVHzGGd5Kc9Lja00G9AUA8z BoWuI3/HaGGJAKYQtcPSWN0RKMuaH4IvR+tz0bNqKKyyOKoKQBGWeqBzvYjBvQ5D IuIRcbvKuMH/iwMXD1QLJyazJKynZrwmiQKiYaCs1ceAztZviVPOfJMYFBZRksAs ageAV6cslTP/uWu4ltJwBFeSm+iyRhMh51usfr8Kf5RnQukP776ecMWqmbUg== 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= fm1; t=1716545700; x=1716632100; bh=G/C+LQby/yaxCHv8AEyLoTok+6w1 WGr3bbgDUydAgoc=; b=YfyIbzyk7UntffwWwXWoHPiODCJS2oWak0Nj1FvrA3qd 7C5AF4ecnMV/etV7U0brPqFTJVWoyYwG2nH2duQFFEg6sxL02gZtucnugvBObffz 8+dHpPT7H+0NSs6mJrr01I2AOqOlI1ouvkoimzsrhCwIOrrS5TcV59Db92cnA+Jt 2MnsJ2ZAvcV92MG6Pdgvfs0BKwMV6qnBWlIaqru/eCKHZC2MQ0fQg38nPbSgysTq eGlmGWvl7OJIt18g6spCH75TbhXlC9fMMTYtYSDFioTfdh3hZG1YNJS4sEcw6tmm em/DID4iDTE/X1kj+xwN1V32M8NoYmO0cgAPSQxGyg== X-ME-Sender: X-ME-Received: X-ME-Proxy-Cause: gggruggvucftvghtrhhoucdtuddrgedvledrvdeikedgvdefucetufdoteggodetrfdotf fvucfrrhhofhhilhgvmecuhfgrshhtofgrihhlpdfqfgfvpdfurfetoffkrfgpnffqhgen uceurghilhhouhhtmecufedttdenucesvcftvggtihhpihgvnhhtshculddquddttddmne cujfgurhepfffhvfevuffkfhggtggujgesghdtreertddtvdenucfhrhhomheprfgrthhr ihgtkhcuufhtvghinhhhrghrughtuceophhssehpkhhsrdhimheqnecuggftrfgrthhtvg hrnhepueektdevtdffveeljeetgfehheeigeekleduvdeffeeghefgledttdehjeelffet necuvehluhhsthgvrhfuihiivgepvdenucfrrghrrghmpehmrghilhhfrhhomhepphhsse hpkhhsrdhimh X-ME-Proxy: Feedback-ID: i197146af:Fastmail Received: by mail.messagingengine.com (Postfix) with ESMTPA; Fri, 24 May 2024 06:14:59 -0400 (EDT) Received: by localhost (OpenSMTPD) with ESMTPSA id bb63380e (TLSv1.3:TLS_AES_256_GCM_SHA384:256:NO); Fri, 24 May 2024 10:14:56 +0000 (UTC) Date: Fri, 24 May 2024 12:14:57 +0200 From: Patrick Steinhardt To: git@vger.kernel.org Cc: Eric Sunshine , Junio C Hamano Subject: [PATCH v2 6/9] refs/files: extract function to iterate through root refs Message-ID: <6b696690ca263b1e91de430f0ee740728d90b356.1716545235.git.ps@pks.im> 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: Extract a new function that can be used to iterate through all root refs known to the "files" backend. This will be used in the next commit, where we start to teach ref backends to remove themselves. Signed-off-by: Patrick Steinhardt --- refs/files-backend.c | 49 ++++++++++++++++++++++++++++++++++++-------- 1 file changed, 40 insertions(+), 9 deletions(-) diff --git a/refs/files-backend.c b/refs/files-backend.c index b4e5437ffe..b7268b26c8 100644 --- a/refs/files-backend.c +++ b/refs/files-backend.c @@ -323,17 +323,15 @@ static void loose_fill_ref_dir(struct ref_store *ref_store, add_per_worktree_entries_to_dir(dir, dirname); } -/* - * Add root refs to the ref dir by parsing the directory for any files which - * follow the root ref syntax. - */ -static void add_root_refs(struct files_ref_store *refs, - struct ref_dir *dir) +static int for_each_root_ref(struct files_ref_store *refs, + int (*cb)(const char *refname, void *cb_data), + void *cb_data) { struct strbuf path = STRBUF_INIT, refname = STRBUF_INIT; const char *dirname = refs->loose->root->name; struct dirent *de; size_t dirnamelen; + int ret; DIR *d; files_ref_path(refs, &path, dirname); @@ -341,7 +339,7 @@ static void add_root_refs(struct files_ref_store *refs, d = opendir(path.buf); if (!d) { strbuf_release(&path); - return; + return -1; } strbuf_addstr(&refname, dirname); @@ -357,14 +355,47 @@ static void add_root_refs(struct files_ref_store *refs, strbuf_addstr(&refname, de->d_name); dtype = get_dtype(de, &path, 1); - if (dtype == DT_REG && is_root_ref(de->d_name)) - loose_fill_ref_dir_regular_file(refs, refname.buf, dir); + if (dtype == DT_REG && is_root_ref(de->d_name)) { + ret = cb(refname.buf, cb_data); + if (ret) + goto done; + } strbuf_setlen(&refname, dirnamelen); } + +done: strbuf_release(&refname); strbuf_release(&path); closedir(d); + return ret; +} + +struct fill_root_ref_data { + struct files_ref_store *refs; + struct ref_dir *dir; +}; + +static int fill_root_ref(const char *refname, void *cb_data) +{ + struct fill_root_ref_data *data = cb_data; + loose_fill_ref_dir_regular_file(data->refs, refname, data->dir); + return 0; +} + +/* + * Add root refs to the ref dir by parsing the directory for any files which + * follow the root ref syntax. + */ +static void add_root_refs(struct files_ref_store *refs, + struct ref_dir *dir) +{ + struct fill_root_ref_data data = { + .refs = refs, + .dir = dir, + }; + + for_each_root_ref(refs, fill_root_ref, &data); } static struct ref_cache *get_loose_ref_cache(struct files_ref_store *refs, From patchwork Fri May 24 10:15:01 2024 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Patrick Steinhardt X-Patchwork-Id: 13673024 Received: from fhigh2-smtp.messagingengine.com (fhigh2-smtp.messagingengine.com [103.168.172.153]) (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 7A42E85261 for ; Fri, 24 May 2024 10:15:05 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=103.168.172.153 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1716545707; cv=none; b=UQyWY6L5eok/541fKaoD8UlJw0GE1ry++s+/Y3hLsNpzA8c/Evdhur1Sk5W1Vy42NMnVQf2M9XAE9P9zCultrCyzhFXCZgpjEQby9c6+heACU1AXGsLi4IujaBjoQxYx80Y6hfIbLJMH6/kD/cBRoXTgqXU4qD0p14WbIz86Sqk= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1716545707; c=relaxed/simple; bh=S4roNQp/iGbmHc+Gzb9aKrzD5pSkfHk5OGcHBWQfZ88=; h=Date:From:To:Cc:Subject:Message-ID:References:MIME-Version: Content-Type:Content-Disposition:In-Reply-To; b=GV1R7VYpDjv/T7zHARyVaIcWJwtth1I4PTLo18G9czBUOT1cg4/onAstNRDIucxXbDaraQIdM/9cewJQ9EqRm+F7EZrl2eooHexAs6micCoDYyM2DiJQgkmp3GRiSuZ78Z56rOcfG/UMuRWD2Dg5w0aBJIlTuMvajEg7GTaNetc= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=reject dis=none) header.from=pks.im; spf=pass smtp.mailfrom=pks.im; dkim=pass (2048-bit key) header.d=pks.im header.i=@pks.im header.b=K2JkeUDQ; dkim=pass (2048-bit key) header.d=messagingengine.com header.i=@messagingengine.com header.b=DuQ4gjLd; arc=none smtp.client-ip=103.168.172.153 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=reject 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="K2JkeUDQ"; dkim=pass (2048-bit key) header.d=messagingengine.com header.i=@messagingengine.com header.b="DuQ4gjLd" Received: from compute1.internal (compute1.nyi.internal [10.202.2.41]) by mailfhigh.nyi.internal (Postfix) with ESMTP id C4E2C114019E; Fri, 24 May 2024 06:15:04 -0400 (EDT) Received: from mailfrontend1 ([10.202.2.162]) by compute1.internal (MEProxy); Fri, 24 May 2024 06:15:04 -0400 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=fm1; t=1716545704; x=1716632104; bh=cwoVDG6pgK qgHzcEFhocVZfEkJ8NpMc3x1gz/UtLXhA=; b=K2JkeUDQz/ldmzkzXJ4IuPhDH5 VHV192eRuXiCnTOLg6hz67Gj2/1SUmi1BL0+djFne67bzRTPx2QtIA9l0csRwTo1 PXvbOeqFIcAeyVeWMzu9MZ/PQgeSn4haUoC24Mw6xdX0Jto1WG7UVTp8NwQzkAnp RkFokm6IBYNrE23NF4c1cIDF98PaUQt02giu4hedZ3z+7X0S/h5GSNiXflQvo+CF bN7YYqIX55o150wtc/WXrcI+bOd3t7nVMkPGG3eYos513Usjtz9d+WhtsP2s5G2n Xq3ofnwolNLt61+Ul+JM0V2b3ppnebkVepXu2KuH39HUAWWlzXycJjYgxIzg== 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= fm1; t=1716545704; x=1716632104; bh=cwoVDG6pgKqgHzcEFhocVZfEkJ8N pMc3x1gz/UtLXhA=; b=DuQ4gjLdznZs2/0wU7cW5lTjuzjXbt1dn/uZywUmL99a 5PTpGu8wCkfDjafIF1wjHfKqJx99KVJjzxXFDwBJiem/wHB6Vrb7lhKK3h360gtv CL6ydpP1cQz4F2Bdlr789D+raO+/UzhNreo138RPE5sRtf/yp7EqnTp699KEzjNz +qEWCfc9VLuMW8W27Eb7TN+J9T9gVC4/NsRTVJvR9e7brUw2IgSlyP1+vGapyn0w TL92J7paAjjdRM7YMrVLn6Xf3x6L+V/s2WKjiGE/XRjiNzSGTagT+maWaUau2QEw MtGdK4e1T2c0PdthsRjjCk1xcjE8J0xbg5PUvaNq4A== X-ME-Sender: X-ME-Received: X-ME-Proxy-Cause: gggruggvucftvghtrhhoucdtuddrgedvledrvdeikedgvdefucetufdoteggodetrfdotf fvucfrrhhofhhilhgvmecuhfgrshhtofgrihhlpdfqfgfvpdfurfetoffkrfgpnffqhgen uceurghilhhouhhtmecufedttdenucesvcftvggtihhpihgvnhhtshculddquddttddmne cujfgurhepfffhvfevuffkfhggtggujgesghdtreertddtvdenucfhrhhomheprfgrthhr ihgtkhcuufhtvghinhhhrghrughtuceophhssehpkhhsrdhimheqnecuggftrfgrthhtvg hrnhepueektdevtdffveeljeetgfehheeigeekleduvdeffeeghefgledttdehjeelffet necuvehluhhsthgvrhfuihiivgepvdenucfrrghrrghmpehmrghilhhfrhhomhepphhsse hpkhhsrdhimh X-ME-Proxy: Feedback-ID: i197146af:Fastmail Received: by mail.messagingengine.com (Postfix) with ESMTPA; Fri, 24 May 2024 06:15:03 -0400 (EDT) Received: by localhost (OpenSMTPD) with ESMTPSA id a2f3a1b4 (TLSv1.3:TLS_AES_256_GCM_SHA384:256:NO); Fri, 24 May 2024 10:15:01 +0000 (UTC) Date: Fri, 24 May 2024 12:15:01 +0200 From: Patrick Steinhardt To: git@vger.kernel.org Cc: Eric Sunshine , Junio C Hamano Subject: [PATCH v2 7/9] refs: implement removal of ref storages 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: We're about to introduce logic to migrate ref storages. One part of the migration will be to delete the files that are part of the old ref storage format. We don't yet have a way to delete such data generically across ref backends though. Implement a new `delete` callback and expose it via a new `ref_storage_delete()` function. Signed-off-by: Patrick Steinhardt --- refs.c | 5 ++++ refs.h | 5 ++++ refs/files-backend.c | 61 +++++++++++++++++++++++++++++++++++++++++ refs/packed-backend.c | 15 ++++++++++ refs/refs-internal.h | 7 +++++ refs/reftable-backend.c | 34 +++++++++++++++++++++++ 6 files changed, 127 insertions(+) diff --git a/refs.c b/refs.c index 66e9585767..9b112b0527 100644 --- a/refs.c +++ b/refs.c @@ -1861,6 +1861,11 @@ int ref_store_create_on_disk(struct ref_store *refs, int flags, struct strbuf *e return refs->be->create_on_disk(refs, flags, err); } +int ref_store_remove_on_disk(struct ref_store *refs, struct strbuf *err) +{ + return refs->be->remove_on_disk(refs, err); +} + int repo_resolve_gitlink_ref(struct repository *r, const char *submodule, const char *refname, struct object_id *oid) diff --git a/refs.h b/refs.h index 50a2b3ab09..61ee7b7a15 100644 --- a/refs.h +++ b/refs.h @@ -129,6 +129,11 @@ int ref_store_create_on_disk(struct ref_store *refs, int flags, struct strbuf *e */ void ref_store_release(struct ref_store *ref_store); +/* + * Remove the ref store from disk. This deletes all associated data. + */ +int ref_store_remove_on_disk(struct ref_store *refs, struct strbuf *err); + /* * Return the peeled value of the oid currently being iterated via * for_each_ref(), etc. This is equivalent to calling: diff --git a/refs/files-backend.c b/refs/files-backend.c index b7268b26c8..8b74518022 100644 --- a/refs/files-backend.c +++ b/refs/files-backend.c @@ -3340,11 +3340,72 @@ static int files_ref_store_create_on_disk(struct ref_store *ref_store, return 0; } +struct remove_one_root_ref_data { + const char *gitdir; + struct strbuf *err; +}; + +static int remove_one_root_ref(const char *refname, + void *cb_data) +{ + struct remove_one_root_ref_data *data = cb_data; + struct strbuf buf = STRBUF_INIT; + int ret = 0; + + strbuf_addf(&buf, "%s/%s", data->gitdir, refname); + + ret = remove_path(buf.buf); + if (ret < 0) + strbuf_addf(data->err, "could not delete %s: %s\n", + refname, strerror(errno)); + + strbuf_release(&buf); + return ret; +} + +static int files_ref_store_remove_on_disk(struct ref_store *ref_store, + struct strbuf *err) +{ + struct files_ref_store *refs = + files_downcast(ref_store, REF_STORE_WRITE, "remove"); + struct remove_one_root_ref_data data = { + .gitdir = refs->base.gitdir, + .err = err, + }; + struct strbuf sb = STRBUF_INIT; + int ret = 0; + + strbuf_addf(&sb, "%s/refs", refs->base.gitdir); + if (remove_dir_recursively(&sb, 0) < 0) { + strbuf_addstr(err, "could not delete refs"); + ret = -1; + } + strbuf_reset(&sb); + + strbuf_addf(&sb, "%s/logs", refs->base.gitdir); + if (remove_dir_recursively(&sb, 0) < 0) { + strbuf_addstr(err, "could not delete logs\n"); + ret = -1; + } + strbuf_reset(&sb); + + ret = for_each_root_ref(refs, remove_one_root_ref, &data); + if (ret < 0) + ret = -1; + + if (ref_store_remove_on_disk(refs->packed_ref_store, err) < 0) + ret = -1; + + strbuf_release(&sb); + return ret; +} + struct ref_storage_be refs_be_files = { .name = "files", .init = files_ref_store_init, .release = files_ref_store_release, .create_on_disk = files_ref_store_create_on_disk, + .remove_on_disk = files_ref_store_remove_on_disk, .transaction_prepare = files_transaction_prepare, .transaction_finish = files_transaction_finish, diff --git a/refs/packed-backend.c b/refs/packed-backend.c index 2789fd92f5..c4c1e36aa2 100644 --- a/refs/packed-backend.c +++ b/refs/packed-backend.c @@ -1,5 +1,6 @@ #include "../git-compat-util.h" #include "../config.h" +#include "../dir.h" #include "../gettext.h" #include "../hash.h" #include "../hex.h" @@ -1266,6 +1267,19 @@ static int packed_ref_store_create_on_disk(struct ref_store *ref_store UNUSED, return 0; } +static int packed_ref_store_remove_on_disk(struct ref_store *ref_store, + struct strbuf *err) +{ + struct packed_ref_store *refs = packed_downcast(ref_store, 0, "remove"); + + if (remove_path(refs->path) < 0) { + strbuf_addstr(err, "could not delete packed-refs"); + return -1; + } + + return 0; +} + /* * Write the packed refs from the current snapshot to the packed-refs * tempfile, incorporating any changes from `updates`. `updates` must @@ -1724,6 +1738,7 @@ struct ref_storage_be refs_be_packed = { .init = packed_ref_store_init, .release = packed_ref_store_release, .create_on_disk = packed_ref_store_create_on_disk, + .remove_on_disk = packed_ref_store_remove_on_disk, .transaction_prepare = packed_transaction_prepare, .transaction_finish = packed_transaction_finish, diff --git a/refs/refs-internal.h b/refs/refs-internal.h index 33749fbd83..cbcb6f9c36 100644 --- a/refs/refs-internal.h +++ b/refs/refs-internal.h @@ -517,6 +517,12 @@ typedef int ref_store_create_on_disk_fn(struct ref_store *refs, int flags, struct strbuf *err); +/* + * Remove the reference store from disk. + */ +typedef int ref_store_remove_on_disk_fn(struct ref_store *refs, + struct strbuf *err); + typedef int ref_transaction_prepare_fn(struct ref_store *refs, struct ref_transaction *transaction, struct strbuf *err); @@ -649,6 +655,7 @@ struct ref_storage_be { ref_store_init_fn *init; ref_store_release_fn *release; ref_store_create_on_disk_fn *create_on_disk; + ref_store_remove_on_disk_fn *remove_on_disk; ref_transaction_prepare_fn *transaction_prepare; ref_transaction_finish_fn *transaction_finish; diff --git a/refs/reftable-backend.c b/refs/reftable-backend.c index bffed9257f..62992a67ee 100644 --- a/refs/reftable-backend.c +++ b/refs/reftable-backend.c @@ -1,6 +1,7 @@ #include "../git-compat-util.h" #include "../abspath.h" #include "../chdir-notify.h" +#include "../dir.h" #include "../environment.h" #include "../gettext.h" #include "../hash.h" @@ -343,6 +344,38 @@ static int reftable_be_create_on_disk(struct ref_store *ref_store, return 0; } +static int reftable_be_remove_on_disk(struct ref_store *ref_store, + struct strbuf *err) +{ + struct reftable_ref_store *refs = + reftable_be_downcast(ref_store, REF_STORE_WRITE, "remove"); + struct strbuf sb = STRBUF_INIT; + int ret = 0; + + strbuf_addf(&sb, "%s/reftable", refs->base.gitdir); + if (remove_dir_recursively(&sb, 0) < 0) { + strbuf_addstr(err, "could not delete reftables"); + ret = -1; + } + strbuf_reset(&sb); + + strbuf_addf(&sb, "%s/HEAD", refs->base.gitdir); + if (remove_path(sb.buf) < 0) { + strbuf_addstr(err, "could not delete stub HEAD"); + ret = -1; + } + strbuf_reset(&sb); + + strbuf_addf(&sb, "%s/refs/heads", refs->base.gitdir); + if (remove_path(sb.buf) < 0) { + strbuf_addstr(err, "could not delete stub heads"); + ret = -1; + } + + strbuf_release(&sb); + return ret; +} + struct reftable_ref_iterator { struct ref_iterator base; struct reftable_ref_store *refs; @@ -2196,6 +2229,7 @@ struct ref_storage_be refs_be_reftable = { .init = reftable_be_init, .release = reftable_be_release, .create_on_disk = reftable_be_create_on_disk, + .remove_on_disk = reftable_be_remove_on_disk, .transaction_prepare = reftable_be_transaction_prepare, .transaction_finish = reftable_be_transaction_finish, From patchwork Fri May 24 10:15:06 2024 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Patrick Steinhardt X-Patchwork-Id: 13673025 Received: from fhigh2-smtp.messagingengine.com (fhigh2-smtp.messagingengine.com [103.168.172.153]) (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 ACD1C85930 for ; Fri, 24 May 2024 10:15:10 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=103.168.172.153 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1716545712; cv=none; b=fwgPybfMqpoYi3mMatUy6dOQKGsLehwXLEmA6LjHJPZB7LVFLVA+/iNdfQUJUGt5tK4WKlCR9icgl2VFQAV316qT8fpmaQ5nzhX6LTC3aULfeF1J2pKSb7ulekrQyQz6TRd+nKsoQjM6zQ2+u6MCnhJjIHvvhUG4rTdO8oJKeW0= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1716545712; c=relaxed/simple; bh=vRaESfYj5FscoNrnNCA88iukijwFXwBEwca0GhresWo=; h=Date:From:To:Cc:Subject:Message-ID:References:MIME-Version: Content-Type:Content-Disposition:In-Reply-To; b=BZvroACXWsDaqFEEv1pqAZfAgI9gSqmZ/HFi3+Q/MMx8CW5LNUKasf0FDVO/GI+MCY8y3hcgZP/6LYxJjCKASUqNaFtAXHLpzfan5S6OYGNo0XJITsSWZ9AB6igRbykHCog00U/+VwYCl9xfn+rvwsIqpbcmDzDwgZa82oEzpuA= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=reject dis=none) header.from=pks.im; spf=pass smtp.mailfrom=pks.im; dkim=pass (2048-bit key) header.d=pks.im header.i=@pks.im header.b=eF/W2p/L; dkim=pass (2048-bit key) header.d=messagingengine.com header.i=@messagingengine.com header.b=WszER8jn; arc=none smtp.client-ip=103.168.172.153 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=reject 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="eF/W2p/L"; dkim=pass (2048-bit key) header.d=messagingengine.com header.i=@messagingengine.com header.b="WszER8jn" Received: from compute1.internal (compute1.nyi.internal [10.202.2.41]) by mailfhigh.nyi.internal (Postfix) with ESMTP id 0B12B114019E; Fri, 24 May 2024 06:15:10 -0400 (EDT) Received: from mailfrontend1 ([10.202.2.162]) by compute1.internal (MEProxy); Fri, 24 May 2024 06:15:10 -0400 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=fm1; t=1716545710; x=1716632110; bh=7OvBFtuha0 pupDO4wUMz+/Hn/NuWEnYPmqGPuN4HX88=; b=eF/W2p/L+Ei7dr6dh14FcJOMYS iejHvVoH0rY7jp7hpa4FLwTAw409lFwy4U/Ud6/zh6s9Ocsh86XLZz9/M6jPlJor SbxPqdEkdJLCe+y4BOJAZJujfi4L00uEIwfdPXtKD4p5O5FOvWKPkAccidQGj2NL vgq1B3Yh2QrLwYOoeAmaq3+PFPZ9gzXz+BznYXlEFESIUlTl5F4OyTOXEG3XfxX3 4h//ZrKhSl5/QKCu0giEn1y4ePgtopc9jxHJlH2rgN2HDTs3uUZwpKYMm0aTOelL +G0eWdIGLzNy/ctPFUHlMHlDi9Ac/+62Oy2yolxbVlkak5frDqqLp+WGzjOA== 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= fm1; t=1716545710; x=1716632110; bh=7OvBFtuha0pupDO4wUMz+/Hn/NuW EnYPmqGPuN4HX88=; b=WszER8jn9+o+m342ZPQ3DWE3stgqJiqPTkEMsHtFf5EX DQopIVJCZWOOOS5dmKF6LkV9wyoXtaDwMGzSv1fOsw/o7xZeyXaZrfoDnrmtPTfL ZlOQ5gJxZO8IiOwNkicI7LZq2wgfCNn3rU1qQo7oGb4jzUnOFviZR4D7WRA/1s86 E+Gp/0MljZoH3/ihahhnE7t32Qz9wvsSZzM9/Yz4lykaksdHId4vtW8C+iAv2XqX BdwC23xRfcvCSoa0bcpeTC4Nxv4z8bd5+CyTb8FPEXbaPqthSjVAM5sFYLD9nWSg bU1MQ7JbvbMTvA9Pyk06t4OiuYL0tq5Rmy391B81Mw== X-ME-Sender: X-ME-Received: X-ME-Proxy-Cause: gggruggvucftvghtrhhoucdtuddrgedvledrvdeikedgvdefucetufdoteggodetrfdotf fvucfrrhhofhhilhgvmecuhfgrshhtofgrihhlpdfqfgfvpdfurfetoffkrfgpnffqhgen uceurghilhhouhhtmecufedttdenucesvcftvggtihhpihgvnhhtshculddquddttddmne cujfgurhepfffhvfevuffkfhggtggujgesghdtreertddtvdenucfhrhhomheprfgrthhr ihgtkhcuufhtvghinhhhrghrughtuceophhssehpkhhsrdhimheqnecuggftrfgrthhtvg hrnhepueektdevtdffveeljeetgfehheeigeekleduvdeffeeghefgledttdehjeelffet necuvehluhhsthgvrhfuihiivgepfeenucfrrghrrghmpehmrghilhhfrhhomhepphhsse hpkhhsrdhimh X-ME-Proxy: Feedback-ID: i197146af:Fastmail Received: by mail.messagingengine.com (Postfix) with ESMTPA; Fri, 24 May 2024 06:15:08 -0400 (EDT) Received: by localhost (OpenSMTPD) with ESMTPSA id 1440e735 (TLSv1.3:TLS_AES_256_GCM_SHA384:256:NO); Fri, 24 May 2024 10:15:05 +0000 (UTC) Date: Fri, 24 May 2024 12:15:06 +0200 From: Patrick Steinhardt To: git@vger.kernel.org Cc: Eric Sunshine , Junio C Hamano Subject: [PATCH v2 8/9] refs: implement logic to migrate between ref storage formats Message-ID: <4d3eb5ea896bffffbf28ab4865b69901cc9edee7.1716545235.git.ps@pks.im> 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: With the introduction of the new "reftable" backend, users may want to migrate repositories between the backends without having to recreate the whole repository. Add the logic to do so. The implementation is generic and works with arbitrary ref storage formats so that a backend does not need to implement any migration logic. It does have a few limitations though: - We do not migrate repositories with worktrees, because worktrees have separate ref storages. It makes the overall affair more complex if we have to migrate multiple storages at once. - We do not migrate reflogs, because we have no interfaces to write many reflog entries. - We do not lock the repository for concurrent access, and thus concurrent writes may make use end up with weird in-between states. There is no way to fully lock the "files" backend for writes due to its format, and thus we punt on this topic altogether and defer to the user to avoid those from happening. In other words, this version is a minimum viable product for migrating a repository's ref storage format. It works alright for bare repos, which often have neither worktrees nor reflogs. But it will not work for many other repositories without some preparations. These limitations are not set into stone though, and ideally we will eventually address them over time. The logic is not yet used by anything, and thus there are no tests for it. Those will be added in the next commit. Signed-off-by: Patrick Steinhardt --- refs.c | 284 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++ refs.h | 18 ++++ 2 files changed, 302 insertions(+) diff --git a/refs.c b/refs.c index 9b112b0527..4ef2dae5e1 100644 --- a/refs.c +++ b/refs.c @@ -2570,3 +2570,287 @@ int ref_update_check_old_target(const char *referent, struct ref_update *update, referent, update->old_target); return -1; } + +struct migration_data { + struct ref_store *old_refs; + struct ref_store *new_refs; + struct ref_transaction *transaction; + struct strbuf *errbuf; + const char *refname; +}; + +static int migrate_one_ref(const char *refname, const struct object_id *oid, + int flags, void *cb_data) +{ + struct migration_data *data = cb_data; + struct strbuf symref_target = STRBUF_INIT; + int ret; + + if (flags & REF_ISSYMREF) { + ret = refs_read_symbolic_ref(data->old_refs, refname, &symref_target); + if (ret < 0) + goto done; + + ret = ref_transaction_update(data->transaction, refname, NULL, null_oid(), + symref_target.buf, NULL, + REF_SKIP_CREATE_REFLOG | REF_NO_DEREF, NULL, data->errbuf); + if (ret < 0) + goto done; + } else { + ret = ref_transaction_create(data->transaction, refname, oid, + REF_SKIP_CREATE_REFLOG | REF_SKIP_OID_VERIFICATION, + NULL, data->errbuf); + if (ret < 0) + goto done; + } + +done: + strbuf_release(&symref_target); + return ret; +} + +static int move_files(const char *from_path, const char *to_path, struct strbuf *errbuf) +{ + struct strbuf from_buf = STRBUF_INIT, to_buf = STRBUF_INIT; + size_t from_len, to_len; + DIR *from_dir; + int ret; + + from_dir = opendir(from_path); + if (!from_dir) { + strbuf_addf(errbuf, "could not open source directory: '%s'", from_path); + ret = -1; + goto done; + } + + strbuf_addstr(&from_buf, from_path); + strbuf_complete(&from_buf, '/'); + from_len = from_buf.len; + + strbuf_addstr(&to_buf, to_path); + strbuf_complete(&to_buf, '/'); + to_len = to_buf.len; + + while (1) { + struct dirent *ent; + + errno = 0; + ent = readdir(from_dir); + if (!ent) + break; + + if (!strcmp(ent->d_name, ".") || + !strcmp(ent->d_name, "..")) + continue; + + strbuf_setlen(&from_buf, from_len); + strbuf_addstr(&from_buf, ent->d_name); + + strbuf_setlen(&to_buf, to_len); + strbuf_addstr(&to_buf, ent->d_name); + + ret = rename(from_buf.buf, to_buf.buf); + if (ret < 0) { + strbuf_addf(errbuf, "could not link file '%s' to '%s': %s", + from_buf.buf, to_buf.buf, strerror(errno)); + goto done; + } + } + + if (errno) { + strbuf_addf(errbuf, "could not read entry from directory '%s': %s", + from_path, strerror(errno)); + ret = -1; + goto done; + } + + ret = 0; + +done: + strbuf_release(&from_buf); + strbuf_release(&to_buf); + closedir(from_dir); + return ret; +} + +static int count_reflogs(const char *reflog, void *payload) +{ + size_t *reflog_count = payload; + (*reflog_count)++; + return 0; +} + +static int has_worktrees(void) +{ + struct worktree **worktrees = get_worktrees(); + int ret = 0; + size_t i; + + for (i = 0; worktrees[i]; i++) { + if (is_main_worktree(worktrees[i])) + continue; + ret = 1; + } + + free_worktrees(worktrees); + return ret; +} + +int repo_migrate_ref_storage_format(struct repository *repo, + enum ref_storage_format format, + unsigned int flags, + struct strbuf *errbuf) +{ + struct ref_store *old_refs = NULL, *new_refs = NULL; + struct ref_transaction *transaction = NULL; + struct strbuf buf = STRBUF_INIT; + struct migration_data data; + size_t reflog_count = 0; + char *new_gitdir; + int ret; + + old_refs = get_main_ref_store(repo); + + /* + * The overall logic looks like this: + * + * 1. Set up a new temporary directory and initialize it with the new + * format. This is where all refs will be migrated into. + * + * 2. Enumerate all refs and write them into the new ref storage. + * This operation is safe as we do not yet modify the main + * repository. + * + * 3. If we're in dry-run mode then we are done and can hand over the + * directory to the caller for inspection. If not, we now start + * with the destructive part. + * + * 4. Delete the old ref storage from disk. As we have a copy of refs + * in the new ref storage it's okay(ish) if we now get interrupted + * as there is an equivalent copy of all refs available. + * + * 5. Move the new ref storage files into place. + * + * 6. Change the repository format to the new ref format. + */ + strbuf_addf(&buf, "%s/%s", old_refs->gitdir, "ref_migration.XXXXXX"); + new_gitdir = mkdtemp(buf.buf); + if (!new_gitdir) { + strbuf_addf(errbuf, "cannot create migration directory: %s", + strerror(errno)); + ret = -1; + goto done; + } + + if (refs_for_each_reflog(old_refs, count_reflogs, &reflog_count) < 0) { + strbuf_addstr(errbuf, "cannot count reflogs"); + ret = -1; + goto done; + } + if (reflog_count) { + strbuf_addstr(errbuf, "migrating reflogs is not supported yet"); + ret = -1; + goto done; + } + + /* + * TODO: we should really be passing the caller-provided repository to + * `has_worktrees()`, but our worktree subsystem doesn't yet support + * that. + */ + if (has_worktrees()) { + strbuf_addstr(errbuf, "migrating repositories with worktrees is not supported yet"); + ret = -1; + goto done; + } + + new_refs = ref_store_init(repo, format, new_gitdir, + REF_STORE_ALL_CAPS); + ret = ref_store_create_on_disk(new_refs, 0, errbuf); + if (ret < 0) + goto done; + + transaction = ref_store_transaction_begin(new_refs, errbuf); + if (!transaction) + goto done; + + data.old_refs = old_refs; + data.new_refs = new_refs; + data.transaction = transaction; + data.errbuf = errbuf; + + /* + * We need to use the internal `do_for_each_ref()` here so that we can + * also include broken refs and symrefs. These would otherwise be + * skipped silently. + * + * Ideally, we would do this call while locking the old ref storage + * such that there cannot be any concurrent modifications. We do not + * have the infra for that though, and the "files" backend does not + * allow for a central lock due to its design. It's thus on the user to + * ensure that there are no concurrent writes. + */ + ret = do_for_each_ref(old_refs, "", NULL, migrate_one_ref, 0, + DO_FOR_EACH_INCLUDE_ROOT_REFS | DO_FOR_EACH_INCLUDE_BROKEN, + &data); + if (ret < 0) + goto done; + + /* + * TODO: we might want to migrate to `initial_ref_transaction_commit()` + * here, which is more efficient for the files backend because it would + * write new refs into the packed-refs file directly. At this point, + * the files backend doesn't handle pseudo-refs and symrefs correctly + * though, so this requires some more work. + */ + ret = ref_transaction_commit(transaction, errbuf); + if (ret < 0) + goto done; + + if (flags & REPO_MIGRATE_REF_STORAGE_FORMAT_DRYRUN) { + printf(_("Finished dry-run migration of refs, " + "the result can be found at '%s'\n"), new_gitdir); + ret = 0; + goto done; + } + + /* + * Until now we were in the non-destructive phase, where we only + * populated the new ref store. From hereon though we are about + * to get hands by deleting the old ref store and then moving + * the new one into place. + * + * Assuming that there were no concurrent writes, the new ref + * store should have all information. So if we fail from hereon + * we may be in an in-between state, but it would still be able + * to recover by manually moving remaining files from the + * temporary migration directory into place. + */ + ret = ref_store_remove_on_disk(old_refs, errbuf); + if (ret < 0) + goto done; + + ret = move_files(new_gitdir, old_refs->gitdir, errbuf); + if (ret < 0) + goto done; + rmdir(new_gitdir); + + /* + * We have migrated the repository, so we now need to adjust the + * repository format so that clients will use the new ref store. + * We also need to swap out the repository's main ref store. + */ + initialize_repository_version(hash_algo_by_ptr(repo->hash_algo), format, 1); + + repo->refs_private = new_refs; + ref_store_release(old_refs); + + ret = 0; + +done: + if (ret && new_refs) + ref_store_release(new_refs); + ref_transaction_free(transaction); + strbuf_release(&buf); + return ret; +} diff --git a/refs.h b/refs.h index 61ee7b7a15..76d25df4de 100644 --- a/refs.h +++ b/refs.h @@ -1070,6 +1070,24 @@ int is_root_ref(const char *refname); */ int is_pseudo_ref(const char *refname); +/* + * The following flags can be passed to `repo_migrate_ref_storage_format()`: + * + * - REPO_MIGRATE_REF_STORAGE_FORMAT_DRYRUN: perform a dry-run migration + * without touching the main repository. The result will be written into a + * temporary ref storage directory. + */ +#define REPO_MIGRATE_REF_STORAGE_FORMAT_DRYRUN (1 << 0) + +/* + * Migrate the ref storage format used by the repository to the + * specified one. + */ +int repo_migrate_ref_storage_format(struct repository *repo, + enum ref_storage_format format, + unsigned int flags, + struct strbuf *err); + /* * The following functions have been removed in Git v2.45 in favor of functions * that receive a `ref_store` as parameter. The intent of this section is From patchwork Fri May 24 10:15:11 2024 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Patrick Steinhardt X-Patchwork-Id: 13673026 Received: from fout4-smtp.messagingengine.com (fout4-smtp.messagingengine.com [103.168.172.147]) (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 2E13985930 for ; Fri, 24 May 2024 10:15:14 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=103.168.172.147 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1716545717; cv=none; b=ZgVeQTlOysis08FnIad9ISpSmIV/HT1l5pZ5H+z//Ropfpuzyao9XJzvtL0WLX2knZEeMduk34y9jbAsMUU1uSqQiRMIwCc1yqlB/BZBZJEiHMrrfNAW2vVMw31uaBEjytoDZrOeJndOOxMLmUKG19kBmnuL9BOSwQU6AG/d/A0= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1716545717; c=relaxed/simple; bh=/R/2AbbXrVYuTFYzeLVJEMAhYpoLzwY1H151BDfM6gM=; h=Date:From:To:Cc:Subject:Message-ID:References:MIME-Version: Content-Type:Content-Disposition:In-Reply-To; b=k5odF7z6Dlg4FvxQK+soeJ9ezaVD3jSzY0XhhWQWLWK87uaVccIDgGkxvcNtHHYSpqps6CGPfL4nFLMq/UtC83VQXLkOSHyHKh7mjFypot+8rqVEoIFTYpcYqz37sU9kljDZu7u9jrLbWoPiuukqegHJJQz5Z4a62ubIss8Bptg= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=reject dis=none) header.from=pks.im; spf=pass smtp.mailfrom=pks.im; dkim=pass (2048-bit key) header.d=pks.im header.i=@pks.im header.b=bAH/hLFG; dkim=pass (2048-bit key) header.d=messagingengine.com header.i=@messagingengine.com header.b=HmNI0cXM; arc=none smtp.client-ip=103.168.172.147 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=reject 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="bAH/hLFG"; dkim=pass (2048-bit key) header.d=messagingengine.com header.i=@messagingengine.com header.b="HmNI0cXM" Received: from compute5.internal (compute5.nyi.internal [10.202.2.45]) by mailfout.nyi.internal (Postfix) with ESMTP id 44024138012D; Fri, 24 May 2024 06:15:14 -0400 (EDT) Received: from mailfrontend1 ([10.202.2.162]) by compute5.internal (MEProxy); Fri, 24 May 2024 06:15:14 -0400 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=fm1; t=1716545714; x=1716632114; bh=Jz1+1D2d1p sK1wBSigZM7fWPYh1CFZ0MGLvCLfumx6g=; b=bAH/hLFGttblCKqiibCXj7MNIA 5D5hc7e9v3aVNV3hxphdjznXWxeGcsbS5uouOv7hIjUeon4W1Tu7S6OA6sgC3+Bx kVUx5TWEeBwknVB6g+EqHy2++OOXW8UdKCaDHssan1bvi8sPuK18szqA79dr0vjh EpztsZ0v8Ty/44nTraLJ/ElvYtPL9Va6CuBNWRJMhsc6QJP5yMtJ+psnMoMF7Tbh wG13++jgOgXC9Nf/6jKer3wZ+qXbnHmzRfGu5lxaPnGunceYP8KCxIAL4j/DeK2e 9ryXbJu1A5pEM6hCEkRIFisluxYqEe4X5RgnMZ/PR5rrH2YUbuUVEHw2Ud6A== 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= fm1; t=1716545714; x=1716632114; bh=Jz1+1D2d1psK1wBSigZM7fWPYh1C FZ0MGLvCLfumx6g=; b=HmNI0cXMZlPMCmkMktaZ+6NRmD9f98/S8Gp/PGxQgEKQ 2/FpNHqV6nS5U1IoIAvLcu0BAEOgdFjOn+gylix+m+NN70H9GnXx/+0t89hAA4ot QYVK2z5Xfc9rvQAFCCXbDA0A4tpj8yBaUmDcvbERyaADFquwrw2wBC8pocOuc4gE ToT0koO/o4quhUMio7uOqMxSFJt8XiLT2uHKj3IQ4QOqj+YI0bAgEgYc6Eokzdv/ wB5sU7QjFi36gk39uunL0mPQSW3tCRz+dPowCkOmXtAKhCVCuXZv5QRs2zzePVH4 lL937Srxbj/CEig72sxrEhoGOZdU8sKiqtsC89ZMwQ== X-ME-Sender: X-ME-Received: X-ME-Proxy-Cause: gggruggvucftvghtrhhoucdtuddrgedvledrvdeikedgvdegucetufdoteggodetrfdotf fvucfrrhhofhhilhgvmecuhfgrshhtofgrihhlpdfqfgfvpdfurfetoffkrfgpnffqhgen uceurghilhhouhhtmecufedttdenucesvcftvggtihhpihgvnhhtshculddquddttddmne cujfgurhepfffhvfevuffkfhggtggujgesghdtreertddtvdenucfhrhhomheprfgrthhr ihgtkhcuufhtvghinhhhrghrughtuceophhssehpkhhsrdhimheqnecuggftrfgrthhtvg hrnhepueektdevtdffveeljeetgfehheeigeekleduvdeffeeghefgledttdehjeelffet necuvehluhhsthgvrhfuihiivgeptdenucfrrghrrghmpehmrghilhhfrhhomhepphhsse hpkhhsrdhimh X-ME-Proxy: Feedback-ID: i197146af:Fastmail Received: by mail.messagingengine.com (Postfix) with ESMTPA; Fri, 24 May 2024 06:15:13 -0400 (EDT) Received: by localhost (OpenSMTPD) with ESMTPSA id b05be614 (TLSv1.3:TLS_AES_256_GCM_SHA384:256:NO); Fri, 24 May 2024 10:15:10 +0000 (UTC) Date: Fri, 24 May 2024 12:15:11 +0200 From: Patrick Steinhardt To: git@vger.kernel.org Cc: Eric Sunshine , Junio C Hamano Subject: [PATCH v2 9/9] builtin/refs: new command to migrate ref storage formats Message-ID: <0df17a51b43e1e9d007328aad6457363876b2e1d.1716545235.git.ps@pks.im> 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: Introduce a new command that allows the user to migrate a repository between ref storage formats. This new command is implemented as part of a new git-refs(1) executable. This is due to two reasons: - There is no good place to put the migration logic in existing commands. git-maintenance(1) felt unwieldy, and git-pack-refs(1) is not the correct place to put it, either. - I had it in my mind to create a new low-level command for accessing refs for quite a while already. git-refs(1) is that command and can over time grow more functionality relating to refs. This should help discoverability by consolidating low-level access to refs into a single executable. As mentioned in the preceding commit that introduces the ref storage format migration logic, the new `git refs migrate` command still has a bunch of restrictions. These restrictions are documented accordingly. Signed-off-by: Patrick Steinhardt --- .gitignore | 1 + Documentation/git-refs.txt | 62 ++++++++++ Makefile | 1 + builtin.h | 1 + builtin/refs.c | 75 ++++++++++++ git.c | 1 + t/t1460-refs-migrate.sh | 243 +++++++++++++++++++++++++++++++++++++ 7 files changed, 384 insertions(+) create mode 100644 Documentation/git-refs.txt create mode 100644 builtin/refs.c create mode 100755 t/t1460-refs-migrate.sh diff --git a/.gitignore b/.gitignore index 612c0f6a0f..8caf3700c2 100644 --- a/.gitignore +++ b/.gitignore @@ -126,6 +126,7 @@ /git-rebase /git-receive-pack /git-reflog +/git-refs /git-remote /git-remote-http /git-remote-https diff --git a/Documentation/git-refs.txt b/Documentation/git-refs.txt new file mode 100644 index 0000000000..3f73ad6aa6 --- /dev/null +++ b/Documentation/git-refs.txt @@ -0,0 +1,62 @@ +git-refs(1) +=========== + +NAME +---- + +git-refs - Low-level access to refs + +SYNOPSIS +-------- + +[verse] +'git refs migrate' --ref-format= [--dry-run] + +DESCRIPTION +----------- + +This command provides low-level access to refs. + +COMMANDS +-------- + +migrate:: + Migrate ref store between different formats. + +OPTIONS +------- + +The following options are specific to 'git refs migrate': + +--ref-format=:: + The ref format to migrate the ref store to. Can be one of: ++ +include::ref-storage-format.txt[] + +--dry-run:: + Perform the migration, but do not modify the repository. The migrated + refs will be written into a separate directory that can be inspected + separately. The name of the directory will be reported on stdout. This + can be used to double check that the migration works as expected doing + performing the actual migration. + +KNOWN LIMITATIONS +----------------- + +The ref format migration has several known limitations in its current form: + +* It is not possible to migrate repositories that have reflogs. + +* It is not possible to migrate repositories that have worktrees. + +* There is no way to block concurrent writes to the repository during an + ongoing migration. Concurrent writes can lead to an inconsistent migrated + state. Users are expected to block writes on a higher level. If your + repository is registered for scheduled maintenance, it is recommended to + unregister it first with git-maintenance(1). + +These limitations may eventually be lifted. + +GIT +--- +Part of the linkgit:git[1] suite diff --git a/Makefile b/Makefile index cf504963c2..2d702b552c 100644 --- a/Makefile +++ b/Makefile @@ -1283,6 +1283,7 @@ BUILTIN_OBJS += builtin/read-tree.o BUILTIN_OBJS += builtin/rebase.o BUILTIN_OBJS += builtin/receive-pack.o BUILTIN_OBJS += builtin/reflog.o +BUILTIN_OBJS += builtin/refs.o BUILTIN_OBJS += builtin/remote-ext.o BUILTIN_OBJS += builtin/remote-fd.o BUILTIN_OBJS += builtin/remote.o diff --git a/builtin.h b/builtin.h index 28280636da..7eda9b2486 100644 --- a/builtin.h +++ b/builtin.h @@ -207,6 +207,7 @@ int cmd_rebase(int argc, const char **argv, const char *prefix); int cmd_rebase__interactive(int argc, const char **argv, const char *prefix); int cmd_receive_pack(int argc, const char **argv, const char *prefix); int cmd_reflog(int argc, const char **argv, const char *prefix); +int cmd_refs(int argc, const char **argv, const char *prefix); int cmd_remote(int argc, const char **argv, const char *prefix); int cmd_remote_ext(int argc, const char **argv, const char *prefix); int cmd_remote_fd(int argc, const char **argv, const char *prefix); diff --git a/builtin/refs.c b/builtin/refs.c new file mode 100644 index 0000000000..02401afa4e --- /dev/null +++ b/builtin/refs.c @@ -0,0 +1,75 @@ +#include "builtin.h" +#include "parse-options.h" +#include "refs.h" +#include "repository.h" +#include "strbuf.h" + +#define REFS_MIGRATE_USAGE \ + N_("git refs migrate --ref-format= [--dry-run]") + +static int cmd_refs_migrate(int argc, const char **argv, const char *prefix) +{ + const char * const migrate_usage[] = { + REFS_MIGRATE_USAGE, + NULL + }; + const char *format_str = NULL; + enum ref_storage_format format; + unsigned int flags = 0; + struct option options[] = { + OPT_STRING_F(0, "ref-format", &format_str, N_("format"), + N_("specify the reference format to convert to"), + PARSE_OPT_NONEG), + OPT_BIT(0, "dry-run", &flags, + N_("perform a non-destructive dry-run"), + REPO_MIGRATE_REF_STORAGE_FORMAT_DRYRUN), + OPT_END(), + }; + struct strbuf errbuf = STRBUF_INIT; + int err; + + argc = parse_options(argc, argv, prefix, options, migrate_usage, 0); + if (argc) + usage(_("too many arguments")); + if (!format_str) + usage(_("missing --ref-format=")); + + format = ref_storage_format_by_name(format_str); + if (format == REF_STORAGE_FORMAT_UNKNOWN) { + err = error(_("unknown ref storage format '%s'"), format_str); + goto out; + } + + if (the_repository->ref_storage_format == format) { + err = error(_("repository already uses '%s' format"), + ref_storage_format_to_name(format)); + goto out; + } + + if (repo_migrate_ref_storage_format(the_repository, format, flags, &errbuf) < 0) { + err = error("%s", errbuf.buf); + goto out; + } + + err = 0; + +out: + strbuf_release(&errbuf); + return err; +} + +int cmd_refs(int argc, const char **argv, const char *prefix) +{ + const char * const refs_usage[] = { + REFS_MIGRATE_USAGE, + NULL, + }; + parse_opt_subcommand_fn *fn = NULL; + struct option opts[] = { + OPT_SUBCOMMAND("migrate", &fn, cmd_refs_migrate), + OPT_END(), + }; + + argc = parse_options(argc, argv, prefix, opts, refs_usage, 0); + return fn(argc, argv, prefix); +} diff --git a/git.c b/git.c index 637c61ca9c..683bb69194 100644 --- a/git.c +++ b/git.c @@ -594,6 +594,7 @@ static struct cmd_struct commands[] = { { "rebase", cmd_rebase, RUN_SETUP | NEED_WORK_TREE }, { "receive-pack", cmd_receive_pack }, { "reflog", cmd_reflog, RUN_SETUP }, + { "refs", cmd_refs, RUN_SETUP }, { "remote", cmd_remote, RUN_SETUP }, { "remote-ext", cmd_remote_ext, NO_PARSEOPT }, { "remote-fd", cmd_remote_fd, NO_PARSEOPT }, diff --git a/t/t1460-refs-migrate.sh b/t/t1460-refs-migrate.sh new file mode 100755 index 0000000000..f7c0783d30 --- /dev/null +++ b/t/t1460-refs-migrate.sh @@ -0,0 +1,243 @@ +#!/bin/sh + +test_description='migration of ref storage backends' + +GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME=main +export GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME + +TEST_PASSES_SANITIZE_LEAK=true +. ./test-lib.sh + +test_migration () { + git -C "$1" for-each-ref --include-root-refs \ + --format='%(refname) %(objectname) %(symref)' >expect && + git -C "$1" refs migrate --ref-format="$2" && + git -C "$1" for-each-ref --include-root-refs \ + --format='%(refname) %(objectname) %(symref)' >actual && + test_cmp expect actual && + + git -C "$1" rev-parse --show-ref-format >actual && + echo "$2" >expect && + test_cmp expect actual +} + +test_expect_success 'setup' ' + rm -rf .git && + # The migration does not yet support reflogs. + git config --global core.logAllRefUpdates false +' + +test_expect_success "superfluous arguments" ' + test_when_finished "rm -rf repo" && + git init repo && + test_must_fail git -C repo refs migrate foo 2>err && + cat >expect <<-EOF && + usage: too many arguments + EOF + test_cmp expect err +' + +test_expect_success "missing ref storage format" ' + test_when_finished "rm -rf repo" && + git init repo && + test_must_fail git -C repo refs migrate 2>err && + cat >expect <<-EOF && + usage: missing --ref-format= + EOF + test_cmp expect err +' + +test_expect_success "unknown ref storage format" ' + test_when_finished "rm -rf repo" && + git init repo && + test_must_fail git -C repo refs migrate \ + --ref-format=unknown 2>err && + cat >expect <<-EOF && + error: unknown ref storage format ${SQ}unknown${SQ} + EOF + test_cmp expect err +' + +ref_formats="files reftable" +for from_format in $ref_formats +do + for to_format in $ref_formats + do + if test "$from_format" = "$to_format" + then + continue + fi + + test_expect_success "$from_format: migration to same format fails" ' + test_when_finished "rm -rf repo" && + git init --ref-format=$from_format repo && + test_must_fail git -C repo refs migrate \ + --ref-format=$from_format 2>err && + cat >expect <<-EOF && + error: repository already uses ${SQ}$from_format${SQ} format + EOF + test_cmp expect err + ' + + test_expect_success "$from_format -> $to_format: migration with reflog fails" ' + test_when_finished "rm -rf repo" && + git init --ref-format=$from_format repo && + test_config -C repo core.logAllRefUpdates true && + test_commit -C repo logged && + test_must_fail git -C repo refs migrate \ + --ref-format=$to_format 2>err && + cat >expect <<-EOF && + error: migrating reflogs is not supported yet + EOF + test_cmp expect err + ' + + test_expect_success "$from_format -> $to_format: migration with worktree fails" ' + test_when_finished "rm -rf repo" && + git init --ref-format=$from_format repo && + git -C repo worktree add wt && + test_must_fail git -C repo refs migrate \ + --ref-format=$to_format 2>err && + cat >expect <<-EOF && + error: migrating repositories with worktrees is not supported yet + EOF + test_cmp expect err + ' + + test_expect_success "$from_format -> $to_format: unborn HEAD" ' + test_when_finished "rm -rf repo" && + git init --ref-format=$from_format repo && + test_migration repo "$to_format" + ' + + test_expect_success "$from_format -> $to_format: single ref" ' + test_when_finished "rm -rf repo" && + git init --ref-format=$from_format repo && + test_commit -C repo initial && + test_migration repo "$to_format" + ' + + test_expect_success "$from_format -> $to_format: bare repository" ' + test_when_finished "rm -rf repo repo.git" && + git init --ref-format=$from_format repo && + test_commit -C repo initial && + git clone --ref-format=$from_format --mirror repo repo.git && + test_migration repo.git "$to_format" + ' + + test_expect_success "$from_format -> $to_format: dangling symref" ' + test_when_finished "rm -rf repo" && + git init --ref-format=$from_format repo && + test_commit -C repo initial && + git -C repo symbolic-ref BROKEN_HEAD refs/heads/nonexistent && + test_migration repo "$to_format" && + echo refs/heads/nonexistent >expect && + git -C repo symbolic-ref BROKEN_HEAD >actual && + test_cmp expect actual + ' + + test_expect_success "$from_format -> $to_format: broken ref" ' + test_when_finished "rm -rf repo" && + git init --ref-format=$from_format repo && + test_commit -C repo initial && + test-tool -C repo ref-store main update-ref "" refs/heads/broken \ + "$(test_oid 001)" "$ZERO_OID" REF_SKIP_CREATE_REFLOG,REF_SKIP_OID_VERIFICATION && + test_migration repo "$to_format" && + test_oid 001 >expect && + git -C repo rev-parse refs/heads/broken >actual && + test_cmp expect actual + ' + + test_expect_success "$from_format -> $to_format: pseudo-refs" ' + test_when_finished "rm -rf repo" && + git init --ref-format=$from_format repo && + test_commit -C repo initial && + git -C repo update-ref FOO_HEAD HEAD && + test_migration repo "$to_format" + ' + + test_expect_success "$from_format -> $to_format: special refs are left alone" ' + test_when_finished "rm -rf repo" && + git init --ref-format=$from_format repo && + test_commit -C repo initial && + git -C repo rev-parse HEAD >repo/.git/MERGE_HEAD && + git -C repo rev-parse MERGE_HEAD && + test_migration repo "$to_format" && + test_path_is_file repo/.git/MERGE_HEAD + ' + + test_expect_success "$from_format -> $to_format: a bunch of refs" ' + test_when_finished "rm -rf repo" && + git init --ref-format=$from_format repo && + + test_commit -C repo initial && + cat >input <<-EOF && + create FOO_HEAD HEAD + create refs/heads/branch-1 HEAD + create refs/heads/branch-2 HEAD + create refs/heads/branch-3 HEAD + create refs/heads/branch-4 HEAD + create refs/tags/tag-1 HEAD + create refs/tags/tag-2 HEAD + EOF + git -C repo update-ref --stdin $to_format: dry-run migration does not modify repository" ' + test_when_finished "rm -rf repo" && + git init --ref-format=$from_format repo && + test_commit -C repo initial && + git -C repo refs migrate --dry-run \ + --ref-format=$to_format >output && + grep "Finished dry-run migration of refs" output && + test_path_is_dir repo/.git/ref_migration.* && + echo $from_format >expect && + git -C repo rev-parse --show-ref-format >actual && + test_cmp expect actual + ' + done +done + +test_expect_success 'migrating from files format deletes backend files' ' + test_when_finished "rm -rf repo" && + git init --ref-format=files repo && + test_commit -C repo first && + git -C repo pack-refs --all && + test_commit -C repo second && + git -C repo update-ref ORIG_HEAD HEAD && + git -C repo rev-parse HEAD >repo/.git/FETCH_HEAD && + + test_path_is_file repo/.git/HEAD && + test_path_is_file repo/.git/ORIG_HEAD && + test_path_is_file repo/.git/refs/heads/main && + test_path_is_file repo/.git/packed-refs && + + test_migration repo reftable && + + echo "ref: refs/heads/.invalid" >expect && + test_cmp expect repo/.git/HEAD && + echo "this repository uses the reftable format" >expect && + test_cmp expect repo/.git/refs/heads && + test_path_is_file repo/.git/FETCH_HEAD && + test_path_is_missing repo/.git/ORIG_HEAD && + test_path_is_missing repo/.git/refs/heads/main && + test_path_is_missing repo/.git/logs && + test_path_is_missing repo/.git/packed-refs +' + +test_expect_success 'migrating from reftable format deletes backend files' ' + test_when_finished "rm -rf repo" && + git init --ref-format=reftable repo && + test_commit -C repo first && + + test_path_is_dir repo/.git/reftable && + test_migration repo files && + + test_path_is_missing repo/.git/reftable && + echo "ref: refs/heads/main" >expect && + test_cmp expect repo/.git/HEAD && + test_path_is_file repo/.git/refs/heads/main +' + +test_done