refs: move out stub modification to generic layer

When creating the reftable reference backend on disk, we create stubs to ensure that the directory can be recognized as a Git repository. This is done by calling `refs_create_refdir_stubs()`. Move this to the generic layer as this is needed for all backends excluding from the files backends. In an upcoming commit where we introduce alternate reference backend locations, we'll have to also create stubs in the $GIT_DIR irrespective of the backend being used. This commit builds the base to add that logic. Similarly, move the logic for deletion of stubs to the generic layer. The files backend recursively calls the remove function of the 'packed-backend', here skip calling the generic function since that would try to delete stubs. 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 2a32ac429e9faaecaf1c15c18e7873da5754a8d7
3 files changed +50 -30
refs.c
+45 -2
@@ -2189,12 +2189,55 @@ void refs_create_refdir_stubs(struct repository *repo, const char *refdir,
2189 /* backend functions */
2190 int ref_store_create_on_disk(struct ref_store *refs, int flags, struct strbuf *err)
2191 {
2192 - return refs->be->create_on_disk(refs, flags, err);
2192 + int ret = refs->be->create_on_disk(refs, flags, err);
2193 +
2194 + if (!ret &&
2195 + ref_storage_format_by_name(refs->be->name) != REF_STORAGE_FORMAT_FILES) {
2196 + struct strbuf msg = STRBUF_INIT;
2197 +
2198 + strbuf_addf(&msg, "this repository uses the %s format", refs->be->name);
2199 + refs_create_refdir_stubs(refs->repo, refs->gitdir, msg.buf);
2200 + strbuf_release(&msg);
2201 + }
2202 +
2203 + return ret;
2204 }
2205
2206 int ref_store_remove_on_disk(struct ref_store *refs, struct strbuf *err)
2207 {
2197 - return refs->be->remove_on_disk(refs, err);
2208 + int ret = refs->be->remove_on_disk(refs, err);
2209 +
2210 + if (!ret &&
2211 + ref_storage_format_by_name(refs->be->name) != REF_STORAGE_FORMAT_FILES) {
2212 + struct strbuf sb = STRBUF_INIT;
2213 +
2214 + strbuf_addf(&sb, "%s/HEAD", refs->gitdir);
2215 + if (unlink(sb.buf) < 0) {
2216 + strbuf_addf(err, "could not delete stub HEAD: %s",
2217 + strerror(errno));
2218 + ret = -1;
2219 + }
2220 + strbuf_reset(&sb);
2221 +
2222 + strbuf_addf(&sb, "%s/refs/heads", refs->gitdir);
2223 + if (unlink(sb.buf) < 0) {
2224 + strbuf_addf(err, "could not delete stub heads: %s",
2225 + strerror(errno));
2226 + ret = -1;
2227 + }
2228 + strbuf_reset(&sb);
2229 +
2230 + strbuf_addf(&sb, "%s/refs", refs->gitdir);
2231 + if (rmdir(sb.buf) < 0) {
2232 + strbuf_addf(err, "could not delete refs directory: %s",
2233 + strerror(errno));
2234 + ret = -1;
2235 + }
2236 +
2237 + strbuf_release(&sb);
2238 + }
2239 +
2240 + return ret;
2241 }
2242
2243 int repo_resolve_gitlink_ref(struct repository *r,
refs/files-backend.c
+5 -1
@@ -3700,7 +3700,11 @@ static int files_ref_store_remove_on_disk(struct ref_store *ref_store,
3700 if (for_each_root_ref(refs, remove_one_root_ref, &data) < 0)
3701 ret = -1;
3702
3703 - if (ref_store_remove_on_disk(refs->packed_ref_store, err) < 0)
3703 + /*
3704 + * Directly access the cleanup functions for packed-refs as the generic function
3705 + * would try to clear stubs which isn't required for the files backend.
3706 + */
3707 + if (refs->packed_ref_store->be->remove_on_disk(refs->packed_ref_store, err) < 0)
3708 ret = -1;
3709
3710 strbuf_release(&sb);
refs/reftable-backend.c
-27
@@ -491,9 +491,6 @@ 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 - refs_create_refdir_stubs(the_repository, refs->base.gitdir,
495 - "this repository uses the reftable format");
496 -
494 strbuf_release(&sb);
495 return 0;
496 }
@@ -519,30 +516,6 @@ static int reftable_be_remove_on_disk(struct ref_store *ref_store,
516 strerror(errno));
517 ret = -1;
518 }
522 - strbuf_reset(&sb);
523 -
524 - strbuf_addf(&sb, "%s/HEAD", refs->base.gitdir);
525 - if (unlink(sb.buf) < 0) {
526 - strbuf_addf(err, "could not delete stub HEAD: %s",
527 - strerror(errno));
528 - ret = -1;
529 - }
530 - strbuf_reset(&sb);
531 -
532 - strbuf_addf(&sb, "%s/refs/heads", refs->base.gitdir);
533 - if (unlink(sb.buf) < 0) {
534 - strbuf_addf(err, "could not delete stub heads: %s",
535 - strerror(errno));
536 - ret = -1;
537 - }
538 - strbuf_reset(&sb);
539 -
540 - strbuf_addf(&sb, "%s/refs", refs->base.gitdir);
541 - if (rmdir(sb.buf) < 0) {
542 - strbuf_addf(err, "could not delete refs directory: %s",
543 - strerror(errno));
544 - ret = -1;
545 - }
519
520 strbuf_release(&sb);
521 return ret;