git/list[1] front-page[2] threads[3] people[4] search[5] about
 

[PATCH 04/12] setup: start tracking ref storage format when

From
Patrick Steinhardt <ps@pks.im>
Date
Dec 20, 2023, 10:55 UTC
Message-ID
<6564659d403de098799ddb8101b74c2803a655d4.1703067989.git.ps@pks.im>
In-Reply-To
<cover.1703067989.git.ps@pks.im>

In order to discern which ref storage format a repository is supposed to use we need to start setting up and/or discovering the format. This needs to happen in two separate code paths.

  - The first path is when we create a repository via `init_db()`. When
    we are re-initializing a preexisting repository we need to retain
    the previously used ref storage format -- if the user asked for a
    different format then this indicates an erorr and we error out.
    Otherwise we either initialize the repository with the format asked
    for by the user or the default format, which currently is the
    "files" backend.
  - The second path is when discovering repositories, where we need to
    read the config of that repository. There is not yet any way to
    configure something other than the "files" backend, so we can just
    blindly set the ref storage format to this backend.

Wire up this logic so that we have the ref storage format always readily available when needed. As there is only a single backend and because it is not configurable we cannot yet verify that this tracking works as expected via tests, but tests will be added in subsequent commits. To countermand this ommission now though, raise a BUG() in case the ref storage format is not set up properly in `ref_store_init()`.

Signed-off-by: Patrick Steinhardt <ps@pks.im>
---
 builtin/clone.c   |  5 +++--
 builtin/init-db.c |  4 +++-
 refs.c            |  6 +++---
 refs.h            |  1 +
 repository.c      |  1 +
 repository.h      |  3 +++
 setup.c           | 26 +++++++++++++++++++++++---
 setup.h           |  6 +++++-
 8 files changed, 42 insertions(+), 10 deletions(-)
diff --git a/builtin/clone.c b/builtin/clone.c
index 339af10c10..6840064b59 100644
--- a/builtin/clone.c
+++ b/builtin/clone.c
@@ -1105,7 +1105,8 @@ int cmd_clone(int argc, const char **argv, const char *prefix)
 	 * repository, and reference backends may persist that information into
 	 * their on-disk data structures.
 	 */
-	init_db(git_dir, real_git_dir, option_template, GIT_HASH_UNKNOWN, NULL,
+	init_db(git_dir, real_git_dir, option_template, GIT_HASH_UNKNOWN,
+		REF_STORAGE_FORMAT_UNKNOWN, NULL,
 		do_not_override_repo_unix_permissions, INIT_DB_QUIET | INIT_DB_SKIP_REFDB);
 
 	if (real_git_dir) {
@@ -1290,7 +1291,7 @@ int cmd_clone(int argc, const char **argv, const char *prefix)
 	hash_algo = hash_algo_by_ptr(transport_get_hash_algo(transport));
 	initialize_repository_version(hash_algo, 1);
 	repo_set_hash_algo(the_repository, hash_algo);
-	create_reference_database(NULL, 1);
+	create_reference_database(the_repository->ref_storage_format, NULL, 1);
 
 	/*
 	 * Before fetching from the remote, download and install bundle
diff --git a/builtin/init-db.c b/builtin/init-db.c
index cb727c826f..b6e80feab6 100644
--- a/builtin/init-db.c
+++ b/builtin/init-db.c
@@ -11,6 +11,7 @@
 #include "object-file.h"
 #include "parse-options.h"
 #include "path.h"
+#include "refs.h"
 #include "setup.h"
 #include "strbuf.h"
 
@@ -236,5 +237,6 @@ int cmd_init_db(int argc, const char **argv, const char *prefix)
 
 	flags |= INIT_DB_EXIST_OK;
 	return init_db(git_dir, real_git_dir, template_dir, hash_algo,
-		       initial_branch, init_shared_repository, flags);
+		       REF_STORAGE_FORMAT_UNKNOWN, initial_branch,
+		       init_shared_repository, flags);
 }
diff --git a/refs.c b/refs.c
index e87c85897d..d289a5e175 100644
--- a/refs.c
+++ b/refs.c
@@ -2045,12 +2045,12 @@ static struct ref_store *ref_store_init(struct repository *repo,
 					const char *gitdir,
 					unsigned int flags)
 {
-	int format = REF_STORAGE_FORMAT_FILES;
-	const struct ref_storage_be *be = find_ref_storage_backend(format);
+	const struct ref_storage_be *be;
 	struct ref_store *refs;
 
+	be = find_ref_storage_backend(repo->ref_storage_format);
 	if (!be)
-		BUG("reference backend %s is unknown", ref_storage_format_to_name(format));
+		BUG("reference backend is unknown");
 
 	refs = be->init(repo, gitdir, flags);
 	return refs;
diff --git a/refs.h b/refs.h
index c6571bcf6c..944a67ac1b 100644
--- a/refs.h
+++ b/refs.h
@@ -11,6 +11,7 @@ struct string_list;
 struct string_list_item;
 struct worktree;
 
+int default_ref_storage_format(void);
 int ref_storage_format_by_name(const char *name);
 const char *ref_storage_format_to_name(int ref_storage_format);
 
diff --git a/repository.c b/repository.c
index a7679ceeaa..a75c1598b0 100644
--- a/repository.c
+++ b/repository.c
@@ -184,6 +184,7 @@ int repo_init(struct repository *repo,
 		goto error;
 
 	repo_set_hash_algo(repo, format.hash_algo);
+	repo->ref_storage_format = format.ref_storage_format;
 	repo->repository_format_worktree_config = format.worktree_config;
 
 	/* take ownership of format.partial_clone */
diff --git a/repository.h b/repository.h
index ea4c488b81..22c30cdbc9 100644
--- a/repository.h
+++ b/repository.h
@@ -163,6 +163,9 @@ struct repository {
 	/* Repository's current hash algorithm, as serialized on disk. */
 	const struct git_hash_algo *hash_algo;
 
+	/* Repository's reference storage format, as serialized on disk. */
+	int ref_storage_format;
+
 	/* A unique-id for tracing purposes. */
 	int trace2_repo_id;
 
diff --git a/setup.c b/setup.c
index 155fe13f70..c1bf106379 100644
--- a/setup.c
+++ b/setup.c
@@ -1564,6 +1564,8 @@ const char *setup_git_directory_gently(int *nongit_ok)
 		}
 		if (startup_info->have_repository) {
 			repo_set_hash_algo(the_repository, repo_fmt.hash_algo);
+			the_repository->ref_storage_format =
+				repo_fmt.ref_storage_format;
 			the_repository->repository_format_worktree_config =
 				repo_fmt.worktree_config;
 			/* take ownership of repo_fmt.partial_clone */
@@ -1657,6 +1659,8 @@ void check_repository_format(struct repository_format *fmt)
 	check_repository_format_gently(get_git_dir(), fmt, NULL);
 	startup_info->have_repository = 1;
 	repo_set_hash_algo(the_repository, fmt->hash_algo);
+	the_repository->ref_storage_format =
+		fmt->ref_storage_format;
 	the_repository->repository_format_worktree_config =
 		fmt->worktree_config;
 	the_repository->repository_format_partial_clone =
@@ -1897,7 +1901,8 @@ static int is_reinit(void)
 	return ret;
 }
 
-void create_reference_database(const char *initial_branch, int quiet)
+void create_reference_database(int ref_storage_format,
+			       const char *initial_branch, int quiet)
 {
 	struct strbuf err = STRBUF_INIT;
 	int reinit = is_reinit();
@@ -1917,6 +1922,7 @@ void create_reference_database(const char *initial_branch, int quiet)
 	safe_create_dir(git_path("refs"), 1);
 	adjust_shared_perm(git_path("refs"));
 
+	the_repository->ref_storage_format = ref_storage_format;
 	if (refs_init_db(&err))
 		die("failed to set up refs db: %s", err.buf);
 
@@ -2135,8 +2141,20 @@ static void validate_hash_algorithm(struct repository_format *repo_fmt, int hash
 	}
 }
 
+static void validate_ref_storage_format(struct repository_format *repo_fmt, int format)
+{
+	if (repo_fmt->version >= 0 &&
+	    format != REF_STORAGE_FORMAT_UNKNOWN &&
+	    format != repo_fmt->ref_storage_format) {
+		die(_("attempt to reinitialize repository with different reference storage format"));
+	} else if (format != REF_STORAGE_FORMAT_UNKNOWN) {
+		repo_fmt->ref_storage_format = format;
+	}
+}
+
 int init_db(const char *git_dir, const char *real_git_dir,
-	    const char *template_dir, int hash, const char *initial_branch,
+	    const char *template_dir, int hash,
+	    int ref_storage_format, const char *initial_branch,
 	    int init_shared_repository, unsigned int flags)
 {
 	int reinit;
@@ -2179,13 +2197,15 @@ int init_db(const char *git_dir, const char *real_git_dir,
 	check_repository_format(&repo_fmt);
 
 	validate_hash_algorithm(&repo_fmt, hash);
+	validate_ref_storage_format(&repo_fmt, ref_storage_format);
 
 	reinit = create_default_files(template_dir, original_git_dir,
 				      &repo_fmt, prev_bare_repository,
 				      init_shared_repository);
 
 	if (!(flags & INIT_DB_SKIP_REFDB))
-		create_reference_database(initial_branch, flags & INIT_DB_QUIET);
+		create_reference_database(repo_fmt.ref_storage_format,
+					  initial_branch, flags & INIT_DB_QUIET);
 	create_object_directory();
 
 	if (get_shared_repository()) {
diff --git a/setup.h b/setup.h
index 3f0f17c351..4927abf2cf 100644
--- a/setup.h
+++ b/setup.h
@@ -115,6 +115,7 @@ struct repository_format {
 	int worktree_config;
 	int is_bare;
 	int hash_algo;
+	int ref_storage_format;
 	int sparse_index;
 	char *work_tree;
 	struct string_list unknown_extensions;
@@ -131,6 +132,7 @@ struct repository_format {
 	.version = -1, \
 	.is_bare = -1, \
 	.hash_algo = GIT_HASH_SHA1, \
+	.ref_storage_format = REF_STORAGE_FORMAT_FILES, \
 	.unknown_extensions = STRING_LIST_INIT_DUP, \
 	.v1_only_extensions = STRING_LIST_INIT_DUP, \
 }
@@ -175,10 +177,12 @@ void check_repository_format(struct repository_format *fmt);
 
 int init_db(const char *git_dir, const char *real_git_dir,
 	    const char *template_dir, int hash_algo,
+	    int ref_storage_format,
 	    const char *initial_branch, int init_shared_repository,
 	    unsigned int flags);
 void initialize_repository_version(int hash_algo, int reinit);
-void create_reference_database(const char *initial_branch, int quiet);
+void create_reference_database(int ref_storage_format,
+			       const char *initial_branch, int quiet);
 
 /*
  * NOTE NOTE NOTE!!
-- 
2.43.GIT
Previous: Patrick SteinhardtNext: Junio C Hamano
Message 10 of 60 in “Introduce `refStorage` extension”
  1. 00/12 Introduce `refStorage` extensionPatrick Steinhardt, Dec 20, 2023
  2. 01/12 t: introduce DEFAULT_REPO_FORMAT prereqPatrick Steinhardt, Dec 20, 2023
  3. Karthik NayakDec 22, 2023
  4. Patrick SteinhardtDec 28, 2023
  5. 02/12 worktree: skip reading HEAD when repairing worktreesPatrick Steinhardt, Dec 20, 2023
  6. Karthik NayakDec 22, 2023
  7. 03/12 refs: refactor logic to look up storage backendsPatrick Steinhardt, Dec 20, 2023
  8. Karthik NayakDec 22, 2023
  9. Patrick SteinhardtDec 28, 2023
  10. 04/12 setup: start tracking ref storage format whenPatrick Steinhardt, Dec 20, 2023
  11. Junio C HamanoDec 20, 2023
  12. Patrick SteinhardtDec 28, 2023
  13. Junio C HamanoDec 28, 2023
  14. Patrick SteinhardtDec 28, 2023
  15. Karthik NayakDec 22, 2023
  16. Patrick SteinhardtDec 28, 2023
  17. 05/12 setup: set repository's formats on initPatrick Steinhardt, Dec 20, 2023
  18. 06/12 setup: introduce "extensions.refStorage" extensionPatrick Steinhardt, Dec 20, 2023
  19. 07/12 setup: introduce GIT_DEFAULT_REF_FORMAT envvarPatrick Steinhardt, Dec 20, 2023
  20. 08/12 t: introduce GIT_TEST_DEFAULT_REF_FORMAT envvarPatrick Steinhardt, Dec 20, 2023
  21. 09/12 builtin/rev-parse: introduce `--show-ref-format` flagPatrick Steinhardt, Dec 20, 2023
  22. 10/12 builtin/init: introduce `--ref-format=` value flagPatrick Steinhardt, Dec 20, 2023
  23. 11/12 builtin/clone: introduce `--ref-format=` value flagPatrick Steinhardt, Dec 20, 2023
  24. 12/12 t9500: write "extensions.refstorage" into configPatrick Steinhardt, Dec 20, 2023
  25. Karthik NayakDec 22, 2023
  26. Karthik NayakDec 22, 2023
  27. Junio C HamanoDec 26, 2023
  28. 00/12 Introduce `refStorage` extensionPatrick Steinhardt, Dec 28, 2023
  29. 01/12 t: introduce DEFAULT_REPO_FORMAT prereqPatrick Steinhardt, Dec 28, 2023
  30. 02/12 worktree: skip reading HEAD when repairing worktreesPatrick Steinhardt, Dec 28, 2023
  31. Eric SunshineDec 28, 2023
  32. Eric SunshineDec 28, 2023
  33. Patrick SteinhardtDec 28, 2023
  34. 03/12 refs: refactor logic to look up storage backendsPatrick Steinhardt, Dec 28, 2023
  35. Junio C HamanoDec 28, 2023
  36. Patrick SteinhardtDec 28, 2023
  37. Junio C HamanoDec 28, 2023
  38. 04/12 setup: start tracking ref storage formatPatrick Steinhardt, Dec 28, 2023
  39. 05/12 setup: set repository's formats on initPatrick Steinhardt, Dec 28, 2023
  40. 06/12 setup: introduce "extensions.refStorage" extensionPatrick Steinhardt, Dec 28, 2023
  41. 07/12 setup: introduce GIT_DEFAULT_REF_FORMAT envvarPatrick Steinhardt, Dec 28, 2023
  42. 08/12 t: introduce GIT_TEST_DEFAULT_REF_FORMAT envvarPatrick Steinhardt, Dec 28, 2023
  43. 09/12 builtin/rev-parse: introduce `--show-ref-format` flagPatrick Steinhardt, Dec 28, 2023
  44. 10/12 builtin/init: introduce `--ref-format=` value flagPatrick Steinhardt, Dec 28, 2023
  45. 11/12 builtin/clone: introduce `--ref-format=` value flagPatrick Steinhardt, Dec 28, 2023
  46. 12/12 t9500: write "extensions.refstorage" into configPatrick Steinhardt, Dec 28, 2023
  47. 00/12 Introduce `refStorage` extensionPatrick Steinhardt, Dec 29, 2023
  48. 01/12 t: introduce DEFAULT_REPO_FORMAT prereqPatrick Steinhardt, Dec 29, 2023
  49. 02/12 worktree: skip reading HEAD when repairing worktreesPatrick Steinhardt, Dec 29, 2023
  50. 03/12 refs: refactor logic to look up storage backendsPatrick Steinhardt, Dec 29, 2023
  51. 04/12 setup: start tracking ref storage formatPatrick Steinhardt, Dec 29, 2023
  52. 05/12 setup: set repository's formats on initPatrick Steinhardt, Dec 29, 2023
  53. 06/12 setup: introduce "extensions.refStorage" extensionPatrick Steinhardt, Dec 29, 2023
  54. 07/12 setup: introduce GIT_DEFAULT_REF_FORMAT envvarPatrick Steinhardt, Dec 29, 2023
  55. 08/12 t: introduce GIT_TEST_DEFAULT_REF_FORMAT envvarPatrick Steinhardt, Dec 29, 2023
  56. 09/12 builtin/rev-parse: introduce `--show-ref-format` flagPatrick Steinhardt, Dec 29, 2023
  57. 10/12 builtin/init: introduce `--ref-format=` value flagPatrick Steinhardt, Dec 29, 2023
  58. 11/12 builtin/clone: introduce `--ref-format=` value flagPatrick Steinhardt, Dec 29, 2023
  59. 12/12 t9500: write "extensions.refstorage" into configPatrick Steinhardt, Dec 29, 2023
  60. Eric SunshineDec 29, 2023

Read the whole thread, see it on lore, or plain text.

$ cat FOOTERMessages come from the public archive at lore.kernel.org/git, fetched every hour. The front page is chosen and written each morning by an AI editor and can be wrong; the threads themselves are the record. About and API. For agents: an MCP server at https://gitlist.dev/mcp, and any thread, story or person page as Markdown by adding .md to its URL (or sending Accept: text/markdown). Details in /llms.txt.