diff options
| author | Patrick Steinhardt <ps@pks.im> | 2025-02-07 12:03:34 +0100 |
|---|---|---|
| committer | Junio C Hamano <gitster@pobox.com> | 2025-02-07 09:59:23 -0800 |
| commit | 8e4710f011dce286d24838fdafd5ce52cfac5285 (patch) | |
| tree | 359727495fa9af9d22dcd7606d677d7f13ee5f61 /builtin | |
| parent | path: drop `git_path_buf()` in favor of `repo_git_path_replace()` (diff) | |
| download | git-8e4710f011dce286d24838fdafd5ce52cfac5285.tar.gz git-8e4710f011dce286d24838fdafd5ce52cfac5285.zip | |
worktree: return allocated string from `get_worktree_git_dir()`
The `get_worktree_git_dir()` function returns a string constant that
does not need to be free'd by the caller. This string is computed for
three different cases:
- If we don't have a worktree we return a path into the Git directory.
The returned string is owned by `the_repository`, so there is no
need for the caller to free it.
- If we have a worktree, but no worktree ID then the caller requests
the main worktree. In this case we return a path into the common
directory, which again is owned by `the_repository` and thus does
not need to be free'd.
- In the third case, where we have an actual worktree, we compute the
path relative to "$GIT_COMMON_DIR/worktrees/". This string does not
need to be released either, even though `git_common_path()` ends up
allocating memory. But this doesn't result in a memory leak either
because we write into a buffer returned by `get_pathname()`, which
returns one out of four static buffers.
We're about to drop `git_common_path()` in favor of `repo_common_path()`,
which doesn't use the same mechanism but instead returns an allocated
string owned by the caller. While we could adapt `get_worktree_git_dir()`
to also use `get_pathname()` and print the derived common path into that
buffer, the whole schema feels a lot like premature optimization in this
context. There are some callsites where we call `get_worktree_git_dir()`
in a loop that iterates through all worktrees. But none of these loops
seem to be even remotely in the hot path, so saving a single allocation
there does not feel worth it.
Refactor the function to instead consistently return an allocated path
so that we can start using `repo_common_path()` in a subsequent commit.
Signed-off-by: Patrick Steinhardt <ps@pks.im>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
Diffstat (limited to 'builtin')
| -rw-r--r-- | builtin/fsck.c | 8 | ||||
| -rw-r--r-- | builtin/receive-pack.c | 4 | ||||
| -rw-r--r-- | builtin/worktree.c | 10 |
3 files changed, 17 insertions, 5 deletions
diff --git a/builtin/fsck.c b/builtin/fsck.c index c12203e012..eea1d43647 100644 --- a/builtin/fsck.c +++ b/builtin/fsck.c @@ -1057,7 +1057,7 @@ int cmd_fsck(int argc, struct worktree *wt = *p; struct index_state istate = INDEX_STATE_INIT(the_repository); - char *path; + char *path, *wt_gitdir; /* * Make a copy since the buffer is reusable @@ -1065,9 +1065,13 @@ int cmd_fsck(int argc, * while we're examining the index. */ path = xstrdup(worktree_git_path(the_repository, wt, "index")); - read_index_from(&istate, path, get_worktree_git_dir(wt)); + wt_gitdir = get_worktree_git_dir(wt); + + read_index_from(&istate, path, wt_gitdir); fsck_index(&istate, path, wt->is_current); + discard_index(&istate); + free(wt_gitdir); free(path); } free_worktrees(worktrees); diff --git a/builtin/receive-pack.c b/builtin/receive-pack.c index b7ea774609..d65a441f32 100644 --- a/builtin/receive-pack.c +++ b/builtin/receive-pack.c @@ -1435,7 +1435,8 @@ static const char *push_to_checkout(unsigned char *hash, static const char *update_worktree(unsigned char *sha1, const struct worktree *worktree) { - const char *retval, *git_dir; + const char *retval; + char *git_dir; struct strvec env = STRVEC_INIT; int invoked_hook; @@ -1453,6 +1454,7 @@ static const char *update_worktree(unsigned char *sha1, const struct worktree *w retval = push_to_deploy(sha1, &env, worktree->path); strvec_clear(&env); + free(git_dir); return retval; } diff --git a/builtin/worktree.c b/builtin/worktree.c index 7959b10d26..2cea9441a6 100644 --- a/builtin/worktree.c +++ b/builtin/worktree.c @@ -657,8 +657,9 @@ static int can_use_local_refs(const struct add_opts *opts) if (!opts->quiet) { struct strbuf path = STRBUF_INIT; struct strbuf contents = STRBUF_INIT; + char *wt_gitdir = get_worktree_git_dir(NULL); - strbuf_add_real_path(&path, get_worktree_git_dir(NULL)); + strbuf_add_real_path(&path, wt_gitdir); strbuf_addstr(&path, "/HEAD"); strbuf_read_file(&contents, path.buf, 64); strbuf_stripspace(&contents, NULL); @@ -670,6 +671,7 @@ static int can_use_local_refs(const struct add_opts *opts) path.buf, contents.buf); strbuf_release(&path); strbuf_release(&contents); + free(wt_gitdir); } return 1; } @@ -1157,6 +1159,9 @@ static void validate_no_submodules(const struct worktree *wt) struct index_state istate = INDEX_STATE_INIT(the_repository); struct strbuf path = STRBUF_INIT; int i, found_submodules = 0; + char *wt_gitdir; + + wt_gitdir = get_worktree_git_dir(wt); if (is_directory(worktree_git_path(the_repository, wt, "modules"))) { /* @@ -1166,7 +1171,7 @@ static void validate_no_submodules(const struct worktree *wt) */ found_submodules = 1; } else if (read_index_from(&istate, worktree_git_path(the_repository, wt, "index"), - get_worktree_git_dir(wt)) > 0) { + wt_gitdir) > 0) { for (i = 0; i < istate.cache_nr; i++) { struct cache_entry *ce = istate.cache[i]; int err; @@ -1185,6 +1190,7 @@ static void validate_no_submodules(const struct worktree *wt) } discard_index(&istate); strbuf_release(&path); + free(wt_gitdir); if (found_submodules) die(_("working trees containing submodules cannot be moved or removed")); |
