refs: extract out `refs_create_refdir_stubs()`

For Git to recognize a directory as a Git directory, it requires the directory to contain: 1. 'HEAD' file 2. 'objects/' directory 3. 'refs/' directory Here, #1 and #3 are part of the reference storage mechanism, specifically the files backend. Since then, newer backends such as the reftable backend have moved to using their own path ('reftable/') for storing references. But to ensure Git still recognizes the directory as a Git directory, we create stubs. There are two locations where we create stubs: - In 'refs/reftable-backend.c' when creating the reftable backend. - In 'clone.c' before spawning transport helpers. In a following commit, we'll add another instance. So instead of repeating the code, let's extract out this code to `refs_create_refdir_stubs()` and use it. Signed-off-by: Karthik Nayak <karthik.188@gmail.com> Signed-off-by: Junio C Hamano <gitster@pobox.com>

Karthik Nayak committed Feb 25, 2026 at 10:40 UTC 4ffbb02ee4bde38b4792b93cfba48755b394a130
4 files changed +39 -18
builtin/clone.c
+1 -6
@@ -1225,12 +1225,7 @@ int cmd_clone(int argc,
1225 initialize_repository_version(GIT_HASH_UNKNOWN,
1226 the_repository->ref_storage_format, 1);
1227
1228 - strbuf_addf(&buf, "%s/HEAD", git_dir);
1229 - write_file(buf.buf, "ref: refs/heads/.invalid");
1230 -
1231 - strbuf_reset(&buf);
1232 - strbuf_addf(&buf, "%s/refs", git_dir);
1233 - safe_create_dir(the_repository, buf.buf, 1);
1228 + refs_create_refdir_stubs(the_repository, git_dir, NULL);
1229
1230 /*
1231 * additional config can be injected with -c, make sure it's included
refs.c
+23
@@ -2163,6 +2163,29 @@ const char *refs_resolve_ref_unsafe(struct ref_store *refs,
2163 return NULL;
2164 }
2165
2166 +void refs_create_refdir_stubs(struct repository *repo, const char *refdir,
2167 + const char *refs_heads_content)
2168 +{
2169 + struct strbuf path = STRBUF_INIT;
2170 +
2171 + strbuf_addf(&path, "%s/HEAD", refdir);
2172 + write_file(path.buf, "ref: refs/heads/.invalid");
2173 + adjust_shared_perm(repo, path.buf);
2174 +
2175 + strbuf_reset(&path);
2176 + strbuf_addf(&path, "%s/refs", refdir);
2177 + safe_create_dir(repo, path.buf, 1);
2178 +
2179 + if (refs_heads_content) {
2180 + strbuf_reset(&path);
2181 + strbuf_addf(&path, "%s/refs/heads", refdir);
2182 + write_file(path.buf, "%s", refs_heads_content);
2183 + adjust_shared_perm(repo, path.buf);
2184 + }
2185 +
2186 + strbuf_release(&path);
2187 +}
2188 +
2189 /* backend functions */
2190 int ref_store_create_on_disk(struct ref_store *refs, int flags, struct strbuf *err)
2191 {
refs.h
+13
@@ -1427,4 +1427,17 @@ void ref_iterator_free(struct ref_iterator *ref_iterator);
1427 int do_for_each_ref_iterator(struct ref_iterator *iter,
1428 each_ref_fn fn, void *cb_data);
1429
1430 +/*
1431 + * Git only recognizes a directory as a repository if it contains:
1432 + * - HEAD file
1433 + * - refs/ folder
1434 + * While it is necessary within the files backend, newer backends may not
1435 + * follow the same structure. To go around this, we create stubs as necessary.
1436 + *
1437 + * If provided with a 'refs_heads_content', we create the 'refs/heads/head' file
1438 + * with the provided message.
1439 + */
1440 +void refs_create_refdir_stubs(struct repository *repo, const char *refdir,
1441 + const char *refs_heads_content);
1442 +
1443 #endif /* REFS_H */
refs/reftable-backend.c
+2 -12
@@ -491,18 +491,8 @@ static int reftable_be_create_on_disk(struct ref_store *ref_store,
491 safe_create_dir(the_repository, sb.buf, 1);
492 strbuf_reset(&sb);
493
494 - strbuf_addf(&sb, "%s/HEAD", refs->base.gitdir);
495 - write_file(sb.buf, "ref: refs/heads/.invalid");
496 - adjust_shared_perm(the_repository, sb.buf);
497 - strbuf_reset(&sb);
498 -
499 - strbuf_addf(&sb, "%s/refs", refs->base.gitdir);
500 - safe_create_dir(the_repository, sb.buf, 1);
501 - strbuf_reset(&sb);
502 -
503 - strbuf_addf(&sb, "%s/refs/heads", refs->base.gitdir);
504 - write_file(sb.buf, "this repository uses the reftable format");
505 - adjust_shared_perm(the_repository, sb.buf);
494 + refs_create_refdir_stubs(the_repository, refs->base.gitdir,
495 + "this repository uses the reftable format");
496
497 strbuf_release(&sb);
498 return 0;