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>maint
parent
3859e39659
commit
8e4710f011
7
branch.c
7
branch.c
|
@ -397,7 +397,7 @@ static void prepare_checked_out_branches(void)
|
|||
worktrees = get_worktrees();
|
||||
|
||||
while (worktrees[i]) {
|
||||
char *old;
|
||||
char *old, *wt_gitdir;
|
||||
struct wt_status_state state = { 0 };
|
||||
struct worktree *wt = worktrees[i++];
|
||||
struct string_list update_refs = STRING_LIST_INIT_DUP;
|
||||
|
@ -437,7 +437,8 @@ static void prepare_checked_out_branches(void)
|
|||
}
|
||||
wt_status_state_free_buffers(&state);
|
||||
|
||||
if (!sequencer_get_update_refs_state(get_worktree_git_dir(wt),
|
||||
wt_gitdir = get_worktree_git_dir(wt);
|
||||
if (!sequencer_get_update_refs_state(wt_gitdir,
|
||||
&update_refs)) {
|
||||
struct string_list_item *item;
|
||||
for_each_string_list_item(item, &update_refs) {
|
||||
|
@ -448,6 +449,8 @@ static void prepare_checked_out_branches(void)
|
|||
}
|
||||
string_list_clear(&update_refs, 1);
|
||||
}
|
||||
|
||||
free(wt_gitdir);
|
||||
}
|
||||
|
||||
free_worktrees(worktrees);
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
||||
|
|
|
@ -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"));
|
||||
|
|
|
@ -65,8 +65,10 @@ static void add_rebase_files(struct rev_info *revs)
|
|||
struct worktree **worktrees = get_worktrees();
|
||||
|
||||
for (struct worktree **wt = worktrees; *wt; wt++) {
|
||||
char *wt_gitdir = get_worktree_git_dir(*wt);
|
||||
|
||||
strbuf_reset(&buf);
|
||||
strbuf_addstr(&buf, get_worktree_git_dir(*wt));
|
||||
strbuf_addstr(&buf, wt_gitdir);
|
||||
strbuf_complete(&buf, '/');
|
||||
len = buf.len;
|
||||
for (size_t i = 0; i < ARRAY_SIZE(path); i++) {
|
||||
|
@ -74,6 +76,8 @@ static void add_rebase_files(struct rev_info *revs)
|
|||
strbuf_addstr(&buf, path[i]);
|
||||
add_one_file(buf.buf, revs);
|
||||
}
|
||||
|
||||
free(wt_gitdir);
|
||||
}
|
||||
strbuf_release(&buf);
|
||||
free_worktrees(worktrees);
|
||||
|
|
|
@ -1874,15 +1874,20 @@ void add_index_objects_to_pending(struct rev_info *revs, unsigned int flags)
|
|||
for (p = worktrees; *p; p++) {
|
||||
struct worktree *wt = *p;
|
||||
struct index_state istate = INDEX_STATE_INIT(revs->repo);
|
||||
char *wt_gitdir;
|
||||
|
||||
if (wt->is_current)
|
||||
continue; /* current index already taken care of */
|
||||
|
||||
wt_gitdir = get_worktree_git_dir(wt);
|
||||
|
||||
if (read_index_from(&istate,
|
||||
worktree_git_path(the_repository, wt, "index"),
|
||||
get_worktree_git_dir(wt)) > 0)
|
||||
wt_gitdir) > 0)
|
||||
do_add_index_objects_to_pending(revs, &istate, flags);
|
||||
|
||||
discard_index(&istate);
|
||||
free(wt_gitdir);
|
||||
}
|
||||
free_worktrees(worktrees);
|
||||
}
|
||||
|
|
11
worktree.c
11
worktree.c
|
@ -59,8 +59,9 @@ static void add_head_info(struct worktree *wt)
|
|||
static int is_current_worktree(struct worktree *wt)
|
||||
{
|
||||
char *git_dir = absolute_pathdup(repo_get_git_dir(the_repository));
|
||||
const char *wt_git_dir = get_worktree_git_dir(wt);
|
||||
char *wt_git_dir = get_worktree_git_dir(wt);
|
||||
int is_current = !fspathcmp(git_dir, absolute_path(wt_git_dir));
|
||||
free(wt_git_dir);
|
||||
free(git_dir);
|
||||
return is_current;
|
||||
}
|
||||
|
@ -175,14 +176,14 @@ struct worktree **get_worktrees(void)
|
|||
return get_worktrees_internal(0);
|
||||
}
|
||||
|
||||
const char *get_worktree_git_dir(const struct worktree *wt)
|
||||
char *get_worktree_git_dir(const struct worktree *wt)
|
||||
{
|
||||
if (!wt)
|
||||
return repo_get_git_dir(the_repository);
|
||||
return xstrdup(repo_get_git_dir(the_repository));
|
||||
else if (!wt->id)
|
||||
return repo_get_common_dir(the_repository);
|
||||
return xstrdup(repo_get_common_dir(the_repository));
|
||||
else
|
||||
return git_common_path("worktrees/%s", wt->id);
|
||||
return xstrdup(git_common_path("worktrees/%s", wt->id));
|
||||
}
|
||||
|
||||
static struct worktree *find_worktree_by_suffix(struct worktree **list,
|
||||
|
|
|
@ -39,7 +39,7 @@ int submodule_uses_worktrees(const char *path);
|
|||
* Return git dir of the worktree. Note that the path may be relative.
|
||||
* If wt is NULL, git dir of current worktree is returned.
|
||||
*/
|
||||
const char *get_worktree_git_dir(const struct worktree *wt);
|
||||
char *get_worktree_git_dir(const struct worktree *wt);
|
||||
|
||||
/*
|
||||
* Search for the worktree identified unambiguously by `arg` -- typically
|
||||
|
|
Loading…
Reference in New Issue