worktree: refactor infer_backlink() to use *strbuf
This lays the groundwork for the next patch, which needs the backlink returned from infer_backlink() as a `strbuf`. It seemed inefficient to convert from `strbuf` to `char*` and back to `strbuf` again. This refactors infer_backlink() to return an integer result and use a pre-allocated `strbuf` for the inferred backlink path, replacing the previous `char*` return type and improving efficiency. Signed-off-by: Caleb White <cdwhite3@pm.me> Signed-off-by: Junio C Hamano <gitster@pobox.com>
Caleb White committed
Oct 7, 2024 at 22:12 UTC
bb4a883584ab13500921325617e022142633e53a
1 file changed
+24
-24
worktree.c
+24
-24
@@ -642,10 +642,9 @@ static int is_main_worktree_path(const char *path)
642
* be able to infer the gitdir by manually reading /path/to/worktree/.git,
643
* extracting the <id>, and checking if <repo>/worktrees/<id> exists.
644
*/
645
-static char *infer_backlink(const char *gitfile)
645
+static int infer_backlink(const char *gitfile, struct strbuf *inferred)
646
{
647
struct strbuf actual = STRBUF_INIT;
648
- struct strbuf inferred = STRBUF_INIT;
648
const char *id;
649
650
if (strbuf_read_file(&actual, gitfile, 0) < 0)
@@ -658,17 +657,18 @@ static char *infer_backlink(const char *gitfile)
657
id++; /* advance past '/' to point at <id> */
658
if (!*id)
659
goto error;
661
- strbuf_git_common_path(&inferred, the_repository, "worktrees/%s", id);
662
- if (!is_directory(inferred.buf))
660
+ strbuf_reset(inferred);
661
+ strbuf_git_common_path(inferred, the_repository, "worktrees/%s", id);
662
+ if (!is_directory(inferred->buf))
663
goto error;
664
665
strbuf_release(&actual);
666
- return strbuf_detach(&inferred, NULL);
666
+ return 1;
667
668
error:
669
strbuf_release(&actual);
670
- strbuf_release(&inferred);
671
- return NULL;
670
+ strbuf_reset(inferred); /* clear invalid path */
671
+ return 0;
672
}
673
674
/*
@@ -680,10 +680,11 @@ void repair_worktree_at_path(const char *path,
680
{
681
struct strbuf dotgit = STRBUF_INIT;
682
struct strbuf realdotgit = STRBUF_INIT;
683
+ struct strbuf backlink = STRBUF_INIT;
684
+ struct strbuf inferred_backlink = STRBUF_INIT;
685
struct strbuf gitdir = STRBUF_INIT;
686
struct strbuf olddotgit = STRBUF_INIT;
685
- char *backlink = NULL;
686
- char *inferred_backlink = NULL;
687
+ char *dotgit_contents = NULL;
688
const char *repair = NULL;
689
int err;
690
@@ -699,23 +700,23 @@ void repair_worktree_at_path(const char *path,
700
goto done;
701
}
702
702
- inferred_backlink = infer_backlink(realdotgit.buf);
703
- backlink = xstrdup_or_null(read_gitfile_gently(realdotgit.buf, &err));
704
- if (err == READ_GITFILE_ERR_NOT_A_FILE) {
703
+ infer_backlink(realdotgit.buf, &inferred_backlink);
704
+ dotgit_contents = xstrdup_or_null(read_gitfile_gently(realdotgit.buf, &err));
705
+ if (dotgit_contents) {
706
+ strbuf_addstr(&backlink, dotgit_contents);
707
+ } else if (err == READ_GITFILE_ERR_NOT_A_FILE) {
708
fn(1, realdotgit.buf, _("unable to locate repository; .git is not a file"), cb_data);
709
goto done;
710
} else if (err == READ_GITFILE_ERR_NOT_A_REPO) {
708
- if (inferred_backlink) {
711
+ if (inferred_backlink.len) {
712
/*
713
* Worktree's .git file does not point at a repository
714
* but we found a .git/worktrees/<id> in this
715
* repository with the same <id> as recorded in the
716
* worktree's .git file so make the worktree point at
714
- * the discovered .git/worktrees/<id>. (Note: backlink
715
- * is already NULL, so no need to free it first.)
717
+ * the discovered .git/worktrees/<id>.
718
*/
717
- backlink = inferred_backlink;
718
- inferred_backlink = NULL;
719
+ strbuf_swap(&backlink, &inferred_backlink);
720
} else {
721
fn(1, realdotgit.buf, _("unable to locate repository; .git file does not reference a repository"), cb_data);
722
goto done;
@@ -743,13 +744,11 @@ void repair_worktree_at_path(const char *path,
744
* in the "copy" repository. In this case, point the "copy" worktree's
745
* .git file at the "copy" repository.
746
*/
746
- if (inferred_backlink && fspathcmp(backlink, inferred_backlink)) {
747
- free(backlink);
748
- backlink = inferred_backlink;
749
- inferred_backlink = NULL;
747
+ if (inferred_backlink.len && fspathcmp(backlink.buf, inferred_backlink.buf)) {
748
+ strbuf_swap(&backlink, &inferred_backlink);
749
}
750
752
- strbuf_addf(&gitdir, "%s/gitdir", backlink);
751
+ strbuf_addf(&gitdir, "%s/gitdir", backlink.buf);
752
if (strbuf_read_file(&olddotgit, gitdir.buf, 0) < 0)
753
repair = _("gitdir unreadable");
754
else {
@@ -763,9 +762,10 @@ void repair_worktree_at_path(const char *path,
762
write_file(gitdir.buf, "%s", realdotgit.buf);
763
}
764
done:
766
- free(backlink);
767
- free(inferred_backlink);
765
+ free(dotgit_contents);
766
strbuf_release(&olddotgit);
767
+ strbuf_release(&backlink);
768
+ strbuf_release(&inferred_backlink);
769
strbuf_release(&gitdir);
770
strbuf_release(&realdotgit);
771
strbuf_release(&dotgit);