The infer_backlink() function initializes a `strbuf` for the inferred backlink and returns the result as a `char*` by detaching the `strbuf`. The next patch 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 accept a pre-allocated `strbuf` for the inferred backlink path, improving efficiency. Signed-off-by: Caleb White <cdwhite3@xxxxx> --- worktree.c | 52 ++++++++++++++++++++++++++-------------------------- 1 file changed, 26 insertions(+), 26 deletions(-) diff --git a/worktree.c b/worktree.c index ec95ea2986107b3bc12d38b0825d7c6e87402bc6..ad60ba0b5843f1676e89b05eca3c82aace5fb49b 100644 --- a/worktree.c +++ b/worktree.c @@ -641,13 +641,15 @@ static int is_main_worktree_path(const char *path) * won't know which <repo>/worktrees/<id>/gitdir to repair. However, we may * be able to infer the gitdir by manually reading /path/to/worktree/.git, * extracting the <id>, and checking if <repo>/worktrees/<id> exists. + * + * Returns -1 on failure and strbuf.len on success. */ -static char *infer_backlink(const char *gitfile) +static int infer_backlink(const char *gitfile, struct strbuf *inferred) { struct strbuf actual = STRBUF_INIT; - struct strbuf inferred = STRBUF_INIT; const char *id; + strbuf_reset(inferred); if (strbuf_read_file(&actual, gitfile, 0) < 0) goto error; if (!starts_with(actual.buf, "gitdir:")) @@ -658,17 +660,16 @@ static char *infer_backlink(const char *gitfile) id++; /* advance past '/' to point at <id> */ if (!*id) goto error; - strbuf_git_common_path(&inferred, the_repository, "worktrees/%s", id); - if (!is_directory(inferred.buf)) + strbuf_git_common_path(inferred, the_repository, "worktrees/%s", id); + if (!is_directory(inferred->buf)) goto error; strbuf_release(&actual); - return strbuf_detach(&inferred, NULL); - + return inferred->len; error: strbuf_release(&actual); - strbuf_release(&inferred); - return NULL; + strbuf_reset(inferred); /* clear invalid path */ + return -1; } /* @@ -680,10 +681,11 @@ void repair_worktree_at_path(const char *path, { struct strbuf dotgit = STRBUF_INIT; struct strbuf realdotgit = STRBUF_INIT; + struct strbuf backlink = STRBUF_INIT; + struct strbuf inferred_backlink = STRBUF_INIT; struct strbuf gitdir = STRBUF_INIT; struct strbuf olddotgit = STRBUF_INIT; - char *backlink = NULL; - char *inferred_backlink = NULL; + char *dotgit_contents = NULL; const char *repair = NULL; int err; @@ -699,23 +701,23 @@ void repair_worktree_at_path(const char *path, goto done; } - inferred_backlink = infer_backlink(realdotgit.buf); - backlink = xstrdup_or_null(read_gitfile_gently(realdotgit.buf, &err)); - if (err == READ_GITFILE_ERR_NOT_A_FILE) { + infer_backlink(realdotgit.buf, &inferred_backlink); + dotgit_contents = xstrdup_or_null(read_gitfile_gently(realdotgit.buf, &err)); + if (dotgit_contents) { + strbuf_addstr(&backlink, dotgit_contents); + } else if (err == READ_GITFILE_ERR_NOT_A_FILE) { fn(1, realdotgit.buf, _("unable to locate repository; .git is not a file"), cb_data); goto done; } else if (err == READ_GITFILE_ERR_NOT_A_REPO) { - if (inferred_backlink) { + if (inferred_backlink.len) { /* * Worktree's .git file does not point at a repository * but we found a .git/worktrees/<id> in this * repository with the same <id> as recorded in the * worktree's .git file so make the worktree point at - * the discovered .git/worktrees/<id>. (Note: backlink - * is already NULL, so no need to free it first.) + * the discovered .git/worktrees/<id>. */ - backlink = inferred_backlink; - inferred_backlink = NULL; + strbuf_swap(&backlink, &inferred_backlink); } else { fn(1, realdotgit.buf, _("unable to locate repository; .git file does not reference a repository"), cb_data); goto done; @@ -743,13 +745,10 @@ void repair_worktree_at_path(const char *path, * in the "copy" repository. In this case, point the "copy" worktree's * .git file at the "copy" repository. */ - if (inferred_backlink && fspathcmp(backlink, inferred_backlink)) { - free(backlink); - backlink = inferred_backlink; - inferred_backlink = NULL; - } + if (inferred_backlink.len && fspathcmp(backlink.buf, inferred_backlink.buf)) + strbuf_swap(&backlink, &inferred_backlink); - strbuf_addf(&gitdir, "%s/gitdir", backlink); + strbuf_addf(&gitdir, "%s/gitdir", backlink.buf); if (strbuf_read_file(&olddotgit, gitdir.buf, 0) < 0) repair = _("gitdir unreadable"); else { @@ -763,9 +762,10 @@ void repair_worktree_at_path(const char *path, write_file(gitdir.buf, "%s", realdotgit.buf); } done: - free(backlink); - free(inferred_backlink); + free(dotgit_contents); strbuf_release(&olddotgit); + strbuf_release(&backlink); + strbuf_release(&inferred_backlink); strbuf_release(&gitdir); strbuf_release(&realdotgit); strbuf_release(&dotgit); -- 2.47.0