worktree: add `write_worktree_linking_files()` function

A new helper function, `write_worktree_linking_files()`, centralizes the logic for computing and writing either relative or absolute paths, based on the provided configuration. This function accepts `strbuf` pointers to both the worktree’s `.git` link and the repository’s `gitdir`, and then writes the appropriate path to each. The `relativeWorktrees` extension is automatically set when a worktree is linked with relative paths. Signed-off-by: Caleb White <cdwhite3@pm.me> Signed-off-by: Junio C Hamano <gitster@pobox.com>

Caleb White committed Nov 29, 2024 at 22:22 UTC 4dac9e3c01cf056edd315e0ed26e6df1c4d94571
2 files changed +48
worktree.c
+35
@@ -1032,3 +1032,38 @@ cleanup:
1032 free(main_worktree_file);
1033 return res;
1034 }
1035 +
1036 +void write_worktree_linking_files(struct strbuf dotgit, struct strbuf gitdir,
1037 + int use_relative_paths)
1038 +{
1039 + struct strbuf path = STRBUF_INIT;
1040 + struct strbuf repo = STRBUF_INIT;
1041 + struct strbuf tmp = STRBUF_INIT;
1042 +
1043 + strbuf_addbuf(&path, &dotgit);
1044 + strbuf_strip_suffix(&path, "/.git");
1045 + strbuf_realpath(&path, path.buf, 1);
1046 + strbuf_addbuf(&repo, &gitdir);
1047 + strbuf_strip_suffix(&repo, "/gitdir");
1048 + strbuf_realpath(&repo, repo.buf, 1);
1049 +
1050 + if (use_relative_paths && !the_repository->repository_format_relative_worktrees) {
1051 + if (upgrade_repository_format(1) < 0)
1052 + die(_("unable to upgrade repository format to support relative worktrees"));
1053 + if (git_config_set_gently("extensions.relativeWorktrees", "true"))
1054 + die(_("unable to set extensions.relativeWorktrees setting"));
1055 + the_repository->repository_format_relative_worktrees = 1;
1056 + }
1057 +
1058 + if (use_relative_paths) {
1059 + write_file(gitdir.buf, "%s/.git", relative_path(path.buf, repo.buf, &tmp));
1060 + write_file(dotgit.buf, "gitdir: %s", relative_path(repo.buf, path.buf, &tmp));
1061 + } else {
1062 + write_file(gitdir.buf, "%s/.git", path.buf);
1063 + write_file(dotgit.buf, "gitdir: %s", repo.buf);
1064 + }
1065 +
1066 + strbuf_release(&path);
1067 + strbuf_release(&repo);
1068 + strbuf_release(&tmp);
1069 +}
worktree.h
+13
@@ -215,4 +215,17 @@ void strbuf_worktree_ref(const struct worktree *wt,
215 */
216 int init_worktree_config(struct repository *r);
217
218 +/**
219 + * Write the .git file and gitdir file that links the worktree to the repository.
220 + *
221 + * The `dotgit` parameter is the path to the worktree's .git file, and `gitdir`
222 + * is the path to the repository's `gitdir` file.
223 + *
224 + * Example
225 + * dotgit: "/path/to/foo/.git"
226 + * gitdir: "/path/to/repo/worktrees/foo/gitdir"
227 + */
228 +void write_worktree_linking_files(struct strbuf dotgit, struct strbuf gitdir,
229 + int use_relative_paths);
230 +
231 #endif