Skip to content

Commit 8f4c00d

Browse files
pks-tgitster
authored andcommitted
builtin/worktree: create refdb via ref backend
When creating a worktree we create the worktree's ref database manually by first writing a "HEAD" file so that the directory is recognized as a Git repository by other commands, and then running git-update-ref(1) or git-symbolic-ref(1) to write the actual value. But while this is fine for the files backend, this logic simply assumes too much about how the ref backend works and will leave behind an invalid ref database once any other ref backend lands. Refactor the code to instead use `refs_init_db()` to initialize the ref database so that git-worktree(1) itself does not need to know about how to initialize it. This will allow future ref backends to customize how the per-worktree ref database is set up. Furthermore, as we now already have a worktree ref store around, we can also avoid spawning external commands to write the HEAD reference and instead use the refs API to do so. Note that we do not have an equivalent to passing the `--quiet` flag to git-symbolic-ref(1) as we did before. This flag does not have an effect anyway though, as git-symbolic-ref(1) only honors it when reading a symref, but never when writing one. Signed-off-by: Patrick Steinhardt <[email protected]> Signed-off-by: Junio C Hamano <[email protected]>
1 parent b8a846b commit 8f4c00d

File tree

1 file changed

+22
-26
lines changed

1 file changed

+22
-26
lines changed

builtin/worktree.c

Lines changed: 22 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -416,15 +416,15 @@ static int add_worktree(const char *path, const char *refname,
416416
struct strbuf sb_git = STRBUF_INIT, sb_repo = STRBUF_INIT;
417417
struct strbuf sb = STRBUF_INIT, realpath = STRBUF_INIT;
418418
const char *name;
419-
struct child_process cp = CHILD_PROCESS_INIT;
420419
struct strvec child_env = STRVEC_INIT;
421420
unsigned int counter = 0;
422421
int len, ret;
423422
struct strbuf symref = STRBUF_INIT;
424423
struct commit *commit = NULL;
425424
int is_branch = 0;
426425
struct strbuf sb_name = STRBUF_INIT;
427-
struct worktree **worktrees;
426+
struct worktree **worktrees, *wt = NULL;
427+
struct ref_store *wt_refs;
428428

429429
worktrees = get_worktrees();
430430
check_candidate_path(path, opts->force, worktrees, "add");
@@ -500,15 +500,26 @@ static int add_worktree(const char *path, const char *refname,
500500
write_file(sb.buf, "../..");
501501

502502
/*
503-
* This is to keep resolve_ref() happy. We need a valid HEAD
504-
* or is_git_directory() will reject the directory. Any value which
505-
* looks like an object ID will do since it will be immediately
506-
* replaced by the symbolic-ref or update-ref invocation in the new
507-
* worktree.
503+
* Set up the ref store of the worktree and create the HEAD reference.
508504
*/
509-
strbuf_reset(&sb);
510-
strbuf_addf(&sb, "%s/HEAD", sb_repo.buf);
511-
write_file(sb.buf, "%s", oid_to_hex(null_oid()));
505+
wt = get_linked_worktree(name, 1);
506+
if (!wt) {
507+
ret = error(_("could not find created worktree '%s'"), name);
508+
goto done;
509+
}
510+
wt_refs = get_worktree_ref_store(wt);
511+
512+
ret = refs_init_db(wt_refs, REFS_INIT_DB_IS_WORKTREE, &sb);
513+
if (ret)
514+
goto done;
515+
516+
if (!is_branch && commit)
517+
ret = refs_update_ref(wt_refs, NULL, "HEAD", &commit->object.oid,
518+
NULL, 0, UPDATE_REFS_MSG_ON_ERR);
519+
else
520+
ret = refs_create_symref(wt_refs, "HEAD", symref.buf, NULL);
521+
if (ret)
522+
goto done;
512523

513524
/*
514525
* If the current worktree has sparse-checkout enabled, then copy
@@ -527,22 +538,6 @@ static int add_worktree(const char *path, const char *refname,
527538

528539
strvec_pushf(&child_env, "%s=%s", GIT_DIR_ENVIRONMENT, sb_git.buf);
529540
strvec_pushf(&child_env, "%s=%s", GIT_WORK_TREE_ENVIRONMENT, path);
530-
cp.git_cmd = 1;
531-
532-
if (!is_branch && commit) {
533-
strvec_pushl(&cp.args, "update-ref", "HEAD",
534-
oid_to_hex(&commit->object.oid), NULL);
535-
} else {
536-
strvec_pushl(&cp.args, "symbolic-ref", "HEAD",
537-
symref.buf, NULL);
538-
if (opts->quiet)
539-
strvec_push(&cp.args, "--quiet");
540-
}
541-
542-
strvec_pushv(&cp.env, child_env.v);
543-
ret = run_command(&cp);
544-
if (ret)
545-
goto done;
546541

547542
if (opts->orphan &&
548543
(ret = make_worktree_orphan(refname, opts, &child_env)))
@@ -588,6 +583,7 @@ static int add_worktree(const char *path, const char *refname,
588583
strbuf_release(&sb_git);
589584
strbuf_release(&sb_name);
590585
strbuf_release(&realpath);
586+
free_worktree(wt);
591587
return ret;
592588
}
593589

0 commit comments

Comments
 (0)