Hi, this is the second version of my patch series that refactors the initialization of worktree refdbs to use the refs API. Changes compared to v1: - Improved commit messages. - This series is now based on `ps/refstorage-extension`, 1b2234079b (t9500: write "extensions.refstorage" into config, 2023-12-29). While there is no functional dependency between those series, merging both topics causes a merge conflict. Patrick Patrick Steinhardt (6): refs: prepare `refs_init_db()` for initializing worktree refs setup: move creation of "refs/" into the files backend refs/files: skip creation of "refs/{heads,tags}" for worktrees builtin/worktree: move setup of commondir file earlier worktree: expose interface to look up worktree by name builtin/worktree: create refdb via ref backend builtin/worktree.c | 53 ++++++++++++++++++++----------------------- refs.c | 6 ++--- refs.h | 4 +++- refs/debug.c | 4 ++-- refs/files-backend.c | 37 +++++++++++++++++++++++++----- refs/packed-backend.c | 1 + refs/refs-internal.h | 4 +++- setup.c | 17 +------------- worktree.c | 27 +++++++++++++--------- worktree.h | 12 ++++++++++ 10 files changed, 96 insertions(+), 69 deletions(-) Range-diff against v1: 1: 6cb4e0a99f ! 1: a4894b3e15 refs: prepare `refs_init_db()` for initializing worktree refs @@ refs/refs-internal.h: typedef struct ref_store *ref_store_init_fn(struct reposit struct ref_transaction *transaction, ## setup.c ## -@@ setup.c: void create_reference_database(const char *initial_branch, int quiet) - safe_create_dir(git_path("refs"), 1); +@@ setup.c: void create_reference_database(unsigned int ref_storage_format, adjust_shared_perm(git_path("refs")); + repo_set_ref_storage_format(the_repository, ref_storage_format); - if (refs_init_db(&err)) + if (refs_init_db(get_main_ref_store(the_repository), 0, &err)) die("failed to set up refs db: %s", err.buf); 2: ae013eaa4a ! 2: f500db51c2 setup: move creation of "refs/" into the files backend @@ Commit message seems a lot more sensible to have it this way round than to require callers to create the directory themselves. + An alternative to this would be to create "refs/" in `refs_init_db()` + directly. This feels conceptually unclean though as the creation of the + refdb is now cluttered across different callsites. Furthermore, both the + "files" and the upcoming "reftable" backend write backend-specific data + into the "refs/" directory anyway, so splitting up this logic would only + make it harder to reason about. + Signed-off-by: Patrick Steinhardt <ps@xxxxxx> ## refs/files-backend.c ## @@ refs/files-backend.c: static int files_init_db(struct ref_store *ref_store, ## setup.c ## -@@ setup.c: void create_reference_database(const char *initial_branch, int quiet) +@@ setup.c: void create_reference_database(unsigned int ref_storage_format, struct strbuf err = STRBUF_INIT; int reinit = is_reinit(); @@ setup.c: void create_reference_database(const char *initial_branch, int quiet) - safe_create_dir(git_path("refs"), 1); - adjust_shared_perm(git_path("refs")); - + repo_set_ref_storage_format(the_repository, ref_storage_format); if (refs_init_db(get_main_ref_store(the_repository), 0, &err)) die("failed to set up refs db: %s", err.buf); - 3: 3cf6ceb274 ! 3: 9e99efeaa3 refs/files: skip creation of "refs/{heads,tags}" for worktrees @@ Commit message The files ref backend will create both "refs/heads" and "refs/tags" in the Git directory. While this logic makes sense for normal repositories, - it does not fo worktrees because those refs are "common" refs that would - always be contained in the main repository's ref database. + it does not for worktrees because those refs are "common" refs that + would always be contained in the main repository's ref database. Introduce a new flag telling the backend that it is expected to create a per-worktree ref database and skip creation of these dirs in the files 4: 1a6337fc51 = 4: f2eb020288 builtin/worktree: move setup of commondir file earlier 5: f344a915e9 ! 5: 5525a9f9c2 worktree: expose interface to look up worktree by name @@ worktree.c free (worktrees); } -@@ worktree.c: static struct worktree *get_main_worktree(void) +@@ worktree.c: static struct worktree *get_main_worktree(int skip_reading_head) return worktree; } --static struct worktree *get_linked_worktree(const char *id) -+struct worktree *get_linked_worktree(const char *id) +-static struct worktree *get_linked_worktree(const char *id, +- int skip_reading_head) ++struct worktree *get_linked_worktree(const char *id, ++ int skip_reading_head) { struct worktree *worktree = NULL; struct strbuf path = STRBUF_INIT; @@ worktree.h: struct worktree *find_worktree(struct worktree **list, + * Look up the worktree corresponding to `id`, or NULL of no such worktree + * exists. + */ -+struct worktree *get_linked_worktree(const char *id); ++struct worktree *get_linked_worktree(const char *id, ++ int skip_reading_head); + /* * Return the worktree corresponding to `path`, or NULL if no such worktree 6: aae969301f ! 6: 240dc40de1 builtin/worktree: create refdb via ref backend @@ builtin/worktree.c: static int add_worktree(const char *path, const char *refnam - strbuf_reset(&sb); - strbuf_addf(&sb, "%s/HEAD", sb_repo.buf); - write_file(sb.buf, "%s", oid_to_hex(null_oid())); -+ wt = get_linked_worktree(name); ++ wt = get_linked_worktree(name, 1); + if (!wt) { + ret = error(_("could not find created worktree '%s'"), name); + goto done; base-commit: 1b2234079b24da99dd78e4ce4bfe338a2a841aed -- 2.43.GIT
Attachment:
signature.asc
Description: PGP signature