path: drop `git_common_path()` in favor of `repo_common_path()`

Remove `git_common_path()` in favor of the `repo_common_path()` family of functions, which makes the implicit dependency on `the_repository` go away. Note that `git_common_path()` used to return a string allocated via `get_pathname()`, which uses a rotating set of statically allocated buffers. Consequently, callers didn't have to free the returned string. The same isn't true for `repo_common_path()`, so we also have to add logic to free the returned strings. This refactoring also allows us to remove `repo_common_pathv()` from the public interface. Signed-off-by: Patrick Steinhardt <ps@pks.im> Signed-off-by: Junio C Hamano <gitster@pobox.com>

Patrick Steinhardt committed Feb 7, 2025 at 12:03 UTC 07242c2a5afb2a633feb110b1aa74e2adcc37575
4 files changed +40 -35
builtin/worktree.c
+12 -4
@@ -151,7 +151,7 @@ static int delete_git_dir(const char *id)
151 struct strbuf sb = STRBUF_INIT;
152 int ret;
153
154 - strbuf_addstr(&sb, git_common_path("worktrees/%s", id));
154 + repo_common_path_append(the_repository, &sb, "worktrees/%s", id);
155 ret = remove_dir_recursively(&sb, 0);
156 if (ret < 0 && errno == ENOTDIR)
157 ret = unlink(sb.buf);
@@ -1102,6 +1102,7 @@ static int lock_worktree(int ac, const char **av, const char *prefix,
1102 OPT_END()
1103 };
1104 struct worktree **worktrees, *wt;
1105 + char *path;
1106
1107 ac = parse_options(ac, av, prefix, options, git_worktree_lock_usage, 0);
1108 if (ac != 1)
@@ -1122,9 +1123,11 @@ static int lock_worktree(int ac, const char **av, const char *prefix,
1123 die(_("'%s' is already locked"), av[0]);
1124 }
1125
1125 - write_file(git_common_path("worktrees/%s/locked", wt->id),
1126 - "%s", reason);
1126 + path = repo_common_path(the_repository, "worktrees/%s/locked", wt->id);
1127 + write_file(path, "%s", reason);
1128 +
1129 free_worktrees(worktrees);
1130 + free(path);
1131 return 0;
1132 }
1133
@@ -1135,6 +1138,7 @@ static int unlock_worktree(int ac, const char **av, const char *prefix,
1138 OPT_END()
1139 };
1140 struct worktree **worktrees, *wt;
1141 + char *path;
1142 int ret;
1143
1144 ac = parse_options(ac, av, prefix, options, git_worktree_unlock_usage, 0);
@@ -1149,8 +1153,12 @@ static int unlock_worktree(int ac, const char **av, const char *prefix,
1153 die(_("The main working tree cannot be locked or unlocked"));
1154 if (!worktree_lock_reason(wt))
1155 die(_("'%s' is not locked"), av[0]);
1152 - ret = unlink_or_warn(git_common_path("worktrees/%s/locked", wt->id));
1156 +
1157 + path = repo_common_path(the_repository, "worktrees/%s/locked", wt->id);
1158 + ret = unlink_or_warn(path);
1159 +
1160 free_worktrees(worktrees);
1161 + free(path);
1162 return ret;
1163 }
1164
path.c
+4 -4
@@ -634,10 +634,10 @@ const char *repo_submodule_path_replace(struct repository *repo,
634 return buf->buf;
635 }
636
637 -void repo_common_pathv(const struct repository *repo,
638 - struct strbuf *sb,
639 - const char *fmt,
640 - va_list args)
637 +static void repo_common_pathv(const struct repository *repo,
638 + struct strbuf *sb,
639 + const char *fmt,
640 + va_list args)
641 {
642 strbuf_addstr(sb, repo->commondir);
643 if (sb->len && !is_dir_sep(sb->buf[sb->len - 1]))
path.h
-19
@@ -233,29 +233,10 @@ struct strbuf *get_pathname(void);
233 # include "repository.h"
234
235 /* Internal implementation details that should not be used. */
236 -void repo_common_pathv(const struct repository *repo,
237 - struct strbuf *buf,
238 - const char *fmt,
239 - va_list args);
236 void repo_git_pathv(const struct repository *repo,
237 const struct worktree *wt, struct strbuf *buf,
238 const char *fmt, va_list args);
239
244 -/*
245 - * Return a statically allocated path into the main repository's
246 - * (the_repository) common git directory.
247 - */
248 -__attribute__((format (printf, 1, 2)))
249 -static inline const char *git_common_path(const char *fmt, ...)
250 -{
251 - struct strbuf *pathname = get_pathname();
252 - va_list args;
253 - va_start(args, fmt);
254 - repo_common_pathv(the_repository, pathname, fmt, args);
255 - va_end(args);
256 - return pathname->buf;
257 -}
258 -
240 /*
241 * Return a statically allocated path into the main repository's
242 * (the_repository) git directory.
worktree.c
+24 -8
@@ -183,7 +183,7 @@ char *get_worktree_git_dir(const struct worktree *wt)
183 else if (!wt->id)
184 return xstrdup(repo_get_common_dir(the_repository));
185 else
186 - return xstrdup(git_common_path("worktrees/%s", wt->id));
186 + return repo_common_path(the_repository, "worktrees/%s", wt->id);
187 }
188
189 static struct worktree *find_worktree_by_suffix(struct worktree **list,
@@ -314,6 +314,7 @@ int validate_worktree(const struct worktree *wt, struct strbuf *errmsg,
314 {
315 struct strbuf wt_path = STRBUF_INIT;
316 struct strbuf realpath = STRBUF_INIT;
317 + struct strbuf buf = STRBUF_INIT;
318 char *path = NULL;
319 int err, ret = -1;
320
@@ -343,7 +344,7 @@ int validate_worktree(const struct worktree *wt, struct strbuf *errmsg,
344 if (!is_absolute_path(wt->path)) {
345 strbuf_addf_gently(errmsg,
346 _("'%s' file does not contain absolute path to the working tree location"),
346 - git_common_path("worktrees/%s/gitdir", wt->id));
347 + repo_common_path_replace(the_repository, &buf, "worktrees/%s/gitdir", wt->id));
348 goto done;
349 }
350
@@ -365,14 +366,16 @@ int validate_worktree(const struct worktree *wt, struct strbuf *errmsg,
366 goto done;
367 }
368
368 - strbuf_realpath(&realpath, git_common_path("worktrees/%s", wt->id), 1);
369 + strbuf_realpath(&realpath, repo_common_path_replace(the_repository, &buf, "worktrees/%s", wt->id), 1);
370 ret = fspathcmp(path, realpath.buf);
371
372 if (ret)
373 strbuf_addf_gently(errmsg, _("'%s' does not point back to '%s'"),
373 - wt->path, git_common_path("worktrees/%s", wt->id));
374 + wt->path, repo_common_path_replace(the_repository, &buf,
375 + "worktrees/%s", wt->id));
376 done:
377 free(path);
378 + strbuf_release(&buf);
379 strbuf_release(&wt_path);
380 strbuf_release(&realpath);
381 return ret;
@@ -384,11 +387,13 @@ void update_worktree_location(struct worktree *wt, const char *path_,
387 struct strbuf path = STRBUF_INIT;
388 struct strbuf dotgit = STRBUF_INIT;
389 struct strbuf gitdir = STRBUF_INIT;
390 + char *wt_gitdir;
391
392 if (is_main_worktree(wt))
393 BUG("can't relocate main worktree");
394
391 - strbuf_realpath(&gitdir, git_common_path("worktrees/%s/gitdir", wt->id), 1);
395 + wt_gitdir = repo_common_path(the_repository, "worktrees/%s/gitdir", wt->id);
396 + strbuf_realpath(&gitdir, wt_gitdir, 1);
397 strbuf_realpath(&path, path_, 1);
398 strbuf_addf(&dotgit, "%s/.git", path.buf);
399 if (fspathcmp(wt->path, path.buf)) {
@@ -400,6 +405,7 @@ void update_worktree_location(struct worktree *wt, const char *path_,
405 strbuf_release(&path);
406 strbuf_release(&dotgit);
407 strbuf_release(&gitdir);
408 + free(wt_gitdir);
409 }
410
411 int is_worktree_being_rebased(const struct worktree *wt,
@@ -585,6 +591,7 @@ static void repair_gitfile(struct worktree *wt,
591 struct strbuf backlink = STRBUF_INIT;
592 char *dotgit_contents = NULL;
593 const char *repair = NULL;
594 + char *path = NULL;
595 int err;
596
597 /* missing worktree can't be repaired */
@@ -596,7 +603,8 @@ static void repair_gitfile(struct worktree *wt,
603 goto done;
604 }
605
599 - strbuf_realpath(&repo, git_common_path("worktrees/%s", wt->id), 1);
606 + path = repo_common_path(the_repository, "worktrees/%s", wt->id);
607 + strbuf_realpath(&repo, path, 1);
608 strbuf_addf(&dotgit, "%s/.git", wt->path);
609 strbuf_addf(&gitdir, "%s/gitdir", repo.buf);
610 dotgit_contents = xstrdup_or_null(read_gitfile_gently(dotgit.buf, &err));
@@ -626,6 +634,7 @@ static void repair_gitfile(struct worktree *wt,
634
635 done:
636 free(dotgit_contents);
637 + free(path);
638 strbuf_release(&repo);
639 strbuf_release(&dotgit);
640 strbuf_release(&gitdir);
@@ -657,11 +666,13 @@ void repair_worktree_after_gitdir_move(struct worktree *wt, const char *old_path
666 struct strbuf gitdir = STRBUF_INIT;
667 struct strbuf dotgit = STRBUF_INIT;
668 int is_relative_path;
669 + char *path = NULL;
670
671 if (is_main_worktree(wt))
672 goto done;
673
664 - strbuf_realpath(&gitdir, git_common_path("worktrees/%s/gitdir", wt->id), 1);
674 + path = repo_common_path(the_repository, "worktrees/%s/gitdir", wt->id);
675 + strbuf_realpath(&gitdir, path, 1);
676
677 if (strbuf_read_file(&dotgit, gitdir.buf, 0) < 0)
678 goto done;
@@ -680,6 +691,7 @@ void repair_worktree_after_gitdir_move(struct worktree *wt, const char *old_path
691 done:
692 strbuf_release(&gitdir);
693 strbuf_release(&dotgit);
694 + free(path);
695 }
696
697 void repair_worktrees_after_gitdir_move(const char *old_path)
@@ -871,7 +883,11 @@ int should_prune_worktree(const char *id, struct strbuf *reason, char **wtpath,
883 ssize_t read_result;
884
885 *wtpath = NULL;
874 - strbuf_realpath(&repo, git_common_path("worktrees/%s", id), 1);
886 +
887 + path = repo_common_path(the_repository, "worktrees/%s", id);
888 + strbuf_realpath(&repo, path, 1);
889 + FREE_AND_NULL(path);
890 +
891 strbuf_addf(&gitdir, "%s/gitdir", repo.buf);
892 if (!is_directory(repo.buf)) {
893 strbuf_addstr(reason, _("not a valid directory"));