From 70a16ff8a162ad0b6a39d17a1699a2949e2a2674 Mon Sep 17 00:00:00 2001 From: Patrick Steinhardt Date: Fri, 7 Feb 2025 12:03:26 +0100 Subject: path: refactor `repo_common_path()` family of functions The functions provided by the "path" subsystem to derive repository paths for the commondir, gitdir, worktrees and submodules are quite inconsistent. Some functions have a `strbuf_` prefix, others have different return values, some don't provide a variant working on top of `strbuf`s. We're thus about to refactor all of these family of functions so that they follow a common pattern: - `repo_*_path()` returns an allocated string. - `repo_*_path_append()` appends the path to the caller-provided buffer while returning a constant pointer to the buffer. This clarifies whether the buffer is being appended to or rewritten, which otherwise wasn't immediately obvious. - `repo_*_path_replace()` replaces contents of the buffer with the computed path, again returning a pointer to the buffer contents. The returned constant pointer isn't being used anywhere yet, but it will be used in subsequent commits. Its intent is to allow calling patterns like the following somewhat contrived example: if (!stat(&st, repo_common_path_replace(repo, &buf, ...)) && !unlink(repo_common_path_replace(repo, &buf, ...))) ... Refactor the commondir family of functions accordingly and adapt all callers. Note that `repo_common_pathv()` is converted into an internal implementation detail. It is only used to implement `the_repository` compatibility shims and will eventually be removed from the public interface. Signed-off-by: Patrick Steinhardt Signed-off-by: Junio C Hamano --- path.c | 32 ++++++++++++++++++++++++++++---- 1 file changed, 28 insertions(+), 4 deletions(-) (limited to 'path.c') diff --git a/path.c b/path.c index 07964f5d32..273b649e00 100644 --- a/path.c +++ b/path.c @@ -414,7 +414,7 @@ static void strbuf_worktree_gitdir(struct strbuf *buf, else if (!wt->id) strbuf_addstr(buf, repo->commondir); else - strbuf_git_common_path(buf, repo, "worktrees/%s", wt->id); + repo_common_path_append(repo, buf, "worktrees/%s", wt->id); } void repo_git_pathv(const struct repository *repo, @@ -596,14 +596,38 @@ void repo_common_pathv(const struct repository *repo, strbuf_cleanup_path(sb); } -void strbuf_git_common_path(struct strbuf *sb, - const struct repository *repo, - const char *fmt, ...) +char *repo_common_path(const struct repository *repo, + const char *fmt, ...) +{ + struct strbuf sb = STRBUF_INIT; + va_list args; + va_start(args, fmt); + repo_common_pathv(repo, &sb, fmt, args); + va_end(args); + return strbuf_detach(&sb, NULL); +} + +const char *repo_common_path_append(const struct repository *repo, + struct strbuf *sb, + const char *fmt, ...) +{ + va_list args; + va_start(args, fmt); + repo_common_pathv(repo, sb, fmt, args); + va_end(args); + return sb->buf; +} + +const char *repo_common_path_replace(const struct repository *repo, + struct strbuf *sb, + const char *fmt, ...) { va_list args; + strbuf_reset(sb); va_start(args, fmt); repo_common_pathv(repo, sb, fmt, args); va_end(args); + return sb->buf; } static struct passwd *getpw_str(const char *username, size_t len) -- cgit v1.3 From bdfc07bfdf3f4f4ef94580c0cb46eef5977bb810 Mon Sep 17 00:00:00 2001 From: Patrick Steinhardt Date: Fri, 7 Feb 2025 12:03:27 +0100 Subject: path: refactor `repo_git_path()` family of functions As explained in an earlier commit, we're refactoring path-related functions to provide a consistent interface for computing paths into the commondir, gitdir and worktree. Refactor the "gitdir" family of functions accordingly. Note that the `repo_git_pathv()` function is converted into an internal implementation detail. It is only used to implement `the_repository` compatibility shims and will eventually be removed from the public interface. Signed-off-by: Patrick Steinhardt Signed-off-by: Junio C Hamano --- editor.c | 6 ++---- hook.c | 3 +-- path.c | 19 ++++++++++++++++--- path.h | 32 +++++++++++--------------------- submodule.c | 4 ++-- 5 files changed, 32 insertions(+), 32 deletions(-) (limited to 'path.c') diff --git a/editor.c b/editor.c index 6b9ce81d5f..b79d97b0e7 100644 --- a/editor.c +++ b/editor.c @@ -142,10 +142,8 @@ int strbuf_edit_interactively(struct repository *r, struct strbuf sb = STRBUF_INIT; int fd, res = 0; - if (!is_absolute_path(path)) { - strbuf_repo_git_path(&sb, r, "%s", path); - path = sb.buf; - } + if (!is_absolute_path(path)) + path = repo_git_path_append(r, &sb, "%s", path); fd = open(path, O_WRONLY | O_CREAT | O_TRUNC, 0666); if (fd < 0) diff --git a/hook.c b/hook.c index 9ddbdee06d..b3de1048bf 100644 --- a/hook.c +++ b/hook.c @@ -16,8 +16,7 @@ const char *find_hook(struct repository *r, const char *name) int found_hook; - strbuf_reset(&path); - strbuf_repo_git_path(&path, r, "hooks/%s", name); + repo_git_path_replace(r, &path, "hooks/%s", name); found_hook = access(path.buf, X_OK) >= 0; #ifdef STRIP_EXTENSION if (!found_hook) { diff --git a/path.c b/path.c index 273b649e00..779aa94b56 100644 --- a/path.c +++ b/path.c @@ -443,14 +443,27 @@ char *repo_git_path(const struct repository *repo, return strbuf_detach(&path, NULL); } -void strbuf_repo_git_path(struct strbuf *sb, - const struct repository *repo, - const char *fmt, ...) +const char *repo_git_path_append(const struct repository *repo, + struct strbuf *sb, + const char *fmt, ...) { va_list args; va_start(args, fmt); repo_git_pathv(repo, NULL, sb, fmt, args); va_end(args); + return sb->buf; +} + +const char *repo_git_path_replace(const struct repository *repo, + struct strbuf *sb, + const char *fmt, ...) +{ + va_list args; + strbuf_reset(sb); + va_start(args, fmt); + repo_git_pathv(repo, NULL, sb, fmt, args); + va_end(args); + return sb->buf; } char *mkpathdup(const char *fmt, ...) diff --git a/path.h b/path.h index 3c75495e1a..c45311b0a8 100644 --- a/path.h +++ b/path.h @@ -52,29 +52,16 @@ const char *repo_common_path_replace(const struct repository *repo, * For an exhaustive list of the adjustments made look at `common_list` and * `adjust_git_path` in path.c. */ - -/* - * Return a path into the git directory of repository `repo`. - */ char *repo_git_path(const struct repository *repo, const char *fmt, ...) __attribute__((format (printf, 2, 3))); - -/* - * Print a path into the git directory of repository `repo` into the provided - * buffer. - */ -void repo_git_pathv(const struct repository *repo, - const struct worktree *wt, struct strbuf *buf, - const char *fmt, va_list args); - -/* - * Construct a path into the git directory of repository `repo` and append it - * to the provided buffer `sb`. - */ -void strbuf_repo_git_path(struct strbuf *sb, - const struct repository *repo, - const char *fmt, ...) +const char *repo_git_path_append(const struct repository *repo, + struct strbuf *sb, + const char *fmt, ...) + __attribute__((format (printf, 3, 4))); +const char *repo_git_path_replace(const struct repository *repo, + struct strbuf *sb, + const char *fmt, ...) __attribute__((format (printf, 3, 4))); /* @@ -241,11 +228,14 @@ struct strbuf *get_pathname(void); # include "strbuf.h" # include "repository.h" -/* Internal implementation detail that should not be used. */ +/* Internal implementation details that should not be used. */ void repo_common_pathv(const struct repository *repo, struct strbuf *buf, const char *fmt, va_list args); +void repo_git_pathv(const struct repository *repo, + const struct worktree *wt, struct strbuf *buf, + const char *fmt, va_list args); /* * Return a statically allocated path into the main repository's diff --git a/submodule.c b/submodule.c index b361076c5b..211ead54a0 100644 --- a/submodule.c +++ b/submodule.c @@ -1315,7 +1315,7 @@ static int repo_has_absorbed_submodules(struct repository *r) int ret; struct strbuf buf = STRBUF_INIT; - strbuf_repo_git_path(&buf, r, "modules/"); + repo_git_path_append(r, &buf, "modules/"); ret = file_exists(buf.buf) && !is_empty_dir(buf.buf); strbuf_release(&buf); return ret; @@ -2629,6 +2629,6 @@ void submodule_name_to_gitdir(struct strbuf *buf, struct repository *r, * administrators can explicitly set. Nothing has been decided, * so for now, just append the name at the end of the path. */ - strbuf_repo_git_path(buf, r, "modules/"); + repo_git_path_append(r, buf, "modules/"); strbuf_addstr(buf, submodule_name); } -- cgit v1.3 From 93a8cfaf3c24f8c1f999b2ca5532ff8f46e0808d Mon Sep 17 00:00:00 2001 From: Patrick Steinhardt Date: Fri, 7 Feb 2025 12:03:28 +0100 Subject: path: refactor `repo_worktree_path()` family of functions As explained in an earlier commit, we're refactoring path-related functions to provide a consistent interface for computing paths into the commondir, gitdir and worktree. Refactor the "worktree" family of functions accordingly. Signed-off-by: Patrick Steinhardt Signed-off-by: Junio C Hamano --- path.c | 28 ++++++++++++++++++++++------ path.h | 20 +++++++++----------- repository.c | 4 ++-- 3 files changed, 33 insertions(+), 19 deletions(-) (limited to 'path.c') diff --git a/path.c b/path.c index 779aa94b56..499116dd1e 100644 --- a/path.c +++ b/path.c @@ -519,28 +519,44 @@ char *repo_worktree_path(const struct repository *repo, const char *fmt, ...) struct strbuf path = STRBUF_INIT; va_list args; + va_start(args, fmt); + do_worktree_path(repo, &path, fmt, args); + va_end(args); + + return strbuf_detach(&path, NULL); +} + +const char *repo_worktree_path_append(const struct repository *repo, + struct strbuf *sb, + const char *fmt, ...) +{ + va_list args; + if (!repo->worktree) return NULL; va_start(args, fmt); - do_worktree_path(repo, &path, fmt, args); + do_worktree_path(repo, sb, fmt, args); va_end(args); - return strbuf_detach(&path, NULL); + return sb->buf; } -void strbuf_repo_worktree_path(struct strbuf *sb, - const struct repository *repo, - const char *fmt, ...) +const char *repo_worktree_path_replace(const struct repository *repo, + struct strbuf *sb, + const char *fmt, ...) { va_list args; + strbuf_reset(sb); if (!repo->worktree) - return; + return NULL; va_start(args, fmt); do_worktree_path(repo, sb, fmt, args); va_end(args); + + return sb->buf; } /* Returns 0 on success, negative on failure. */ diff --git a/path.h b/path.h index c45311b0a8..d3f85f0676 100644 --- a/path.h +++ b/path.h @@ -75,24 +75,22 @@ const char *worktree_git_path(struct repository *r, __attribute__((format (printf, 3, 4))); /* - * Return a path into the worktree of repository `repo`. + * The `repo_worktree_path` family of functions will construct a path into a + * repository's worktree. * - * If the repository doesn't have a worktree NULL is returned. + * Returns a `NULL` pointer in case the repository has no worktree. */ char *repo_worktree_path(const struct repository *repo, const char *fmt, ...) __attribute__((format (printf, 2, 3))); - -/* - * Construct a path into the worktree of repository `repo` and append it - * to the provided buffer `sb`. - * - * If the repository doesn't have a worktree nothing will be appended to `sb`. - */ -void strbuf_repo_worktree_path(struct strbuf *sb, - const struct repository *repo, +const char *repo_worktree_path_append(const struct repository *repo, + struct strbuf *sb, const char *fmt, ...) __attribute__((format (printf, 3, 4))); +const char *repo_worktree_path_replace(const struct repository *repo, + struct strbuf *sb, + const char *fmt, ...) + __attribute__((format (printf, 3, 4))); /* * Return a path into a submodule's git directory located at `path`. `path` diff --git a/repository.c b/repository.c index 1a6a62bbd0..648cd88474 100644 --- a/repository.c +++ b/repository.c @@ -312,8 +312,8 @@ int repo_submodule_init(struct repository *subrepo, struct strbuf worktree = STRBUF_INIT; int ret = 0; - strbuf_repo_worktree_path(&gitdir, superproject, "%s/.git", path); - strbuf_repo_worktree_path(&worktree, superproject, "%s", path); + repo_worktree_path_append(superproject, &gitdir, "%s/.git", path); + repo_worktree_path_append(superproject, &worktree, "%s", path); if (repo_init(subrepo, gitdir.buf, worktree.buf)) { /* -- cgit v1.3 From f9467895d884908d5588fc920997b2e53dfb3302 Mon Sep 17 00:00:00 2001 From: Patrick Steinhardt Date: Fri, 7 Feb 2025 12:03:29 +0100 Subject: submodule: refactor `submodule_to_gitdir()` to accept a repo The `submodule_to_gitdir()` function implicitly uses `the_repository` to resolve submodule paths. Refactor the function to instead accept a repo as parameter to remove the dependency on global state. Signed-off-by: Patrick Steinhardt Signed-off-by: Junio C Hamano --- builtin/submodule--helper.c | 2 +- path.c | 2 +- refs.c | 2 +- submodule.c | 11 ++++++----- submodule.h | 3 ++- 5 files changed, 11 insertions(+), 9 deletions(-) (limited to 'path.c') diff --git a/builtin/submodule--helper.c b/builtin/submodule--helper.c index f9b970f8a6..3a64f7e605 100644 --- a/builtin/submodule--helper.c +++ b/builtin/submodule--helper.c @@ -1301,7 +1301,7 @@ static void sync_submodule(const char *path, const char *prefix, remote_key = xstrfmt("remote.%s.url", default_remote); free(default_remote); - submodule_to_gitdir(&sb, path); + submodule_to_gitdir(the_repository, &sb, path); strbuf_addstr(&sb, "/config"); if (git_config_set_in_file_gently(sb.buf, remote_key, NULL, sub_origin_url)) diff --git a/path.c b/path.c index 499116dd1e..a7fa42162e 100644 --- a/path.c +++ b/path.c @@ -567,7 +567,7 @@ static int do_submodule_path(struct strbuf *buf, const char *path, struct strbuf git_submodule_dir = STRBUF_INIT; int ret; - ret = submodule_to_gitdir(&git_submodule_dir, path); + ret = submodule_to_gitdir(the_repository, &git_submodule_dir, path); if (ret) goto cleanup; diff --git a/refs.c b/refs.c index daf6a84205..e1293e53aa 100644 --- a/refs.c +++ b/refs.c @@ -2146,7 +2146,7 @@ struct ref_store *repo_get_submodule_ref_store(struct repository *repo, if (!is_nonbare_repository_dir(&submodule_sb)) goto done; - if (submodule_to_gitdir(&submodule_sb, submodule)) + if (submodule_to_gitdir(repo, &submodule_sb, submodule)) goto done; subrepo = xmalloc(sizeof(*subrepo)); diff --git a/submodule.c b/submodule.c index 211ead54a0..0530e8cf24 100644 --- a/submodule.c +++ b/submodule.c @@ -536,7 +536,8 @@ static struct repository *open_submodule(const char *path) struct strbuf sb = STRBUF_INIT; struct repository *out = xmalloc(sizeof(*out)); - if (submodule_to_gitdir(&sb, path) || repo_init(out, sb.buf, NULL)) { + if (submodule_to_gitdir(the_repository, &sb, path) || + repo_init(out, sb.buf, NULL)) { strbuf_release(&sb); free(out); return NULL; @@ -2572,7 +2573,8 @@ int get_superproject_working_tree(struct strbuf *buf) * Put the gitdir for a submodule (given relative to the main * repository worktree) into `buf`, or return -1 on error. */ -int submodule_to_gitdir(struct strbuf *buf, const char *submodule) +int submodule_to_gitdir(struct repository *repo, + struct strbuf *buf, const char *submodule) { const struct submodule *sub; const char *git_dir; @@ -2592,14 +2594,13 @@ int submodule_to_gitdir(struct strbuf *buf, const char *submodule) strbuf_addstr(buf, git_dir); } if (!is_git_directory(buf->buf)) { - sub = submodule_from_path(the_repository, null_oid(), - submodule); + sub = submodule_from_path(repo, null_oid(), submodule); if (!sub) { ret = -1; goto cleanup; } strbuf_reset(buf); - submodule_name_to_gitdir(buf, the_repository, sub->name); + submodule_name_to_gitdir(buf, repo, sub->name); } cleanup: diff --git a/submodule.h b/submodule.h index 4deb1b5f84..db980c1d08 100644 --- a/submodule.h +++ b/submodule.h @@ -136,7 +136,8 @@ int push_unpushed_submodules(struct repository *r, * path of that submodule in 'buf'. Return -1 on error or when the * submodule is not initialized. */ -int submodule_to_gitdir(struct strbuf *buf, const char *submodule); +int submodule_to_gitdir(struct repository *repo, + struct strbuf *buf, const char *submodule); /* * Given a submodule name, create a path to where the submodule's gitdir lives -- cgit v1.3 From f5c714e2a7d6239548b94c37ae906484e94b5bc7 Mon Sep 17 00:00:00 2001 From: Patrick Steinhardt Date: Fri, 7 Feb 2025 12:03:30 +0100 Subject: path: refactor `repo_submodule_path()` family of functions As explained in an earlier commit, we're refactoring path-related functions to provide a consistent interface for computing paths into the commondir, gitdir and worktree. Refactor the "submodule" family of functions accordingly. Note that in contrast to the other `repo_*_path()` families, we have to pass in the repository as a non-constant pointer. This is because we end up calling `repo_read_gitmodules()` deep down in the callstack, which may end up modifying the repository. Signed-off-by: Patrick Steinhardt Signed-off-by: Junio C Hamano --- builtin/submodule--helper.c | 2 +- path.c | 37 +++++++++++++++++++++++++++++-------- path.h | 30 ++++++++++++++++++------------ t/helper/test-ref-store.c | 7 +++---- worktree.c | 3 ++- 5 files changed, 53 insertions(+), 26 deletions(-) (limited to 'path.c') diff --git a/builtin/submodule--helper.c b/builtin/submodule--helper.c index 3a64f7e605..c1a8029714 100644 --- a/builtin/submodule--helper.c +++ b/builtin/submodule--helper.c @@ -1826,7 +1826,7 @@ static int clone_submodule(const struct module_clone_data *clone_data, connect_work_tree_and_git_dir(clone_data_path, sm_gitdir, 0); - p = git_pathdup_submodule(clone_data_path, "config"); + p = repo_submodule_path(the_repository, clone_data_path, "config"); if (!p) die(_("could not get submodule directory for '%s'"), clone_data_path); diff --git a/path.c b/path.c index a7fa42162e..0d81e9fc32 100644 --- a/path.c +++ b/path.c @@ -560,14 +560,15 @@ const char *repo_worktree_path_replace(const struct repository *repo, } /* Returns 0 on success, negative on failure. */ -static int do_submodule_path(struct strbuf *buf, const char *path, +static int do_submodule_path(struct repository *repo, + struct strbuf *buf, const char *path, const char *fmt, va_list args) { struct strbuf git_submodule_common_dir = STRBUF_INIT; struct strbuf git_submodule_dir = STRBUF_INIT; int ret; - ret = submodule_to_gitdir(the_repository, &git_submodule_dir, path); + ret = submodule_to_gitdir(repo, &git_submodule_dir, path); if (ret) goto cleanup; @@ -586,13 +587,14 @@ cleanup: return ret; } -char *git_pathdup_submodule(const char *path, const char *fmt, ...) +char *repo_submodule_path(struct repository *repo, + const char *path, const char *fmt, ...) { int err; va_list args; struct strbuf buf = STRBUF_INIT; va_start(args, fmt); - err = do_submodule_path(&buf, path, fmt, args); + err = do_submodule_path(repo, &buf, path, fmt, args); va_end(args); if (err) { strbuf_release(&buf); @@ -601,16 +603,35 @@ char *git_pathdup_submodule(const char *path, const char *fmt, ...) return strbuf_detach(&buf, NULL); } -int strbuf_git_path_submodule(struct strbuf *buf, const char *path, - const char *fmt, ...) +const char *repo_submodule_path_append(struct repository *repo, + struct strbuf *buf, + const char *path, + const char *fmt, ...) { int err; va_list args; va_start(args, fmt); - err = do_submodule_path(buf, path, fmt, args); + err = do_submodule_path(repo, buf, path, fmt, args); va_end(args); + if (err) + return NULL; + return buf->buf; +} - return err; +const char *repo_submodule_path_replace(struct repository *repo, + struct strbuf *buf, + const char *path, + const char *fmt, ...) +{ + int err; + va_list args; + strbuf_reset(buf); + va_start(args, fmt); + err = do_submodule_path(repo, buf, path, fmt, args); + va_end(args); + if (err) + return NULL; + return buf->buf; } void repo_common_pathv(const struct repository *repo, diff --git a/path.h b/path.h index d3f85f0676..4fe523626c 100644 --- a/path.h +++ b/path.h @@ -93,20 +93,26 @@ const char *repo_worktree_path_replace(const struct repository *repo, __attribute__((format (printf, 3, 4))); /* - * Return a path into a submodule's git directory located at `path`. `path` - * must only reference a submodule of the main repository (the_repository). - */ -char *git_pathdup_submodule(const char *path, const char *fmt, ...) - __attribute__((format (printf, 2, 3))); - -/* - * Construct a path into a submodule's git directory located at `path` and - * append it to the provided buffer `sb`. `path` must only reference a - * submodule of the main repository (the_repository). + * The `repo_submodule_path` family of functions will construct a path into a + * submodule's git directory located at `path`. `path` must be a submodule path + * as found in the index and must be part of the given repository. + * + * Returns a `NULL` pointer in case the submodule cannot be found. */ -int strbuf_git_path_submodule(struct strbuf *sb, const char *path, - const char *fmt, ...) +char *repo_submodule_path(struct repository *repo, + const char *path, + const char *fmt, ...) __attribute__((format (printf, 3, 4))); +const char *repo_submodule_path_append(struct repository *repo, + struct strbuf *sb, + const char *path, + const char *fmt, ...) + __attribute__((format (printf, 4, 5))); +const char *repo_submodule_path_replace(struct repository *repo, + struct strbuf *sb, + const char *path, + const char *fmt, ...) + __attribute__((format (printf, 4, 5))); void report_linked_checkout_garbage(struct repository *r); diff --git a/t/helper/test-ref-store.c b/t/helper/test-ref-store.c index 1cc05f043a..e00fce592b 100644 --- a/t/helper/test-ref-store.c +++ b/t/helper/test-ref-store.c @@ -75,11 +75,10 @@ static const char **get_store(const char **argv, struct ref_store **refs) *refs = get_main_ref_store(the_repository); } else if (skip_prefix(argv[0], "submodule:", &gitdir)) { struct strbuf sb = STRBUF_INIT; - int ret; - ret = strbuf_git_path_submodule(&sb, gitdir, "objects/"); - if (ret) - die("strbuf_git_path_submodule failed: %d", ret); + if (!repo_submodule_path_append(the_repository, + &sb, gitdir, "objects/")) + die("computing submodule path failed"); add_to_alternates_memory(sb.buf); strbuf_release(&sb); diff --git a/worktree.c b/worktree.c index f8d6e7127f..8f4fc10c44 100644 --- a/worktree.c +++ b/worktree.c @@ -487,7 +487,8 @@ int submodule_uses_worktrees(const char *path) int ret = 0; struct repository_format format = REPOSITORY_FORMAT_INIT; - submodule_gitdir = git_pathdup_submodule(path, "%s", ""); + submodule_gitdir = repo_submodule_path(the_repository, + path, "%s", ""); if (!submodule_gitdir) return 0; -- cgit v1.3 From 07242c2a5afb2a633feb110b1aa74e2adcc37575 Mon Sep 17 00:00:00 2001 From: Patrick Steinhardt Date: Fri, 7 Feb 2025 12:03:35 +0100 Subject: 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 Signed-off-by: Junio C Hamano --- builtin/worktree.c | 16 ++++++++++++---- path.c | 8 ++++---- path.h | 19 ------------------- worktree.c | 32 ++++++++++++++++++++++++-------- 4 files changed, 40 insertions(+), 35 deletions(-) (limited to 'path.c') diff --git a/builtin/worktree.c b/builtin/worktree.c index 2cea9441a6..761e302a36 100644 --- a/builtin/worktree.c +++ b/builtin/worktree.c @@ -151,7 +151,7 @@ static int delete_git_dir(const char *id) struct strbuf sb = STRBUF_INIT; int ret; - strbuf_addstr(&sb, git_common_path("worktrees/%s", id)); + repo_common_path_append(the_repository, &sb, "worktrees/%s", id); ret = remove_dir_recursively(&sb, 0); if (ret < 0 && errno == ENOTDIR) ret = unlink(sb.buf); @@ -1102,6 +1102,7 @@ static int lock_worktree(int ac, const char **av, const char *prefix, OPT_END() }; struct worktree **worktrees, *wt; + char *path; ac = parse_options(ac, av, prefix, options, git_worktree_lock_usage, 0); if (ac != 1) @@ -1122,9 +1123,11 @@ static int lock_worktree(int ac, const char **av, const char *prefix, die(_("'%s' is already locked"), av[0]); } - write_file(git_common_path("worktrees/%s/locked", wt->id), - "%s", reason); + path = repo_common_path(the_repository, "worktrees/%s/locked", wt->id); + write_file(path, "%s", reason); + free_worktrees(worktrees); + free(path); return 0; } @@ -1135,6 +1138,7 @@ static int unlock_worktree(int ac, const char **av, const char *prefix, OPT_END() }; struct worktree **worktrees, *wt; + char *path; int ret; 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, die(_("The main working tree cannot be locked or unlocked")); if (!worktree_lock_reason(wt)) die(_("'%s' is not locked"), av[0]); - ret = unlink_or_warn(git_common_path("worktrees/%s/locked", wt->id)); + + path = repo_common_path(the_repository, "worktrees/%s/locked", wt->id); + ret = unlink_or_warn(path); + free_worktrees(worktrees); + free(path); return ret; } diff --git a/path.c b/path.c index 0d81e9fc32..2d07ba723d 100644 --- a/path.c +++ b/path.c @@ -634,10 +634,10 @@ const char *repo_submodule_path_replace(struct repository *repo, return buf->buf; } -void repo_common_pathv(const struct repository *repo, - struct strbuf *sb, - const char *fmt, - va_list args) +static void repo_common_pathv(const struct repository *repo, + struct strbuf *sb, + const char *fmt, + va_list args) { strbuf_addstr(sb, repo->commondir); if (sb->len && !is_dir_sep(sb->buf[sb->len - 1])) diff --git a/path.h b/path.h index cdc26acb74..bed0a4c6f9 100644 --- a/path.h +++ b/path.h @@ -233,29 +233,10 @@ struct strbuf *get_pathname(void); # include "repository.h" /* Internal implementation details that should not be used. */ -void repo_common_pathv(const struct repository *repo, - struct strbuf *buf, - const char *fmt, - va_list args); void repo_git_pathv(const struct repository *repo, const struct worktree *wt, struct strbuf *buf, const char *fmt, va_list args); -/* - * Return a statically allocated path into the main repository's - * (the_repository) common git directory. - */ -__attribute__((format (printf, 1, 2))) -static inline const char *git_common_path(const char *fmt, ...) -{ - struct strbuf *pathname = get_pathname(); - va_list args; - va_start(args, fmt); - repo_common_pathv(the_repository, pathname, fmt, args); - va_end(args); - return pathname->buf; -} - /* * Return a statically allocated path into the main repository's * (the_repository) git directory. diff --git a/worktree.c b/worktree.c index 3b94535963..d5d07d7a84 100644 --- a/worktree.c +++ b/worktree.c @@ -183,7 +183,7 @@ char *get_worktree_git_dir(const struct worktree *wt) else if (!wt->id) return xstrdup(repo_get_common_dir(the_repository)); else - return xstrdup(git_common_path("worktrees/%s", wt->id)); + return repo_common_path(the_repository, "worktrees/%s", wt->id); } static struct worktree *find_worktree_by_suffix(struct worktree **list, @@ -314,6 +314,7 @@ int validate_worktree(const struct worktree *wt, struct strbuf *errmsg, { struct strbuf wt_path = STRBUF_INIT; struct strbuf realpath = STRBUF_INIT; + struct strbuf buf = STRBUF_INIT; char *path = NULL; int err, ret = -1; @@ -343,7 +344,7 @@ int validate_worktree(const struct worktree *wt, struct strbuf *errmsg, if (!is_absolute_path(wt->path)) { strbuf_addf_gently(errmsg, _("'%s' file does not contain absolute path to the working tree location"), - git_common_path("worktrees/%s/gitdir", wt->id)); + repo_common_path_replace(the_repository, &buf, "worktrees/%s/gitdir", wt->id)); goto done; } @@ -365,14 +366,16 @@ int validate_worktree(const struct worktree *wt, struct strbuf *errmsg, goto done; } - strbuf_realpath(&realpath, git_common_path("worktrees/%s", wt->id), 1); + strbuf_realpath(&realpath, repo_common_path_replace(the_repository, &buf, "worktrees/%s", wt->id), 1); ret = fspathcmp(path, realpath.buf); if (ret) strbuf_addf_gently(errmsg, _("'%s' does not point back to '%s'"), - wt->path, git_common_path("worktrees/%s", wt->id)); + wt->path, repo_common_path_replace(the_repository, &buf, + "worktrees/%s", wt->id)); done: free(path); + strbuf_release(&buf); strbuf_release(&wt_path); strbuf_release(&realpath); return ret; @@ -384,11 +387,13 @@ void update_worktree_location(struct worktree *wt, const char *path_, struct strbuf path = STRBUF_INIT; struct strbuf dotgit = STRBUF_INIT; struct strbuf gitdir = STRBUF_INIT; + char *wt_gitdir; if (is_main_worktree(wt)) BUG("can't relocate main worktree"); - strbuf_realpath(&gitdir, git_common_path("worktrees/%s/gitdir", wt->id), 1); + wt_gitdir = repo_common_path(the_repository, "worktrees/%s/gitdir", wt->id); + strbuf_realpath(&gitdir, wt_gitdir, 1); strbuf_realpath(&path, path_, 1); strbuf_addf(&dotgit, "%s/.git", path.buf); if (fspathcmp(wt->path, path.buf)) { @@ -400,6 +405,7 @@ void update_worktree_location(struct worktree *wt, const char *path_, strbuf_release(&path); strbuf_release(&dotgit); strbuf_release(&gitdir); + free(wt_gitdir); } int is_worktree_being_rebased(const struct worktree *wt, @@ -585,6 +591,7 @@ static void repair_gitfile(struct worktree *wt, struct strbuf backlink = STRBUF_INIT; char *dotgit_contents = NULL; const char *repair = NULL; + char *path = NULL; int err; /* missing worktree can't be repaired */ @@ -596,7 +603,8 @@ static void repair_gitfile(struct worktree *wt, goto done; } - strbuf_realpath(&repo, git_common_path("worktrees/%s", wt->id), 1); + path = repo_common_path(the_repository, "worktrees/%s", wt->id); + strbuf_realpath(&repo, path, 1); strbuf_addf(&dotgit, "%s/.git", wt->path); strbuf_addf(&gitdir, "%s/gitdir", repo.buf); dotgit_contents = xstrdup_or_null(read_gitfile_gently(dotgit.buf, &err)); @@ -626,6 +634,7 @@ static void repair_gitfile(struct worktree *wt, done: free(dotgit_contents); + free(path); strbuf_release(&repo); strbuf_release(&dotgit); strbuf_release(&gitdir); @@ -657,11 +666,13 @@ void repair_worktree_after_gitdir_move(struct worktree *wt, const char *old_path struct strbuf gitdir = STRBUF_INIT; struct strbuf dotgit = STRBUF_INIT; int is_relative_path; + char *path = NULL; if (is_main_worktree(wt)) goto done; - strbuf_realpath(&gitdir, git_common_path("worktrees/%s/gitdir", wt->id), 1); + path = repo_common_path(the_repository, "worktrees/%s/gitdir", wt->id); + strbuf_realpath(&gitdir, path, 1); if (strbuf_read_file(&dotgit, gitdir.buf, 0) < 0) goto done; @@ -680,6 +691,7 @@ void repair_worktree_after_gitdir_move(struct worktree *wt, const char *old_path done: strbuf_release(&gitdir); strbuf_release(&dotgit); + free(path); } 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, ssize_t read_result; *wtpath = NULL; - strbuf_realpath(&repo, git_common_path("worktrees/%s", id), 1); + + path = repo_common_path(the_repository, "worktrees/%s", id); + strbuf_realpath(&repo, path, 1); + FREE_AND_NULL(path); + strbuf_addf(&gitdir, "%s/gitdir", repo.buf); if (!is_directory(repo.buf)) { strbuf_addstr(reason, _("not a valid directory")); -- cgit v1.3 From 88dd321cfedc6ee190dfafe4670a83ea33cdf4a3 Mon Sep 17 00:00:00 2001 From: Patrick Steinhardt Date: Fri, 7 Feb 2025 12:03:37 +0100 Subject: path: drop `git_path()` in favor of `repo_git_path()` Remove `git_path()` in favor of the `repo_git_path()` family of functions, which makes the implicit dependency on `the_repository` go away. Note that `git_path()` returned 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()` as well as `get_pathname()` from the public interface. Signed-off-by: Patrick Steinhardt Signed-off-by: Junio C Hamano --- builtin/commit.c | 8 +++++--- builtin/gc.c | 21 +++++++++++++++------ builtin/notes.c | 7 ++++++- builtin/rebase.c | 2 +- builtin/remote.c | 6 ++++-- builtin/rev-parse.c | 6 +++--- builtin/worktree.c | 11 +++++++++-- notes-merge.c | 20 ++++++++++++-------- path.c | 8 ++++---- path.h | 27 --------------------------- read-cache.c | 24 +++++++++++++++++------- remote.c | 21 ++++++++++++--------- rerere.c | 14 +++++++++++--- shallow.c | 4 +++- wt-status.c | 42 ++++++++++++++++++++++++++---------------- 15 files changed, 128 insertions(+), 93 deletions(-) (limited to 'path.c') diff --git a/builtin/commit.c b/builtin/commit.c index 9fb405dd4a..2f45968222 100644 --- a/builtin/commit.c +++ b/builtin/commit.c @@ -352,6 +352,7 @@ static const char *prepare_index(const char **argv, const char *prefix, struct pathspec pathspec; int refresh_flags = REFRESH_QUIET; const char *ret; + char *path = NULL; if (is_status) refresh_flags |= REFRESH_UNMERGED; @@ -524,9 +525,9 @@ static const char *prepare_index(const char **argv, const char *prefix, if (write_locked_index(the_repository->index, &index_lock, 0)) die(_("unable to write new index file")); - hold_lock_file_for_update(&false_lock, - git_path("next-index-%"PRIuMAX, - (uintmax_t) getpid()), + path = repo_git_path(the_repository, "next-index-%"PRIuMAX, + (uintmax_t) getpid()); + hold_lock_file_for_update(&false_lock, path, LOCK_DIE_ON_ERROR); create_base_index(current_head); @@ -542,6 +543,7 @@ static const char *prepare_index(const char **argv, const char *prefix, out: string_list_clear(&partial, 0); clear_pathspec(&pathspec); + free(path); return ret; } diff --git a/builtin/gc.c b/builtin/gc.c index 57f6aee174..5923d9a05b 100644 --- a/builtin/gc.c +++ b/builtin/gc.c @@ -99,9 +99,11 @@ static void process_log_file(void) /* There was some error recorded in the lock file */ commit_lock_file(&log_lock); } else { + char *path = repo_git_path(the_repository, "gc.log"); /* No error, clean up any old gc.log */ - unlink(git_path("gc.log")); + unlink(path); rollback_lock_file(&log_lock); + free(path); } } @@ -299,8 +301,11 @@ static int too_many_loose_objects(struct gc_config *cfg) int num_loose = 0; int needed = 0; const unsigned hexsz_loose = the_hash_algo->hexsz - 2; + char *path; - dir = opendir(git_path("objects/17")); + path = repo_git_path(the_repository, "objects/17"); + dir = opendir(path); + free(path); if (!dir) return 0; @@ -821,11 +826,12 @@ struct repository *repo UNUSED) } if (daemonized) { - hold_lock_file_for_update(&log_lock, - git_path("gc.log"), + char *path = repo_git_path(the_repository, "gc.log"); + hold_lock_file_for_update(&log_lock, path, LOCK_DIE_ON_ERROR); dup2(get_lock_file_fd(&log_lock), 2); atexit(process_log_file_at_exit); + free(path); } gc_before_repack(&opts, &cfg); @@ -887,8 +893,11 @@ struct repository *repo UNUSED) warning(_("There are too many unreachable loose objects; " "run 'git prune' to remove them.")); - if (!daemonized) - unlink(git_path("gc.log")); + if (!daemonized) { + char *path = repo_git_path(the_repository, "gc.log"); + unlink(path); + free(path); + } out: gc_config_release(&cfg); diff --git a/builtin/notes.c b/builtin/notes.c index 18bcbb2f91..ff61ec5f2d 100644 --- a/builtin/notes.c +++ b/builtin/notes.c @@ -979,6 +979,8 @@ static int merge(int argc, const char **argv, const char *prefix, else { /* Merge has unresolved conflicts */ struct worktree **worktrees; const struct worktree *wt; + char *path; + /* Update .git/NOTES_MERGE_PARTIAL with partial merge result */ refs_update_ref(get_main_ref_store(the_repository), msg.buf, "NOTES_MERGE_PARTIAL", &result_oid, NULL, @@ -994,10 +996,13 @@ static int merge(int argc, const char **argv, const char *prefix, if (refs_update_symref(get_main_ref_store(the_repository), "NOTES_MERGE_REF", notes_ref, NULL)) die(_("failed to store link to current notes ref (%s)"), notes_ref); + + path = repo_git_path(the_repository, NOTES_MERGE_WORKTREE); fprintf(stderr, _("Automatic notes merge failed. Fix conflicts in %s " "and commit the result with 'git notes merge --commit', " "or abort the merge with 'git notes merge --abort'.\n"), - git_path(NOTES_MERGE_WORKTREE)); + path); + free(path); } free_notes(t); diff --git a/builtin/rebase.c b/builtin/rebase.c index 6c9eaf3788..d4715ed35d 100644 --- a/builtin/rebase.c +++ b/builtin/rebase.c @@ -644,7 +644,7 @@ static int run_am(struct rebase_options *opts) return run_command(&am); } - rebased_patches = xstrdup(git_path("rebased-patches")); + rebased_patches = repo_git_path(the_repository, "rebased-patches"); format_patch.out = open(rebased_patches, O_WRONLY | O_CREAT | O_TRUNC, 0666); if (format_patch.out < 0) { diff --git a/builtin/remote.c b/builtin/remote.c index 71d84fb3cf..0489fcc8f3 100644 --- a/builtin/remote.c +++ b/builtin/remote.c @@ -644,9 +644,11 @@ static int migrate_file(struct remote *remote) git_config_set_multivar(buf.buf, remote->fetch.items[i].raw, "^$", 0); #ifndef WITH_BREAKING_CHANGES if (remote->origin == REMOTE_REMOTES) - unlink_or_warn(git_path("remotes/%s", remote->name)); + unlink_or_warn(repo_git_path_replace(the_repository, &buf, + "remotes/%s", remote->name)); else if (remote->origin == REMOTE_BRANCHES) - unlink_or_warn(git_path("branches/%s", remote->name)); + unlink_or_warn(repo_git_path_replace(the_repository, &buf, + "branches/%s", remote->name)); #endif /* WITH_BREAKING_CHANGES */ strbuf_release(&buf); diff --git a/builtin/rev-parse.c b/builtin/rev-parse.c index 428c866c05..490da33bec 100644 --- a/builtin/rev-parse.c +++ b/builtin/rev-parse.c @@ -789,8 +789,8 @@ int cmd_rev_parse(int argc, if (!strcmp(arg, "--git-path")) { if (!argv[i + 1]) die(_("--git-path requires an argument")); - strbuf_reset(&buf); - print_path(git_path("%s", argv[i + 1]), prefix, + print_path(repo_git_path_replace(the_repository, &buf, + "%s", argv[i + 1]), prefix, format, DEFAULT_RELATIVE_IF_SHARED); i++; @@ -1083,7 +1083,7 @@ int cmd_rev_parse(int argc, die(_("Could not read the index")); if (the_repository->index->split_index) { const struct object_id *oid = &the_repository->index->split_index->base_oid; - const char *path = git_path("sharedindex.%s", oid_to_hex(oid)); + const char *path = repo_git_path_replace(the_repository, &buf, "sharedindex.%s", oid_to_hex(oid)); print_path(path, prefix, format, DEFAULT_RELATIVE); } continue; diff --git a/builtin/worktree.c b/builtin/worktree.c index 761e302a36..48448a8355 100644 --- a/builtin/worktree.c +++ b/builtin/worktree.c @@ -163,7 +163,9 @@ static int delete_git_dir(const char *id) static void delete_worktrees_dir_if_empty(void) { - rmdir(git_path("worktrees")); /* ignore failed removal */ + char *path = repo_git_path(the_repository, "worktrees"); + rmdir(path); /* ignore failed removal */ + free(path); } static void prune_worktree(const char *id, const char *reason) @@ -212,8 +214,13 @@ static void prune_worktrees(void) struct strbuf reason = STRBUF_INIT; struct strbuf main_path = STRBUF_INIT; struct string_list kept = STRING_LIST_INIT_DUP; - DIR *dir = opendir(git_path("worktrees")); + char *path; + DIR *dir; struct dirent *d; + + path = repo_git_path(the_repository, "worktrees"); + dir = opendir(path); + free(path); if (!dir) return; while ((d = readdir_skip_dot_and_dotdot(dir)) != NULL) { diff --git a/notes-merge.c b/notes-merge.c index 8c22a171c1..67a472020d 100644 --- a/notes-merge.c +++ b/notes-merge.c @@ -275,34 +275,38 @@ static void diff_tree_local(struct notes_merge_options *o, static void check_notes_merge_worktree(struct notes_merge_options *o) { + struct strbuf buf = STRBUF_INIT; + if (!o->has_worktree) { /* * Must establish NOTES_MERGE_WORKTREE. * Abort if NOTES_MERGE_WORKTREE already exists */ - if (file_exists(git_path(NOTES_MERGE_WORKTREE)) && - !is_empty_dir(git_path(NOTES_MERGE_WORKTREE))) { + if (file_exists(repo_git_path_replace(the_repository, &buf, NOTES_MERGE_WORKTREE)) && + !is_empty_dir(repo_git_path_replace(the_repository, &buf, NOTES_MERGE_WORKTREE))) { if (advice_enabled(ADVICE_RESOLVE_CONFLICT)) die(_("You have not concluded your previous " "notes merge (%s exists).\nPlease, use " "'git notes merge --commit' or 'git notes " "merge --abort' to commit/abort the " "previous merge before you start a new " - "notes merge."), git_path("NOTES_MERGE_*")); + "notes merge."), repo_git_path_replace(the_repository, &buf, "NOTES_MERGE_*")); else die(_("You have not concluded your notes merge " - "(%s exists)."), git_path("NOTES_MERGE_*")); + "(%s exists)."), repo_git_path_replace(the_repository, &buf, "NOTES_MERGE_*")); } - if (safe_create_leading_directories_const(git_path( + if (safe_create_leading_directories_const(repo_git_path_replace(the_repository, &buf, NOTES_MERGE_WORKTREE "/.test"))) die_errno("unable to create directory %s", - git_path(NOTES_MERGE_WORKTREE)); + repo_git_path_replace(the_repository, &buf, NOTES_MERGE_WORKTREE)); o->has_worktree = 1; - } else if (!file_exists(git_path(NOTES_MERGE_WORKTREE))) + } else if (!file_exists(repo_git_path_replace(the_repository, &buf, NOTES_MERGE_WORKTREE))) /* NOTES_MERGE_WORKTREE should already be established */ die("missing '%s'. This should not happen", - git_path(NOTES_MERGE_WORKTREE)); + repo_git_path_replace(the_repository, &buf, NOTES_MERGE_WORKTREE)); + + strbuf_release(&buf); } static void write_buf_to_worktree(const struct object_id *obj, diff --git a/path.c b/path.c index 2d07ba723d..a42f72800d 100644 --- a/path.c +++ b/path.c @@ -30,7 +30,7 @@ static int get_st_mode_bits(const char *path, int *mode) return 0; } -struct strbuf *get_pathname(void) +static struct strbuf *get_pathname(void) { static struct strbuf pathname_array[4] = { STRBUF_INIT, STRBUF_INIT, STRBUF_INIT, STRBUF_INIT @@ -417,9 +417,9 @@ static void strbuf_worktree_gitdir(struct strbuf *buf, repo_common_path_append(repo, buf, "worktrees/%s", wt->id); } -void repo_git_pathv(const struct repository *repo, - const struct worktree *wt, struct strbuf *buf, - const char *fmt, va_list args) +static void repo_git_pathv(const struct repository *repo, + const struct worktree *wt, struct strbuf *buf, + const char *fmt, va_list args) { int gitdir_len; strbuf_worktree_gitdir(buf, repo, wt); diff --git a/path.h b/path.h index bed0a4c6f9..f28d5a7ca9 100644 --- a/path.h +++ b/path.h @@ -221,37 +221,10 @@ char *xdg_cache_home(const char *filename); */ void safe_create_dir(const char *dir, int share); -/* - * Do not use this function. It is only exported to other subsystems until we - * can get rid of the below block of functions that implicitly rely on - * `the_repository`. - */ -struct strbuf *get_pathname(void); - # ifdef USE_THE_REPOSITORY_VARIABLE # include "strbuf.h" # include "repository.h" -/* Internal implementation details that should not be used. */ -void repo_git_pathv(const struct repository *repo, - const struct worktree *wt, struct strbuf *buf, - const char *fmt, va_list args); - -/* - * Return a statically allocated path into the main repository's - * (the_repository) git directory. - */ -__attribute__((format (printf, 1, 2))) -static inline const char *git_path(const char *fmt, ...) -{ - struct strbuf *pathname = get_pathname(); - va_list args; - va_start(args, fmt); - repo_git_pathv(the_repository, NULL, pathname, fmt, args); - va_end(args); - return pathname->buf; -} - #define GIT_PATH_FUNC(func, filename) \ const char *func(void) \ { \ diff --git a/read-cache.c b/read-cache.c index d54be2c172..66ad0015a7 100644 --- a/read-cache.c +++ b/read-cache.c @@ -3251,15 +3251,18 @@ static int clean_shared_index_files(const char *current_hex) while ((de = readdir(dir)) != NULL) { const char *sha1_hex; - const char *shared_index_path; + char *shared_index_path; if (!skip_prefix(de->d_name, "sharedindex.", &sha1_hex)) continue; if (!strcmp(sha1_hex, current_hex)) continue; - shared_index_path = git_path("%s", de->d_name); + + shared_index_path = repo_git_path(the_repository, "%s", de->d_name); if (should_delete_shared_index(shared_index_path) > 0 && unlink(shared_index_path)) warning_errno(_("unable to unlink: %s"), shared_index_path); + + free(shared_index_path); } closedir(dir); @@ -3271,6 +3274,7 @@ static int write_shared_index(struct index_state *istate, { struct split_index *si = istate->split_index; int ret, was_full = !istate->sparse_index; + char *path; move_cache_to_base_index(istate); convert_to_sparse(istate, 0); @@ -3291,13 +3295,15 @@ static int write_shared_index(struct index_state *istate, error(_("cannot fix permission bits on '%s'"), get_tempfile_path(*temp)); return ret; } - ret = rename_tempfile(temp, - git_path("sharedindex.%s", oid_to_hex(&si->base->oid))); + + path = repo_git_path(the_repository, "sharedindex.%s", oid_to_hex(&si->base->oid)); + ret = rename_tempfile(temp, path); if (!ret) { oidcpy(&si->base_oid, &si->base->oid); clean_shared_index_files(oid_to_hex(&si->base->oid)); } + free(path); return ret; } @@ -3378,9 +3384,12 @@ int write_locked_index(struct index_state *istate, struct lock_file *lock, if (new_shared_index) { struct tempfile *temp; int saved_errno; + char *path; /* Same initial permissions as the main .git/index file */ - temp = mks_tempfile_sm(git_path("sharedindex_XXXXXX"), 0, 0666); + path = repo_git_path(the_repository, "sharedindex_XXXXXX"); + temp = mks_tempfile_sm(path, 0, 0666); + free(path); if (!temp) { ret = do_write_locked_index(istate, lock, flags, ~WRITE_SPLIT_INDEX_EXTENSION); @@ -3401,9 +3410,10 @@ int write_locked_index(struct index_state *istate, struct lock_file *lock, /* Freshen the shared index only if the split-index was written */ if (!ret && !new_shared_index && !is_null_oid(&si->base_oid)) { - const char *shared_index = git_path("sharedindex.%s", - oid_to_hex(&si->base_oid)); + char *shared_index = repo_git_path(the_repository, "sharedindex.%s", + oid_to_hex(&si->base_oid)); freshen_shared_index(shared_index, 1); + free(shared_index); } out: diff --git a/remote.c b/remote.c index 1779f0e7bb..81d151a507 100644 --- a/remote.c +++ b/remote.c @@ -321,10 +321,11 @@ static void read_remotes_file(struct remote_state *remote_state, struct remote *remote) { struct strbuf buf = STRBUF_INIT; - FILE *f = fopen_or_warn(git_path("remotes/%s", remote->name), "r"); + FILE *f = fopen_or_warn(repo_git_path_append(the_repository, &buf, + "remotes/%s", remote->name), "r"); if (!f) - return; + goto out; warn_about_deprecated_remote_type("remotes", remote); @@ -343,8 +344,10 @@ static void read_remotes_file(struct remote_state *remote_state, else if (skip_prefix(buf.buf, "Pull:", &v)) refspec_append(&remote->fetch, skip_spaces(v)); } - strbuf_release(&buf); fclose(f); + +out: + strbuf_release(&buf); } static void read_branches_file(struct remote_state *remote_state, @@ -352,20 +355,19 @@ static void read_branches_file(struct remote_state *remote_state, { char *frag, *to_free = NULL; struct strbuf buf = STRBUF_INIT; - FILE *f = fopen_or_warn(git_path("branches/%s", remote->name), "r"); + FILE *f = fopen_or_warn(repo_git_path_append(the_repository, &buf, + "branches/%s", remote->name), "r"); if (!f) - return; + goto out; warn_about_deprecated_remote_type("branches", remote); strbuf_getline_lf(&buf, f); fclose(f); strbuf_trim(&buf); - if (!buf.len) { - strbuf_release(&buf); - return; - } + if (!buf.len) + goto out; remote->configured_in_repo = 1; remote->origin = REMOTE_BRANCHES; @@ -393,6 +395,7 @@ static void read_branches_file(struct remote_state *remote_state, refspec_appendf(&remote->push, "HEAD:refs/heads/%s", frag); remote->fetch_tags = 1; /* always auto-follow */ +out: strbuf_release(&buf); free(to_free); } diff --git a/rerere.c b/rerere.c index 6dd6b959b5..6bd395bebe 100644 --- a/rerere.c +++ b/rerere.c @@ -127,8 +127,12 @@ static int is_rr_file(const char *name, const char *filename, int *variant) static void scan_rerere_dir(struct rerere_dir *rr_dir) { struct dirent *de; - DIR *dir = opendir(git_path("rr-cache/%s", rr_dir->name)); + char *path; + DIR *dir; + path = repo_git_path(the_repository, "rr-cache/%s", rr_dir->name); + dir = opendir(path); + free(path); if (!dir) return; while ((de = readdir(dir)) != NULL) { @@ -1234,6 +1238,7 @@ void rerere_gc(struct repository *r, struct string_list *rr) timestamp_t now = time(NULL); timestamp_t cutoff_noresolve = now - 15 * 86400; timestamp_t cutoff_resolve = now - 60 * 86400; + struct strbuf buf = STRBUF_INIT; if (setup_rerere(r, rr, 0) < 0) return; @@ -1243,7 +1248,7 @@ void rerere_gc(struct repository *r, struct string_list *rr) repo_config_get_expiry_in_days(the_repository, "gc.rerereunresolved", &cutoff_noresolve, now); git_config(git_default_config, NULL); - dir = opendir(git_path("rr-cache")); + dir = opendir(repo_git_path_replace(the_repository, &buf, "rr-cache")); if (!dir) die_errno(_("unable to open rr-cache directory")); /* Collect stale conflict IDs ... */ @@ -1272,9 +1277,12 @@ void rerere_gc(struct repository *r, struct string_list *rr) /* ... and then remove the empty directories */ for (i = 0; i < to_remove.nr; i++) - rmdir(git_path("rr-cache/%s", to_remove.items[i].string)); + rmdir(repo_git_path_replace(the_repository, &buf, + "rr-cache/%s", to_remove.items[i].string)); + string_list_clear(&to_remove, 0); rollback_lock_file(&write_lock); + strbuf_release(&buf); } /* diff --git a/shallow.c b/shallow.c index b54244ffa9..4bd9342c9a 100644 --- a/shallow.c +++ b/shallow.c @@ -364,7 +364,9 @@ const char *setup_temporary_shallow(const struct oid_array *extra) struct strbuf sb = STRBUF_INIT; if (write_shallow_commits(&sb, 0, extra)) { - temp = xmks_tempfile(git_path("shallow_XXXXXX")); + char *path = repo_git_path(the_repository, "shallow_XXXXXX"); + temp = xmks_tempfile(path); + free(path); if (write_in_full(temp->fd, sb.buf, sb.len) < 0 || close_tempfile_gently(temp) < 0) diff --git a/wt-status.c b/wt-status.c index 3ee9181764..1da5732f57 100644 --- a/wt-status.c +++ b/wt-status.c @@ -1289,7 +1289,8 @@ static void show_am_in_progress(struct wt_status *s, static char *read_line_from_git_path(const char *filename) { struct strbuf buf = STRBUF_INIT; - FILE *fp = fopen_or_warn(git_path("%s", filename), "r"); + FILE *fp = fopen_or_warn(repo_git_path_append(the_repository, &buf, + "%s", filename), "r"); if (!fp) { strbuf_release(&buf); @@ -1383,27 +1384,33 @@ static void abbrev_oid_in_line(struct strbuf *line) static int read_rebase_todolist(const char *fname, struct string_list *lines) { - struct strbuf line = STRBUF_INIT; - FILE *f = fopen(git_path("%s", fname), "r"); + struct strbuf buf = STRBUF_INIT; + FILE *f = fopen(repo_git_path_append(the_repository, &buf, "%s", fname), "r"); + int ret; if (!f) { - if (errno == ENOENT) - return -1; + if (errno == ENOENT) { + ret = -1; + goto out; + } die_errno("Could not open file %s for reading", - git_path("%s", fname)); + repo_git_path_replace(the_repository, &buf, "%s", fname)); } - while (!strbuf_getline_lf(&line, f)) { - if (starts_with(line.buf, comment_line_str)) + while (!strbuf_getline_lf(&buf, f)) { + if (starts_with(buf.buf, comment_line_str)) continue; - strbuf_trim(&line); - if (!line.len) + strbuf_trim(&buf); + if (!buf.len) continue; - abbrev_oid_in_line(&line); - string_list_append(lines, line.buf); + abbrev_oid_in_line(&buf); + string_list_append(lines, buf.buf); } fclose(f); - strbuf_release(&line); - return 0; + + ret = 0; +out: + strbuf_release(&buf); + return ret; } static void show_rebase_information(struct wt_status *s, @@ -1434,9 +1441,12 @@ static void show_rebase_information(struct wt_status *s, i < have_done.nr; i++) status_printf_ln(s, color, " %s", have_done.items[i].string); - if (have_done.nr > nr_lines_to_show && s->hints) + if (have_done.nr > nr_lines_to_show && s->hints) { + char *path = repo_git_path(the_repository, "rebase-merge/done"); status_printf_ln(s, color, - _(" (see more in file %s)"), git_path("rebase-merge/done")); + _(" (see more in file %s)"), path); + free(path); + } } if (yet_to_do.nr == 0) -- cgit v1.3 From 6f3fbed8eda577703426d77dacc71ce0ba46634e Mon Sep 17 00:00:00 2001 From: Patrick Steinhardt Date: Fri, 7 Feb 2025 12:03:39 +0100 Subject: environment: move access to "core.hooksPath" into repo settings The "core.hooksPath" setting is stored in a global variable and populated via the `git_default_core_config`. This may cause issues in the case where one is handling multiple different repositories in a single process with different values for that config key, as we may or may not see the correct value in that case. Furthermore, global state blocks our path towards libification. Refactor the code so that we instead store the value in `struct repo_settings`. The value is computed as-needed and cached. The result should be functionally the same as there aren't ever any code paths where we'd execute hooks outside the context of a repository. Note that this requires us to change the passed-in repository in the `repo_git_path()` family of functions to be non-constant, as we call `adjust_git_path()` there. Signed-off-by: Patrick Steinhardt Signed-off-by: Junio C Hamano --- config.c | 5 ----- environment.c | 1 - environment.h | 1 - path.c | 15 ++++++++------- path.h | 6 +++--- repo-settings.c | 8 ++++++++ repo-settings.h | 4 ++++ 7 files changed, 23 insertions(+), 17 deletions(-) (limited to 'path.c') diff --git a/config.c b/config.c index 50f2d17b39..d932d4b134 100644 --- a/config.c +++ b/config.c @@ -1436,11 +1436,6 @@ static int git_default_core_config(const char *var, const char *value, return git_config_pathname(&git_attributes_file, var, value); } - if (!strcmp(var, "core.hookspath")) { - FREE_AND_NULL(git_hooks_path); - return git_config_pathname(&git_hooks_path, var, value); - } - if (!strcmp(var, "core.bare")) { is_bare_repository_cfg = git_config_bool(var, value); return 0; diff --git a/environment.c b/environment.c index 8389a27270..39755873ee 100644 --- a/environment.c +++ b/environment.c @@ -42,7 +42,6 @@ char *git_log_output_encoding; char *apply_default_whitespace; char *apply_default_ignorewhitespace; char *git_attributes_file; -char *git_hooks_path; int zlib_compression_level = Z_BEST_SPEED; int pack_compression_level = Z_DEFAULT_COMPRESSION; int fsync_object_files = -1; diff --git a/environment.h b/environment.h index 2f43340f0b..66989afbac 100644 --- a/environment.h +++ b/environment.h @@ -160,7 +160,6 @@ extern int warn_on_object_refname_ambiguity; extern char *apply_default_whitespace; extern char *apply_default_ignorewhitespace; extern char *git_attributes_file; -extern char *git_hooks_path; extern int zlib_compression_level; extern int pack_compression_level; extern size_t packed_git_window_size; diff --git a/path.c b/path.c index a42f72800d..e81ebd3b5c 100644 --- a/path.c +++ b/path.c @@ -387,10 +387,11 @@ void report_linked_checkout_garbage(struct repository *r) strbuf_release(&sb); } -static void adjust_git_path(const struct repository *repo, +static void adjust_git_path(struct repository *repo, struct strbuf *buf, int git_dir_len) { const char *base = buf->buf + git_dir_len; + if (is_dir_file(base, "info", "grafts")) strbuf_splice(buf, 0, buf->len, repo->graft_file, strlen(repo->graft_file)); @@ -399,8 +400,8 @@ static void adjust_git_path(const struct repository *repo, repo->index_file, strlen(repo->index_file)); else if (dir_prefix(base, "objects")) replace_dir(buf, git_dir_len + 7, repo->objects->odb->path); - else if (git_hooks_path && dir_prefix(base, "hooks")) - replace_dir(buf, git_dir_len + 5, git_hooks_path); + else if (repo_settings_get_hooks_path(repo) && dir_prefix(base, "hooks")) + replace_dir(buf, git_dir_len + 5, repo_settings_get_hooks_path(repo)); else if (repo->different_commondir) update_common_dir(buf, git_dir_len, repo->commondir); } @@ -417,7 +418,7 @@ static void strbuf_worktree_gitdir(struct strbuf *buf, repo_common_path_append(repo, buf, "worktrees/%s", wt->id); } -static void repo_git_pathv(const struct repository *repo, +static void repo_git_pathv(struct repository *repo, const struct worktree *wt, struct strbuf *buf, const char *fmt, va_list args) { @@ -432,7 +433,7 @@ static void repo_git_pathv(const struct repository *repo, strbuf_cleanup_path(buf); } -char *repo_git_path(const struct repository *repo, +char *repo_git_path(struct repository *repo, const char *fmt, ...) { struct strbuf path = STRBUF_INIT; @@ -443,7 +444,7 @@ char *repo_git_path(const struct repository *repo, return strbuf_detach(&path, NULL); } -const char *repo_git_path_append(const struct repository *repo, +const char *repo_git_path_append(struct repository *repo, struct strbuf *sb, const char *fmt, ...) { @@ -454,7 +455,7 @@ const char *repo_git_path_append(const struct repository *repo, return sb->buf; } -const char *repo_git_path_replace(const struct repository *repo, +const char *repo_git_path_replace(struct repository *repo, struct strbuf *sb, const char *fmt, ...) { diff --git a/path.h b/path.h index f28d5a7ca9..373404dd9d 100644 --- a/path.h +++ b/path.h @@ -52,14 +52,14 @@ const char *repo_common_path_replace(const struct repository *repo, * For an exhaustive list of the adjustments made look at `common_list` and * `adjust_git_path` in path.c. */ -char *repo_git_path(const struct repository *repo, +char *repo_git_path(struct repository *repo, const char *fmt, ...) __attribute__((format (printf, 2, 3))); -const char *repo_git_path_append(const struct repository *repo, +const char *repo_git_path_append(struct repository *repo, struct strbuf *sb, const char *fmt, ...) __attribute__((format (printf, 3, 4))); -const char *repo_git_path_replace(const struct repository *repo, +const char *repo_git_path_replace(struct repository *repo, struct strbuf *sb, const char *fmt, ...) __attribute__((format (printf, 3, 4))); diff --git a/repo-settings.c b/repo-settings.c index 719cd7c85c..876d527581 100644 --- a/repo-settings.c +++ b/repo-settings.c @@ -146,6 +146,7 @@ void repo_settings_clear(struct repository *r) { struct repo_settings empty = REPO_SETTINGS_INIT; FREE_AND_NULL(r->settings.fsmonitor); + FREE_AND_NULL(r->settings.hooks_path); r->settings = empty; } @@ -173,3 +174,10 @@ int repo_settings_get_warn_ambiguous_refs(struct repository *repo) &repo->settings.warn_ambiguous_refs, 1); return repo->settings.warn_ambiguous_refs; } + +const char *repo_settings_get_hooks_path(struct repository *repo) +{ + if (!repo->settings.hooks_path) + repo_config_get_pathname(repo, "core.hookspath", &repo->settings.hooks_path); + return repo->settings.hooks_path; +} diff --git a/repo-settings.h b/repo-settings.h index c4f7e3bd8a..0cef970443 100644 --- a/repo-settings.h +++ b/repo-settings.h @@ -61,6 +61,8 @@ struct repo_settings { size_t delta_base_cache_limit; size_t packed_git_window_size; size_t packed_git_limit; + + char *hooks_path; }; #define REPO_SETTINGS_INIT { \ .index_version = -1, \ @@ -79,5 +81,7 @@ void repo_settings_clear(struct repository *r); enum log_refs_config repo_settings_get_log_all_ref_updates(struct repository *repo); /* Read the value for "core.warnAmbiguousRefs". */ int repo_settings_get_warn_ambiguous_refs(struct repository *repo); +/* Read the value for "core.hooksPath". */ +const char *repo_settings_get_hooks_path(struct repository *repo); #endif /* REPO_SETTINGS_H */ -- cgit v1.3 From f1ce861c34bffbc02998173016b0bca0f6d9f6c4 Mon Sep 17 00:00:00 2001 From: Patrick Steinhardt Date: Fri, 7 Feb 2025 12:03:40 +0100 Subject: environment: move access to "core.sharedRepository" into repo settings Similar as with the preceding commit, we track "core.sharedRepository" via a pair of global variables. Move them into `struct repo_settings` so that we can instead track them per-repository. Signed-off-by: Patrick Steinhardt Signed-off-by: Junio C Hamano --- builtin/init-db.c | 8 ++++---- builtin/log.c | 6 +++--- environment.c | 26 -------------------------- environment.h | 10 ---------- path.c | 10 +++++----- repo-settings.c | 26 ++++++++++++++++++++++++++ repo-settings.h | 9 +++++++++ setup.c | 21 +++++++++++---------- 8 files changed, 58 insertions(+), 58 deletions(-) (limited to 'path.c') diff --git a/builtin/init-db.c b/builtin/init-db.c index 096f96b9c4..196dccdd77 100644 --- a/builtin/init-db.c +++ b/builtin/init-db.c @@ -132,8 +132,8 @@ int cmd_init_db(int argc, * and we know shared_repository should always be 0; * but just in case we play safe. */ - saved = get_shared_repository(); - set_shared_repository(0); + saved = repo_settings_get_shared_repository(the_repository); + repo_settings_set_shared_repository(the_repository, 0); switch (safe_create_leading_directories_const(argv[0])) { case SCLD_OK: case SCLD_PERMS: @@ -145,7 +145,7 @@ int cmd_init_db(int argc, die_errno(_("cannot mkdir %s"), argv[0]); break; } - set_shared_repository(saved); + repo_settings_set_shared_repository(the_repository, saved); if (mkdir(argv[0], 0777) < 0) die_errno(_("cannot mkdir %s"), argv[0]); mkdir_tried = 1; @@ -175,7 +175,7 @@ int cmd_init_db(int argc, } if (init_shared_repository != -1) - set_shared_repository(init_shared_repository); + repo_settings_set_shared_repository(the_repository, init_shared_repository); /* * GIT_WORK_TREE makes sense only in conjunction with GIT_DIR diff --git a/builtin/log.c b/builtin/log.c index e41f88945e..04a6ef97bc 100644 --- a/builtin/log.c +++ b/builtin/log.c @@ -2309,8 +2309,8 @@ int cmd_format_patch(int argc, * We consider as 'outside of gitdir', therefore avoid * applying adjust_shared_perm in s-c-l-d. */ - saved = get_shared_repository(); - set_shared_repository(0); + saved = repo_settings_get_shared_repository(the_repository); + repo_settings_set_shared_repository(the_repository, 0); switch (safe_create_leading_directories_const(output_directory)) { case SCLD_OK: case SCLD_EXISTS: @@ -2319,7 +2319,7 @@ int cmd_format_patch(int argc, die(_("could not create leading directories " "of '%s'"), output_directory); } - set_shared_repository(saved); + repo_settings_set_shared_repository(the_repository, saved); if (mkdir(output_directory, 0777) < 0 && errno != EEXIST) die_errno(_("could not create directory '%s'"), output_directory); diff --git a/environment.c b/environment.c index 39755873ee..c79acc69e7 100644 --- a/environment.c +++ b/environment.c @@ -206,32 +206,6 @@ const char *get_commit_output_encoding(void) return git_commit_encoding ? git_commit_encoding : "UTF-8"; } -static int the_shared_repository = PERM_UMASK; -static int need_shared_repository_from_config = 1; - -void set_shared_repository(int value) -{ - the_shared_repository = value; - need_shared_repository_from_config = 0; -} - -int get_shared_repository(void) -{ - if (need_shared_repository_from_config) { - const char *var = "core.sharedrepository"; - const char *value; - if (!git_config_get_value(var, &value)) - the_shared_repository = git_config_perm(var, value); - need_shared_repository_from_config = 0; - } - return the_shared_repository; -} - -void reset_shared_repository(void) -{ - need_shared_repository_from_config = 1; -} - int use_optional_locks(void) { return git_env_bool(GIT_OPTIONAL_LOCKS_ENVIRONMENT, 1); diff --git a/environment.h b/environment.h index 66989afbac..45e690f203 100644 --- a/environment.h +++ b/environment.h @@ -134,16 +134,6 @@ void setup_git_env(const char *git_dir); */ int have_git_dir(void); -/* - * Accessors for the core.sharedrepository config which lazy-load the value - * from the config (if not already set). The "reset" function can be - * used to unset "set" or cached value, meaning that the value will be loaded - * fresh from the config file on the next call to get_shared_repository(). - */ -void set_shared_repository(int value); -int get_shared_repository(void); -void reset_shared_repository(void); - extern int is_bare_repository_cfg; int is_bare_repository(void); extern char *git_work_tree_cfg; diff --git a/path.c b/path.c index e81ebd3b5c..a2f402baec 100644 --- a/path.c +++ b/path.c @@ -844,17 +844,17 @@ int calc_shared_perm(int mode) { int tweak; - if (get_shared_repository() < 0) - tweak = -get_shared_repository(); + if (repo_settings_get_shared_repository(the_repository) < 0) + tweak = -repo_settings_get_shared_repository(the_repository); else - tweak = get_shared_repository(); + tweak = repo_settings_get_shared_repository(the_repository); if (!(mode & S_IWUSR)) tweak &= ~0222; if (mode & S_IXUSR) /* Copy read bits to execute bits */ tweak |= (tweak & 0444) >> 2; - if (get_shared_repository() < 0) + if (repo_settings_get_shared_repository(the_repository) < 0) mode = (mode & ~0777) | tweak; else mode |= tweak; @@ -867,7 +867,7 @@ int adjust_shared_perm(const char *path) { int old_mode, new_mode; - if (!get_shared_repository()) + if (!repo_settings_get_shared_repository(the_repository)) return 0; if (get_st_mode_bits(path, &old_mode) < 0) return -1; diff --git a/repo-settings.c b/repo-settings.c index 876d527581..67e9cfd2e6 100644 --- a/repo-settings.c +++ b/repo-settings.c @@ -4,6 +4,7 @@ #include "repository.h" #include "midx.h" #include "pack-objects.h" +#include "setup.h" static void repo_cfg_bool(struct repository *r, const char *key, int *dest, int def) @@ -181,3 +182,28 @@ const char *repo_settings_get_hooks_path(struct repository *repo) repo_config_get_pathname(repo, "core.hookspath", &repo->settings.hooks_path); return repo->settings.hooks_path; } + +int repo_settings_get_shared_repository(struct repository *repo) +{ + if (!repo->settings.shared_repository_initialized) { + const char *var = "core.sharedrepository"; + const char *value; + if (!repo_config_get_value(repo, var, &value)) + repo->settings.shared_repository = git_config_perm(var, value); + else + repo->settings.shared_repository = PERM_UMASK; + repo->settings.shared_repository_initialized = 1; + } + return repo->settings.shared_repository; +} + +void repo_settings_set_shared_repository(struct repository *repo, int value) +{ + repo->settings.shared_repository = value; + repo->settings.shared_repository_initialized = 1; +} + +void repo_settings_reset_shared_repository(struct repository *repo) +{ + repo->settings.shared_repository_initialized = 0; +} diff --git a/repo-settings.h b/repo-settings.h index 0cef970443..ddc11967e0 100644 --- a/repo-settings.h +++ b/repo-settings.h @@ -37,6 +37,9 @@ struct repo_settings { int pack_use_bitmap_boundary_traversal; int pack_use_multi_pack_reuse; + int shared_repository; + int shared_repository_initialized; + /* * Does this repository have core.useReplaceRefs=true (on by * default)? This provides a repository-scoped version of this @@ -65,6 +68,7 @@ struct repo_settings { char *hooks_path; }; #define REPO_SETTINGS_INIT { \ + .shared_repository = -1, \ .index_version = -1, \ .core_untracked_cache = UNTRACKED_CACHE_KEEP, \ .fetch_negotiation_algorithm = FETCH_NEGOTIATION_CONSECUTIVE, \ @@ -84,4 +88,9 @@ int repo_settings_get_warn_ambiguous_refs(struct repository *repo); /* Read the value for "core.hooksPath". */ const char *repo_settings_get_hooks_path(struct repository *repo); +/* Read, set or reset the value for "core.sharedRepository". */ +int repo_settings_get_shared_repository(struct repository *repo); +void repo_settings_set_shared_repository(struct repository *repo, int value); +void repo_settings_reset_shared_repository(struct repository *repo); + #endif /* REPO_SETTINGS_H */ diff --git a/setup.c b/setup.c index 30889386f7..aa65b93f53 100644 --- a/setup.c +++ b/setup.c @@ -2332,7 +2332,7 @@ static int create_default_files(const char *template_path, */ copy_templates(template_path); git_config_clear(); - reset_shared_repository(); + repo_settings_reset_shared_repository(the_repository); git_config(git_default_config, NULL); reinit = is_reinit(); @@ -2342,7 +2342,8 @@ static int create_default_files(const char *template_path, * values we might have just re-read from the config. */ if (init_shared_repository != -1) - set_shared_repository(init_shared_repository); + repo_settings_set_shared_repository(the_repository, + init_shared_repository); is_bare_repository_cfg = !work_tree; @@ -2350,7 +2351,7 @@ static int create_default_files(const char *template_path, * We would have created the above under user's umask -- under * shared-repository settings, we would need to fix them up. */ - if (get_shared_repository()) { + if (repo_settings_get_shared_repository(the_repository)) { adjust_shared_perm(repo_get_git_dir(the_repository)); } @@ -2597,7 +2598,7 @@ int init_db(const char *git_dir, const char *real_git_dir, initial_branch, flags & INIT_DB_QUIET); create_object_directory(); - if (get_shared_repository()) { + if (repo_settings_get_shared_repository(the_repository)) { char buf[10]; /* We do not spell "group" and such, so that * the configuration can be read by older version @@ -2605,12 +2606,12 @@ int init_db(const char *git_dir, const char *real_git_dir, * and compatibility values for PERM_GROUP and * PERM_EVERYBODY. */ - if (get_shared_repository() < 0) + if (repo_settings_get_shared_repository(the_repository) < 0) /* force to the mode value */ - xsnprintf(buf, sizeof(buf), "0%o", -get_shared_repository()); - else if (get_shared_repository() == PERM_GROUP) + xsnprintf(buf, sizeof(buf), "0%o", -repo_settings_get_shared_repository(the_repository)); + else if (repo_settings_get_shared_repository(the_repository) == PERM_GROUP) xsnprintf(buf, sizeof(buf), "%d", OLD_PERM_GROUP); - else if (get_shared_repository() == PERM_EVERYBODY) + else if (repo_settings_get_shared_repository(the_repository) == PERM_EVERYBODY) xsnprintf(buf, sizeof(buf), "%d", OLD_PERM_EVERYBODY); else BUG("invalid value for shared_repository"); @@ -2622,12 +2623,12 @@ int init_db(const char *git_dir, const char *real_git_dir, int len = strlen(git_dir); if (reinit) - printf(get_shared_repository() + printf(repo_settings_get_shared_repository(the_repository) ? _("Reinitialized existing shared Git repository in %s%s\n") : _("Reinitialized existing Git repository in %s%s\n"), git_dir, len && git_dir[len-1] != '/' ? "/" : ""); else - printf(get_shared_repository() + printf(repo_settings_get_shared_repository(the_repository) ? _("Initialized empty shared Git repository in %s%s\n") : _("Initialized empty Git repository in %s%s\n"), git_dir, len && git_dir[len-1] != '/' ? "/" : ""); -- cgit v1.3 From 028f618658e34230e1d65678f14b6876e0f9856d Mon Sep 17 00:00:00 2001 From: Patrick Steinhardt Date: Fri, 7 Feb 2025 12:03:41 +0100 Subject: path: adjust last remaining users of `the_repository` With the preceding refactorings we now only have a couple of implicit users of `the_repository` left in the "path" subsystem, all of which depend on global state via `calc_shared_perm()`. Make the dependency on `the_repository` explicit by passing the repo as a parameter instead and adjust callers accordingly. Note that this change bubbles up into a couple of subsystems that were previously declared as free from `the_repository`. Instead of marking all of them as `the_repository`-dependent again, we instead use the repository that is available in the calling context. There are three exceptions though with "copy.c", "pack-write.c" and "tempfile.c". Adjusting these would require us to adapt callsites all over the place, so this is left for a future iteration. Mark "path.c" as free from `the_repository`. Signed-off-by: Patrick Steinhardt Signed-off-by: Junio C Hamano --- builtin/clone.c | 2 +- commit-graph.c | 2 +- copy.c | 4 +++- loose.c | 2 +- midx-write.c | 2 +- object-file.c | 8 ++++---- pack-bitmap-write.c | 2 +- pack-write.c | 10 ++++++---- path.c | 25 ++++++++++++------------- path.h | 6 +++--- read-cache.c | 2 +- refs/files-backend.c | 10 +++++----- refs/reftable-backend.c | 10 +++++----- server-info.c | 2 +- setup.c | 12 ++++++------ tempfile.c | 4 +++- tmp-objdir.c | 17 ++++++++++------- 17 files changed, 64 insertions(+), 56 deletions(-) (limited to 'path.c') diff --git a/builtin/clone.c b/builtin/clone.c index 5ae6ee9db9..23eeb782aa 100644 --- a/builtin/clone.c +++ b/builtin/clone.c @@ -1220,7 +1220,7 @@ int cmd_clone(int argc, strbuf_reset(&buf); strbuf_addf(&buf, "%s/refs", git_dir); - safe_create_dir(buf.buf, 1); + safe_create_dir(the_repository, buf.buf, 1); /* * additional config can be injected with -c, make sure it's included diff --git a/commit-graph.c b/commit-graph.c index 2a2999a6b8..1021ccb983 100644 --- a/commit-graph.c +++ b/commit-graph.c @@ -2084,7 +2084,7 @@ static int write_commit_graph_file(struct write_commit_graph_context *ctx) return -1; } - if (adjust_shared_perm(get_tempfile_path(graph_layer))) { + if (adjust_shared_perm(the_repository, get_tempfile_path(graph_layer))) { error(_("unable to adjust shared permissions for '%s'"), get_tempfile_path(graph_layer)); return -1; diff --git a/copy.c b/copy.c index d9d2092012..b668209b6c 100644 --- a/copy.c +++ b/copy.c @@ -1,3 +1,5 @@ +#define USE_THE_REPOSITORY_VARIABLE + #include "git-compat-util.h" #include "copy.h" #include "path.h" @@ -57,7 +59,7 @@ int copy_file(const char *dst, const char *src, int mode) if (close(fdo) != 0) return error_errno("%s: close error", dst); - if (!status && adjust_shared_perm(dst)) + if (!status && adjust_shared_perm(the_repository, dst)) return -1; return status; diff --git a/loose.c b/loose.c index 51ef490f93..bb602aaa36 100644 --- a/loose.c +++ b/loose.c @@ -190,7 +190,7 @@ static int write_one_object(struct repository *repo, const struct object_id *oid goto errout; if (close(fd)) goto errout; - adjust_shared_perm(path.buf); + adjust_shared_perm(repo, path.buf); rollback_lock_file(&lock); strbuf_release(&buf); strbuf_release(&path); diff --git a/midx-write.c b/midx-write.c index 61b59d557d..48d6558253 100644 --- a/midx-write.c +++ b/midx-write.c @@ -1336,7 +1336,7 @@ static int write_midx_internal(struct repository *r, const char *object_dir, return -1; } - if (adjust_shared_perm(get_tempfile_path(incr))) { + if (adjust_shared_perm(r, get_tempfile_path(incr))) { error(_("unable to adjust shared permissions for '%s'"), get_tempfile_path(incr)); return -1; diff --git a/object-file.c b/object-file.c index dc9fcaf3e9..5d782417e3 100644 --- a/object-file.c +++ b/object-file.c @@ -388,7 +388,7 @@ int mkdir_in_gitdir(const char *path) } strbuf_release(&sb); } - return adjust_shared_perm(path); + return adjust_shared_perm(the_repository, path); } static enum scld_error safe_create_leading_directories_1(char *path, int share) @@ -437,7 +437,7 @@ static enum scld_error safe_create_leading_directories_1(char *path, int share) ret = SCLD_VANISHED; else ret = SCLD_FAILED; - } else if (share && adjust_shared_perm(path)) { + } else if (share && adjust_shared_perm(the_repository, path)) { ret = SCLD_PERMS; } *slash = slash_character; @@ -2105,7 +2105,7 @@ retry: } out: - if (adjust_shared_perm(filename)) + if (adjust_shared_perm(the_repository, filename)) return error(_("unable to set permission to '%s'"), filename); return 0; } @@ -2181,7 +2181,7 @@ static int create_tmpfile(struct strbuf *tmp, const char *filename) strbuf_add(tmp, filename, dirlen - 1); if (mkdir(tmp->buf, 0777) && errno != EEXIST) return -1; - if (adjust_shared_perm(tmp->buf)) + if (adjust_shared_perm(the_repository, tmp->buf)) return -1; /* Try again */ diff --git a/pack-bitmap-write.c b/pack-bitmap-write.c index a06a1f35c6..34e86d4994 100644 --- a/pack-bitmap-write.c +++ b/pack-bitmap-write.c @@ -1072,7 +1072,7 @@ void bitmap_writer_finish(struct bitmap_writer *writer, finalize_hashfile(f, NULL, FSYNC_COMPONENT_PACK_METADATA, CSUM_HASH_IN_STREAM | CSUM_FSYNC | CSUM_CLOSE); - if (adjust_shared_perm(tmp_file.buf)) + if (adjust_shared_perm(the_repository, tmp_file.buf)) die_errno("unable to make temporary bitmap file readable"); if (rename(tmp_file.buf, filename)) diff --git a/pack-write.c b/pack-write.c index a2faeb1895..c3f4e66f02 100644 --- a/pack-write.c +++ b/pack-write.c @@ -1,3 +1,5 @@ +#define USE_THE_REPOSITORY_VARIABLE + #include "git-compat-util.h" #include "environment.h" #include "gettext.h" @@ -287,7 +289,7 @@ char *write_rev_file_order(const struct git_hash_algo *hash_algo, write_rev_index_positions(f, pack_order, nr_objects); write_rev_trailer(hash_algo, f, hash); - if (adjust_shared_perm(path) < 0) + if (adjust_shared_perm(the_repository, path) < 0) die(_("failed to make %s readable"), path); finalize_hashfile(f, NULL, FSYNC_COMPONENT_PACK_METADATA, @@ -350,7 +352,7 @@ static char *write_mtimes_file(const struct git_hash_algo *hash_algo, write_mtimes_objects(f, to_pack, objects, nr_objects); write_mtimes_trailer(hash_algo, f, hash); - if (adjust_shared_perm(mtimes_name) < 0) + if (adjust_shared_perm(the_repository, mtimes_name) < 0) die(_("failed to make %s readable"), mtimes_name); finalize_hashfile(f, NULL, FSYNC_COMPONENT_PACK_METADATA, @@ -565,12 +567,12 @@ void stage_tmp_packfiles(const struct git_hash_algo *hash_algo, char *rev_tmp_name = NULL; char *mtimes_tmp_name = NULL; - if (adjust_shared_perm(pack_tmp_name)) + if (adjust_shared_perm(the_repository, pack_tmp_name)) die_errno("unable to make temporary pack file readable"); *idx_tmp_name = (char *)write_idx_file(hash_algo, NULL, written_list, nr_written, pack_idx_opts, hash); - if (adjust_shared_perm(*idx_tmp_name)) + if (adjust_shared_perm(the_repository, *idx_tmp_name)) die_errno("unable to make temporary index file readable"); rev_tmp_name = write_rev_file(hash_algo, NULL, written_list, nr_written, diff --git a/path.c b/path.c index a2f402baec..910756c8b3 100644 --- a/path.c +++ b/path.c @@ -2,8 +2,6 @@ * Utilities for paths and pathnames */ -#define USE_THE_REPOSITORY_VARIABLE - #include "git-compat-util.h" #include "abspath.h" #include "environment.h" @@ -840,21 +838,22 @@ const char *enter_repo(const char *path, unsigned flags) return NULL; } -int calc_shared_perm(int mode) +int calc_shared_perm(struct repository *repo, + int mode) { int tweak; - if (repo_settings_get_shared_repository(the_repository) < 0) - tweak = -repo_settings_get_shared_repository(the_repository); + if (repo_settings_get_shared_repository(repo) < 0) + tweak = -repo_settings_get_shared_repository(repo); else - tweak = repo_settings_get_shared_repository(the_repository); + tweak = repo_settings_get_shared_repository(repo); if (!(mode & S_IWUSR)) tweak &= ~0222; if (mode & S_IXUSR) /* Copy read bits to execute bits */ tweak |= (tweak & 0444) >> 2; - if (repo_settings_get_shared_repository(the_repository) < 0) + if (repo_settings_get_shared_repository(repo) < 0) mode = (mode & ~0777) | tweak; else mode |= tweak; @@ -862,17 +861,17 @@ int calc_shared_perm(int mode) return mode; } - -int adjust_shared_perm(const char *path) +int adjust_shared_perm(struct repository *repo, + const char *path) { int old_mode, new_mode; - if (!repo_settings_get_shared_repository(the_repository)) + if (!repo_settings_get_shared_repository(repo)) return 0; if (get_st_mode_bits(path, &old_mode) < 0) return -1; - new_mode = calc_shared_perm(old_mode); + new_mode = calc_shared_perm(repo, old_mode); if (S_ISDIR(old_mode)) { /* Copy read bits to execute bits */ new_mode |= (new_mode & 0444) >> 2; @@ -891,7 +890,7 @@ int adjust_shared_perm(const char *path) return 0; } -void safe_create_dir(const char *dir, int share) +void safe_create_dir(struct repository *repo, const char *dir, int share) { if (mkdir(dir, 0777) < 0) { if (errno != EEXIST) { @@ -899,7 +898,7 @@ void safe_create_dir(const char *dir, int share) exit(1); } } - else if (share && adjust_shared_perm(dir)) + else if (share && adjust_shared_perm(repo, dir)) die(_("Could not make %s writable by group"), dir); } diff --git a/path.h b/path.h index 373404dd9d..65fe968a13 100644 --- a/path.h +++ b/path.h @@ -141,8 +141,8 @@ const char *git_path_shallow(struct repository *r); int ends_with_path_components(const char *path, const char *components); -int calc_shared_perm(int mode); -int adjust_shared_perm(const char *path); +int calc_shared_perm(struct repository *repo, int mode); +int adjust_shared_perm(struct repository *repo, const char *path); char *interpolate_path(const char *path, int real_home); @@ -219,7 +219,7 @@ char *xdg_cache_home(const char *filename); * directories under $GIT_DIR. Don't use it for working tree * directories. */ -void safe_create_dir(const char *dir, int share); +void safe_create_dir(struct repository *repo, const char *dir, int share); # ifdef USE_THE_REPOSITORY_VARIABLE # include "strbuf.h" diff --git a/read-cache.c b/read-cache.c index 66ad0015a7..900738e7a8 100644 --- a/read-cache.c +++ b/read-cache.c @@ -3290,7 +3290,7 @@ static int write_shared_index(struct index_state *istate, if (ret) return ret; - ret = adjust_shared_perm(get_tempfile_path(*temp)); + ret = adjust_shared_perm(the_repository, get_tempfile_path(*temp)); if (ret) { error(_("cannot fix permission bits on '%s'"), get_tempfile_path(*temp)); return ret; diff --git a/refs/files-backend.c b/refs/files-backend.c index 29f08dced4..6c6e67dc1c 100644 --- a/refs/files-backend.c +++ b/refs/files-backend.c @@ -1831,7 +1831,7 @@ static int log_ref_setup(struct files_ref_store *refs, } if (*logfd >= 0) - adjust_shared_perm(logfile); + adjust_shared_perm(the_repository, logfile); free(logfile); return 0; @@ -3488,8 +3488,8 @@ static int files_ref_store_create_on_disk(struct ref_store *ref_store, * they do not understand the reference format extension. */ strbuf_addf(&sb, "%s/refs", ref_store->gitdir); - safe_create_dir(sb.buf, 1); - adjust_shared_perm(sb.buf); + safe_create_dir(the_repository, sb.buf, 1); + adjust_shared_perm(the_repository, sb.buf); /* * There is no need to create directories for common refs when creating @@ -3501,11 +3501,11 @@ static int files_ref_store_create_on_disk(struct ref_store *ref_store, */ strbuf_reset(&sb); files_ref_path(refs, &sb, "refs/heads"); - safe_create_dir(sb.buf, 1); + safe_create_dir(the_repository, sb.buf, 1); strbuf_reset(&sb); files_ref_path(refs, &sb, "refs/tags"); - safe_create_dir(sb.buf, 1); + safe_create_dir(the_repository, sb.buf, 1); } strbuf_release(&sb); diff --git a/refs/reftable-backend.c b/refs/reftable-backend.c index d39a14c5a4..9c54e2c173 100644 --- a/refs/reftable-backend.c +++ b/refs/reftable-backend.c @@ -380,7 +380,7 @@ static struct ref_store *reftable_be_init(struct repository *repo, default: BUG("unknown hash algorithm %d", repo->hash_algo->format_id); } - refs->write_options.default_permissions = calc_shared_perm(0666 & ~mask); + refs->write_options.default_permissions = calc_shared_perm(the_repository, 0666 & ~mask); refs->write_options.disable_auto_compact = !git_env_bool("GIT_TEST_REFTABLE_AUTOCOMPACTION", 1); refs->write_options.lock_timeout_ms = 100; @@ -470,21 +470,21 @@ static int reftable_be_create_on_disk(struct ref_store *ref_store, struct strbuf sb = STRBUF_INIT; strbuf_addf(&sb, "%s/reftable", refs->base.gitdir); - safe_create_dir(sb.buf, 1); + safe_create_dir(the_repository, sb.buf, 1); strbuf_reset(&sb); strbuf_addf(&sb, "%s/HEAD", refs->base.gitdir); write_file(sb.buf, "ref: refs/heads/.invalid"); - adjust_shared_perm(sb.buf); + adjust_shared_perm(the_repository, sb.buf); strbuf_reset(&sb); strbuf_addf(&sb, "%s/refs", refs->base.gitdir); - safe_create_dir(sb.buf, 1); + safe_create_dir(the_repository, sb.buf, 1); strbuf_reset(&sb); strbuf_addf(&sb, "%s/refs/heads", refs->base.gitdir); write_file(sb.buf, "this repository uses the reftable format"); - adjust_shared_perm(sb.buf); + adjust_shared_perm(the_repository, sb.buf); strbuf_release(&sb); return 0; diff --git a/server-info.c b/server-info.c index 31c3fdc118..1ca0e00d51 100644 --- a/server-info.c +++ b/server-info.c @@ -125,7 +125,7 @@ static int update_info_file(struct repository *r, char *path, uic.cur_fp = NULL; if (uic_is_stale(&uic)) { - if (adjust_shared_perm(get_tempfile_path(f)) < 0) + if (adjust_shared_perm(r, get_tempfile_path(f)) < 0) goto out; if (rename_tempfile(&f, path) < 0) goto out; diff --git a/setup.c b/setup.c index aa65b93f53..71a3d66f05 100644 --- a/setup.c +++ b/setup.c @@ -2088,7 +2088,7 @@ static void copy_templates_1(struct strbuf *path, struct strbuf *template_path, * with the way the namespace under .git/ is organized, should * be really carefully chosen. */ - safe_create_dir(path->buf, 1); + safe_create_dir(the_repository, path->buf, 1); while ((de = readdir(dir)) != NULL) { struct stat st_git, st_template; int exists = 0; @@ -2352,7 +2352,7 @@ static int create_default_files(const char *template_path, * shared-repository settings, we would need to fix them up. */ if (repo_settings_get_shared_repository(the_repository)) { - adjust_shared_perm(repo_get_git_dir(the_repository)); + adjust_shared_perm(the_repository, repo_get_git_dir(the_repository)); } initialize_repository_version(fmt->hash_algo, fmt->ref_storage_format, reinit); @@ -2413,15 +2413,15 @@ static void create_object_directory(void) strbuf_addstr(&path, repo_get_object_directory(the_repository)); baselen = path.len; - safe_create_dir(path.buf, 1); + safe_create_dir(the_repository, path.buf, 1); strbuf_setlen(&path, baselen); strbuf_addstr(&path, "/pack"); - safe_create_dir(path.buf, 1); + safe_create_dir(the_repository, path.buf, 1); strbuf_setlen(&path, baselen); strbuf_addstr(&path, "/info"); - safe_create_dir(path.buf, 1); + safe_create_dir(the_repository, path.buf, 1); strbuf_release(&path); } @@ -2588,7 +2588,7 @@ int init_db(const char *git_dir, const char *real_git_dir, */ git_config(platform_core_config, NULL); - safe_create_dir(git_dir, 0); + safe_create_dir(the_repository, git_dir, 0); reinit = create_default_files(template_dir, original_git_dir, &repo_fmt, init_shared_repository); diff --git a/tempfile.c b/tempfile.c index ed88cf8431..82dfa3d82f 100644 --- a/tempfile.c +++ b/tempfile.c @@ -42,6 +42,8 @@ * file created by its parent. */ +#define USE_THE_REPOSITORY_VARIABLE + #include "git-compat-util.h" #include "abspath.h" #include "path.h" @@ -148,7 +150,7 @@ struct tempfile *create_tempfile_mode(const char *path, int mode) return NULL; } activate_tempfile(tempfile); - if (adjust_shared_perm(tempfile->filename.buf)) { + if (adjust_shared_perm(the_repository, tempfile->filename.buf)) { int save_errno = errno; error("cannot fix permission bits on %s", tempfile->filename.buf); delete_tempfile(&tempfile); diff --git a/tmp-objdir.c b/tmp-objdir.c index 0ea078a5c5..31d16a4c2c 100644 --- a/tmp-objdir.c +++ b/tmp-objdir.c @@ -207,10 +207,12 @@ static int read_dir_paths(struct string_list *out, const char *path) return 0; } -static int migrate_paths(struct strbuf *src, struct strbuf *dst, +static int migrate_paths(struct tmp_objdir *t, + struct strbuf *src, struct strbuf *dst, enum finalize_object_file_flags flags); -static int migrate_one(struct strbuf *src, struct strbuf *dst, +static int migrate_one(struct tmp_objdir *t, + struct strbuf *src, struct strbuf *dst, enum finalize_object_file_flags flags) { struct stat st; @@ -219,11 +221,11 @@ static int migrate_one(struct strbuf *src, struct strbuf *dst, return -1; if (S_ISDIR(st.st_mode)) { if (!mkdir(dst->buf, 0777)) { - if (adjust_shared_perm(dst->buf)) + if (adjust_shared_perm(t->repo, dst->buf)) return -1; } else if (errno != EEXIST) return -1; - return migrate_paths(src, dst, flags); + return migrate_paths(t, src, dst, flags); } return finalize_object_file_flags(src->buf, dst->buf, flags); } @@ -233,7 +235,8 @@ static int is_loose_object_shard(const char *name) return strlen(name) == 2 && isxdigit(name[0]) && isxdigit(name[1]); } -static int migrate_paths(struct strbuf *src, struct strbuf *dst, +static int migrate_paths(struct tmp_objdir *t, + struct strbuf *src, struct strbuf *dst, enum finalize_object_file_flags flags) { size_t src_len = src->len, dst_len = dst->len; @@ -255,7 +258,7 @@ static int migrate_paths(struct strbuf *src, struct strbuf *dst, if (is_loose_object_shard(name)) flags_copy |= FOF_SKIP_COLLISION_CHECK; - ret |= migrate_one(src, dst, flags_copy); + ret |= migrate_one(t, src, dst, flags_copy); strbuf_setlen(src, src_len); strbuf_setlen(dst, dst_len); @@ -283,7 +286,7 @@ int tmp_objdir_migrate(struct tmp_objdir *t) strbuf_addbuf(&src, &t->path); strbuf_addstr(&dst, repo_get_object_directory(t->repo)); - ret = migrate_paths(&src, &dst, 0); + ret = migrate_paths(t, &src, &dst, 0); strbuf_release(&src); strbuf_release(&dst); -- cgit v1.3