git/list[1] front-page[2] threads[3] people[4] search[5] about
 

Re: [PATCH 09/16] worktree: return allocated string from `get_worktree_git_dir()`

From
Karthik Nayak <karthik.188@gmail.com>
Date
Feb 7, 2025, 07:15 UTC
Message-ID
<CAOLa=ZSXFqvwFEfJ+cktqzSUf0XMoFC8Z0S0DJHcg4jYN4+DcA@mail.gmail.com>
In-Reply-To
<20250206-b4-pks-path-drop-the-repository-v1-9-4e77f0313206@pks.im>
Patrick Steinhardt <ps@pks.im> writes:
Show 5 quoted lines
> The `get_worktree_git_dir()` function returns a string constant that
> does not need to be free'd by the caller. For `repo_get_git_dir()` and
> `repo_get_common_dir()` this is because we return strings owned by
> `the_repository`.
>

Not sure what the second sentence is signifying here. What relation does `get_worktree_git_dir()` have with `repo_get_git_dir()` and `repo_get_common_dir()`?

Show 5 quoted lines
> But for `git_common_path()` it's a bit less obvious though, because that
> function does end up allocating memory. 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.
>

Now `git_common_path()`, what is binding all these functions together? Sneaking down to the code, it looks like `get_worktree_git_dir()` calls one of the other three functions. Maybe we should start with that?

Show 14 quoted lines
>
> 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.
>
This makes sense.
[snip]
Show 10 quoted lines
> diff --git a/revision.c b/revision.c
> index 474fa1e767..be72f226f3 100644
> --- a/revision.c
> +++ b/revision.c
> @@ -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 *gitdir;
>
Nit: should this be named `wt_gitdir` to stay consistent?
Show 16 quoted lines
>  		if (wt->is_current)
>  			continue; /* current index already taken care of */
>
> +		gitdir = get_worktree_git_dir(wt);
> +
>  		if (read_index_from(&istate,
>  				    worktree_git_path(the_repository, wt, "index"),
> -				    get_worktree_git_dir(wt)) > 0)
> +				    gitdir) > 0)
>  			do_add_index_objects_to_pending(revs, &istate, flags);
> +
>  		discard_index(&istate);
> +		free(gitdir);
>  	}
>  	free_worktrees(worktrees);
>  }
[snip]
Show 10 quoted lines
> diff --git a/worktree.c b/worktree.c
> index 8f4fc10c44..3b94535963 100644
> --- a/worktree.c
> +++ b/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);
Nit: here too, even though it is a pre-existing name. Perhaps it is just
me. So feel free to ignore :)
Show 23 quoted lines
>  	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));
>  }
>

So this is the crux of the patch, we allocate the string for the first two function's return value to ensure that `get_worktree_git_dir()` returns a string which needs to be free'd. Alright!

Previous: Patrick SteinhardtNext: Patrick Steinhardt
Message 21 of 36 in “path: remove dependency on `the_repository`”
  1. 00/16 path: remove dependency on `the_repository`Patrick Steinhardt, Feb 6, 2025
  2. 01/16 path: refactor `repo_common_path()` family of functionsPatrick Steinhardt, Feb 6, 2025
  3. Karthik NayakFeb 6, 2025
  4. Patrick SteinhardtFeb 7, 2025
  5. shejialuoFeb 6, 2025
  6. Patrick SteinhardtFeb 7, 2025
  7. 02/16 path: refactor `repo_git_path()` family of functionsPatrick Steinhardt, Feb 6, 2025
  8. Karthik NayakFeb 6, 2025
  9. Patrick SteinhardtFeb 7, 2025
  10. 03/16 path: refactor `repo_worktree_path()` family of functionsPatrick Steinhardt, Feb 6, 2025
  11. 04/16 submodule: refactor `submodule_to_gitdir()` to accept a repoPatrick Steinhardt, Feb 6, 2025
  12. 05/16 path: refactor `repo_submodule_path()` family of functionsPatrick Steinhardt, Feb 6, 2025
  13. Karthik NayakFeb 6, 2025
  14. Patrick SteinhardtFeb 7, 2025
  15. Karthik NayakFeb 7, 2025
  16. shejialuoFeb 6, 2025
  17. 06/16 path: drop unused `strbuf_git_path()` functionPatrick Steinhardt, Feb 6, 2025
  18. 07/16 path: drop `git_pathdup()` in favor of `repo_git_path()`Patrick Steinhardt, Feb 6, 2025
  19. 08/16 path: drop `git_path_buf()` in favor of `repo_git_path_replace()`Patrick Steinhardt, Feb 6, 2025
  20. 09/16 worktree: return allocated string from `get_worktree_git_dir()`Patrick Steinhardt, Feb 6, 2025
  21. Karthik NayakFeb 7, 2025
  22. Patrick SteinhardtFeb 7, 2025
  23. 10/16 path: drop `git_common_path()` in favor of `repo_common_path()`Patrick Steinhardt, Feb 6, 2025
  24. shejialuoFeb 6, 2025
  25. Patrick SteinhardtFeb 7, 2025
  26. 11/16 rerere: let `rerere_path()` write paths into a caller-provided bufferPatrick Steinhardt, Feb 6, 2025
  27. 12/16 path: drop `git_path()` in favor of `repo_git_path()`Patrick Steinhardt, Feb 6, 2025
  28. shejialuoFeb 6, 2025
  29. Patrick SteinhardtFeb 7, 2025
  30. 13/16 repo-settings: introduce function to clear structPatrick Steinhardt, Feb 6, 2025
  31. 14/16 environment: move access to "core.hooksPath" into repo settingsPatrick Steinhardt, Feb 6, 2025
  32. 15/16 environment: move access to "core.sharedRepository" into repo settingsPatrick Steinhardt, Feb 6, 2025
  33. 16/16 path: adjust last remaining users of `the_repository`Patrick Steinhardt, Feb 6, 2025
  34. shejialuoFeb 6, 2025
  35. Patrick SteinhardtFeb 7, 2025
  36. Karthik NayakFeb 7, 2025

Read the whole thread, see it on lore, or plain text.

$ cat FOOTERMessages come from the public archive at lore.kernel.org/git, fetched every hour. The front page is chosen and written each morning by an AI editor and can be wrong; the threads themselves are the record. About and API. For agents: an MCP server at https://gitlist.dev/mcp, and any thread, story or person page as Markdown by adding .md to its URL (or sending Accept: text/markdown). Details in /llms.txt.