8000 worktree: mimic 'git worktree add' behavior. · libgit2/libgit2@3db9ad2 · GitHub
[go: up one dir, main page]

Skip to content

Commit 3db9ad2

Browse files
committed
worktree: mimic 'git worktree add' behavior.
When adding a worktree using 'git worktree add <path>', if a reference named 'refs/heads/$(basename <path>)' already exist, it is checkouted in the worktree. Mimic this behavior in libgit2. Signed-off-by: Gregory Herrero <gregory.herrero@oracle.com>
1 parent 6bd37c3 commit 3db9ad2

File tree

2 files changed

+24
-9
lines changed

2 files changed

+24
-9
lines changed

src/worktree.c

Lines changed: 20 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -278,7 +278,8 @@ int git_worktree_add(git_worktree **out, git_repository *repo,
278278
const char *name, const char *worktree,
279279
const git_worktree_add_options *opts)
280280
{
281-
git_buf gitdir = GIT_BUF_INIT, wddir = GIT_BUF_INIT, buf = GIT_BUF_INIT;
281+
git_buf gitdir = GIT_BUF_INIT, wddir = GIT_BUF_INIT;
282+
git_buf buf = GIT_BUF_INIT, ref_buf = GIT_BUF_INIT;
282283
git_reference *ref = NULL, *head = NULL;
283284
git_commit *commit = NULL;
284285
git_repository *wt = NULL;
@@ -365,12 +366,24 @@ int git_worktree_add(git_worktree **out, git_repository *repo,
365366
if ((err = git_reference_dup(&ref, wtopts.ref)) < 0)
366367
goto out;
367368
} else {
368-
if ((err = git_repository_head(&head, repo)) < 0)
369-
goto out;
370-
if ((err = git_commit_lookup(&commit, repo, &head->target.oid)) < 0)
371-
goto out;
372-
if ((err = git_branch_create(&ref, repo, name, commit, false)) < 0)
369+
if ((err = git_buf_printf(&ref_buf, "refs/heads/%s", name)) < 0)
373370
goto out;
371+
if (!git_reference_lookup(&ref, repo, ref_buf.ptr)) {
372+
if (git_branch_is_checked_out(ref)) {
373+
git_error_set(GIT_ERROR_WORKTREE,
374+
"reference %s is already checked out",
375+
ref_buf.ptr);
376+
err = -1;
377+
goto out;
378+
}
379+
} else {
380+
if ((err = git_repository_head(&head, repo)) < 0)
381+
goto out;
382+
if ((err = git_commit_lookup(&commit, repo, &head->target.oid)) < 0)
383+
goto out;
384+
if ((err = git_branch_create(&ref, repo, name, commit, false)) < 0)
385+
goto out;
386+
}
374387
}
375388

376389
/* Set worktree's HEAD */
@@ -392,6 +405,7 @@ int git_worktree_add(git_worktree **out, git_repository *repo,
392405
git_buf_dispose(&gitdir);
393406
git_buf_dispose(&wddir);
394407
git_buf_dispose(&buf);
408+
git_buf_dispose(&ref_buf);
395409
git_reference_free(ref);
396410
git_reference_free(head);
397411
git_commit_free(commit);

tests/worktree/worktree.c

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -250,12 +250,13 @@ void test_worktree_worktree__init_existing_branch(void)
250250

251251
cl_git_pass(git_repository_head(&head, fixture.repo));
252252
cl_git_pass(git_commit_lookup(&commit, fixture.repo, &head->target.oid));
253-
cl_git_pass(git_branch_create(&branch, fixture.repo, "worktree-new", commit, false));
253+
cl_git_pass(git_branch_create(&branch, fixture.repo, "worktree-new-exist", commit, false));
254254

255-
cl_git_pass(git_buf_joinpath(&path, fixture.repo->workdir, "../worktree-new"));
256-
cl_git_fail(git_worktree_add(&wt, fixture.repo, "worktree-new", path.ptr, NULL));
255+
cl_git_pass(git_buf_joinpath(&path, fixture.repo->workdir, "../worktree-new-exist"));
256+
cl_git_pass(git_worktree_add(&wt, fixture.repo, "worktree-new-exist", path.ptr, NULL));
257257

258258
git_buf_dispose(&path);
259+
git_worktree_free(wt);
259260
git_commit_free(commit);
260261
git_reference_free(head);
261262
git_reference_free(branch);

0 commit comments

Comments
 (0)
0