Merge branch 'ps/path-sans-the-repository'

The path.[ch] API takes an explicit repository parameter passed
throughout the callchain, instead of relying on the_repository
singleton instance.

* ps/path-sans-the-repository:
  path: adjust last remaining users of `the_repository`
  environment: move access to "core.sharedRepository" into repo settings
  environment: move access to "core.hooksPath" into repo settings
  repo-settings: introduce function to clear struct
  path: drop `git_path()` in favor of `repo_git_path()`
  rerere: let `rerere_path()` write paths into a caller-provided buffer
  path: drop `git_common_path()` in favor of `repo_common_path()`
  worktree: return allocated string from `get_worktree_git_dir()`
  path: drop `git_path_buf()` in favor of `repo_git_path_replace()`
  path: drop `git_pathdup()` in favor of `repo_git_path()`
  path: drop unused `strbuf_git_path()` function
  path: refactor `repo_submodule_path()` family of functions
  submodule: refactor `submodule_to_gitdir()` to accept a repo
  path: refactor `repo_worktree_path()` family of functions
  path: refactor `repo_git_path()` family of functions
  path: refactor `repo_common_path()` family of functions
This commit is contained in:
Junio C Hamano 2025-03-05 10:37:43 -08:00
commit feffb34257
62 changed files with 644 additions and 495 deletions

View File

@ -930,7 +930,7 @@ static enum bisect_error check_good_are_ancestors_of_bad(struct repository *r,
if (!current_bad_oid) if (!current_bad_oid)
return error(_("a %s revision is needed"), term_bad); return error(_("a %s revision is needed"), term_bad);
filename = git_pathdup("BISECT_ANCESTORS_OK"); filename = repo_git_path(the_repository, "BISECT_ANCESTORS_OK");
/* Check if file BISECT_ANCESTORS_OK exists. */ /* Check if file BISECT_ANCESTORS_OK exists. */
if (!stat(filename, &st) && S_ISREG(st.st_mode)) if (!stat(filename, &st) && S_ISREG(st.st_mode))

View File

@ -397,7 +397,7 @@ static void prepare_checked_out_branches(void)
worktrees = get_worktrees(); worktrees = get_worktrees();
while (worktrees[i]) { while (worktrees[i]) {
char *old; char *old, *wt_gitdir;
struct wt_status_state state = { 0 }; struct wt_status_state state = { 0 };
struct worktree *wt = worktrees[i++]; struct worktree *wt = worktrees[i++];
struct string_list update_refs = STRING_LIST_INIT_DUP; struct string_list update_refs = STRING_LIST_INIT_DUP;
@ -437,7 +437,8 @@ static void prepare_checked_out_branches(void)
} }
wt_status_state_free_buffers(&state); wt_status_state_free_buffers(&state);
if (!sequencer_get_update_refs_state(get_worktree_git_dir(wt), wt_gitdir = get_worktree_git_dir(wt);
if (!sequencer_get_update_refs_state(wt_gitdir,
&update_refs)) { &update_refs)) {
struct string_list_item *item; struct string_list_item *item;
for_each_string_list_item(item, &update_refs) { for_each_string_list_item(item, &update_refs) {
@ -448,6 +449,8 @@ static void prepare_checked_out_branches(void)
} }
string_list_clear(&update_refs, 1); string_list_clear(&update_refs, 1);
} }
free(wt_gitdir);
} }
free_worktrees(worktrees); free_worktrees(worktrees);

View File

@ -158,7 +158,7 @@ static void am_state_init(struct am_state *state)
memset(state, 0, sizeof(*state)); memset(state, 0, sizeof(*state));
state->dir = git_pathdup("rebase-apply"); state->dir = repo_git_path(the_repository, "rebase-apply");
state->prec = 4; state->prec = 4;

View File

@ -835,7 +835,7 @@ static void write_refspec_config(const char *src_ref_prefix,
static void dissociate_from_references(void) static void dissociate_from_references(void)
{ {
char *alternates = git_pathdup("objects/info/alternates"); char *alternates = repo_git_path(the_repository, "objects/info/alternates");
if (!access(alternates, F_OK)) { if (!access(alternates, F_OK)) {
struct child_process cmd = CHILD_PROCESS_INIT; struct child_process cmd = CHILD_PROCESS_INIT;
@ -1219,7 +1219,7 @@ int cmd_clone(int argc,
strbuf_reset(&buf); strbuf_reset(&buf);
strbuf_addf(&buf, "%s/refs", git_dir); 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 * additional config can be injected with -c, make sure it's included

View File

@ -352,6 +352,7 @@ static const char *prepare_index(const char **argv, const char *prefix,
struct pathspec pathspec; struct pathspec pathspec;
int refresh_flags = REFRESH_QUIET; int refresh_flags = REFRESH_QUIET;
const char *ret; const char *ret;
char *path = NULL;
if (is_status) if (is_status)
refresh_flags |= REFRESH_UNMERGED; 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)) if (write_locked_index(the_repository->index, &index_lock, 0))
die(_("unable to write new index file")); die(_("unable to write new index file"));
hold_lock_file_for_update(&false_lock, path = repo_git_path(the_repository, "next-index-%"PRIuMAX,
git_path("next-index-%"PRIuMAX, (uintmax_t) getpid());
(uintmax_t) getpid()), hold_lock_file_for_update(&false_lock, path,
LOCK_DIE_ON_ERROR); LOCK_DIE_ON_ERROR);
create_base_index(current_head); create_base_index(current_head);
@ -542,6 +543,7 @@ static const char *prepare_index(const char **argv, const char *prefix,
out: out:
string_list_clear(&partial, 0); string_list_clear(&partial, 0);
clear_pathspec(&pathspec); clear_pathspec(&pathspec);
free(path);
return ret; return ret;
} }

View File

@ -775,13 +775,13 @@ static void location_options_init(struct config_location_options *opts,
opts->source.file = opts->file_to_free = git_system_config(); opts->source.file = opts->file_to_free = git_system_config();
opts->source.scope = CONFIG_SCOPE_SYSTEM; opts->source.scope = CONFIG_SCOPE_SYSTEM;
} else if (opts->use_local_config) { } else if (opts->use_local_config) {
opts->source.file = opts->file_to_free = git_pathdup("config"); opts->source.file = opts->file_to_free = repo_git_path(the_repository, "config");
opts->source.scope = CONFIG_SCOPE_LOCAL; opts->source.scope = CONFIG_SCOPE_LOCAL;
} else if (opts->use_worktree_config) { } else if (opts->use_worktree_config) {
struct worktree **worktrees = get_worktrees(); struct worktree **worktrees = get_worktrees();
if (the_repository->repository_format_worktree_config) if (the_repository->repository_format_worktree_config)
opts->source.file = opts->file_to_free = opts->source.file = opts->file_to_free =
git_pathdup("config.worktree"); repo_git_path(the_repository, "config.worktree");
else if (worktrees[0] && worktrees[1]) else if (worktrees[0] && worktrees[1])
die(_("--worktree cannot be used with multiple " die(_("--worktree cannot be used with multiple "
"working trees unless the config\n" "working trees unless the config\n"
@ -790,7 +790,7 @@ static void location_options_init(struct config_location_options *opts,
"section in \"git help worktree\" for details")); "section in \"git help worktree\" for details"));
else else
opts->source.file = opts->file_to_free = opts->source.file = opts->file_to_free =
git_pathdup("config"); repo_git_path(the_repository, "config");
opts->source.scope = CONFIG_SCOPE_LOCAL; opts->source.scope = CONFIG_SCOPE_LOCAL;
free_worktrees(worktrees); free_worktrees(worktrees);
} else if (opts->source.file) { } else if (opts->source.file) {
@ -1087,7 +1087,7 @@ static int show_editor(struct config_location_options *opts)
git_config(git_default_config, NULL); git_config(git_default_config, NULL);
config_file = opts->source.file ? config_file = opts->source.file ?
xstrdup(opts->source.file) : xstrdup(opts->source.file) :
git_pathdup("config"); repo_git_path(the_repository, "config");
if (opts->use_global_config) { if (opts->use_global_config) {
int fd = open(config_file, O_CREAT | O_EXCL | O_WRONLY, 0666); int fd = open(config_file, O_CREAT | O_EXCL | O_WRONLY, 0666);
if (fd >= 0) { if (fd >= 0) {

View File

@ -328,7 +328,7 @@ static void write_branch_report(FILE *rpt, struct branch *b)
static void write_crash_report(const char *err) static void write_crash_report(const char *err)
{ {
char *loc = git_pathdup("fast_import_crash_%"PRIuMAX, (uintmax_t) getpid()); char *loc = repo_git_path(the_repository, "fast_import_crash_%"PRIuMAX, (uintmax_t) getpid());
FILE *rpt = fopen(loc, "w"); FILE *rpt = fopen(loc, "w");
struct branch *b; struct branch *b;
unsigned long lu; unsigned long lu;
@ -3280,7 +3280,7 @@ static char* make_fast_import_path(const char *path)
{ {
if (!relative_marks_paths || is_absolute_path(path)) if (!relative_marks_paths || is_absolute_path(path))
return prefix_filename(global_prefix, path); return prefix_filename(global_prefix, path);
return git_pathdup("info/fast-import/%s", path); return repo_git_path(the_repository, "info/fast-import/%s", path);
} }
static void option_import_marks(const char *marks, static void option_import_marks(const char *marks,

View File

@ -326,7 +326,7 @@ static void check_unreachable_object(struct object *obj)
printable_type(&obj->oid, obj->type), printable_type(&obj->oid, obj->type),
describe_object(&obj->oid)); describe_object(&obj->oid));
if (write_lost_and_found) { if (write_lost_and_found) {
char *filename = git_pathdup("lost-found/%s/%s", char *filename = repo_git_path(the_repository, "lost-found/%s/%s",
obj->type == OBJ_COMMIT ? "commit" : "other", obj->type == OBJ_COMMIT ? "commit" : "other",
describe_object(&obj->oid)); describe_object(&obj->oid));
FILE *f; FILE *f;
@ -1057,7 +1057,7 @@ int cmd_fsck(int argc,
struct worktree *wt = *p; struct worktree *wt = *p;
struct index_state istate = struct index_state istate =
INDEX_STATE_INIT(the_repository); INDEX_STATE_INIT(the_repository);
char *path; char *path, *wt_gitdir;
/* /*
* Make a copy since the buffer is reusable * Make a copy since the buffer is reusable
@ -1065,9 +1065,13 @@ int cmd_fsck(int argc,
* while we're examining the index. * while we're examining the index.
*/ */
path = xstrdup(worktree_git_path(the_repository, wt, "index")); path = xstrdup(worktree_git_path(the_repository, wt, "index"));
read_index_from(&istate, path, get_worktree_git_dir(wt)); wt_gitdir = get_worktree_git_dir(wt);
read_index_from(&istate, path, wt_gitdir);
fsck_index(&istate, path, wt->is_current); fsck_index(&istate, path, wt->is_current);
discard_index(&istate); discard_index(&istate);
free(wt_gitdir);
free(path); free(path);
} }
free_worktrees(worktrees); free_worktrees(worktrees);

View File

@ -99,9 +99,11 @@ static void process_log_file(void)
/* There was some error recorded in the lock file */ /* There was some error recorded in the lock file */
commit_lock_file(&log_lock); commit_lock_file(&log_lock);
} else { } else {
char *path = repo_git_path(the_repository, "gc.log");
/* No error, clean up any old gc.log */ /* No error, clean up any old gc.log */
unlink(git_path("gc.log")); unlink(path);
rollback_lock_file(&log_lock); rollback_lock_file(&log_lock);
free(path);
} }
} }
@ -300,8 +302,11 @@ static int too_many_loose_objects(struct gc_config *cfg)
int num_loose = 0; int num_loose = 0;
int needed = 0; int needed = 0;
const unsigned hexsz_loose = the_hash_algo->hexsz - 2; 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) if (!dir)
return 0; return 0;
@ -550,7 +555,7 @@ static const char *lock_repo_for_gc(int force, pid_t* ret_pid)
if (xgethostname(my_host, sizeof(my_host))) if (xgethostname(my_host, sizeof(my_host)))
xsnprintf(my_host, sizeof(my_host), "unknown"); xsnprintf(my_host, sizeof(my_host), "unknown");
pidfile_path = git_pathdup("gc.pid"); pidfile_path = repo_git_path(the_repository, "gc.pid");
fd = hold_lock_file_for_update(&lock, pidfile_path, fd = hold_lock_file_for_update(&lock, pidfile_path,
LOCK_DIE_ON_ERROR); LOCK_DIE_ON_ERROR);
if (!force) { if (!force) {
@ -611,7 +616,7 @@ static int report_last_gc_error(void)
int ret = 0; int ret = 0;
ssize_t len; ssize_t len;
struct stat st; struct stat st;
char *gc_log_path = git_pathdup("gc.log"); char *gc_log_path = repo_git_path(the_repository, "gc.log");
if (stat(gc_log_path, &st)) { if (stat(gc_log_path, &st)) {
if (errno == ENOENT) if (errno == ENOENT)
@ -826,11 +831,12 @@ struct repository *repo UNUSED)
} }
if (daemonized) { if (daemonized) {
hold_lock_file_for_update(&log_lock, char *path = repo_git_path(the_repository, "gc.log");
git_path("gc.log"), hold_lock_file_for_update(&log_lock, path,
LOCK_DIE_ON_ERROR); LOCK_DIE_ON_ERROR);
dup2(get_lock_file_fd(&log_lock), 2); dup2(get_lock_file_fd(&log_lock), 2);
atexit(process_log_file_at_exit); atexit(process_log_file_at_exit);
free(path);
} }
gc_before_repack(&opts, &cfg); gc_before_repack(&opts, &cfg);
@ -892,8 +898,11 @@ struct repository *repo UNUSED)
warning(_("There are too many unreachable loose objects; " warning(_("There are too many unreachable loose objects; "
"run 'git prune' to remove them.")); "run 'git prune' to remove them."));
if (!daemonized) if (!daemonized) {
unlink(git_path("gc.log")); char *path = repo_git_path(the_repository, "gc.log");
unlink(path);
free(path);
}
out: out:
gc_config_release(&cfg); gc_config_release(&cfg);

View File

@ -132,8 +132,8 @@ int cmd_init_db(int argc,
* and we know shared_repository should always be 0; * and we know shared_repository should always be 0;
* but just in case we play safe. * but just in case we play safe.
*/ */
saved = get_shared_repository(); saved = repo_settings_get_shared_repository(the_repository);
set_shared_repository(0); repo_settings_set_shared_repository(the_repository, 0);
switch (safe_create_leading_directories_const(argv[0])) { switch (safe_create_leading_directories_const(argv[0])) {
case SCLD_OK: case SCLD_OK:
case SCLD_PERMS: case SCLD_PERMS:
@ -145,7 +145,7 @@ int cmd_init_db(int argc,
die_errno(_("cannot mkdir %s"), argv[0]); die_errno(_("cannot mkdir %s"), argv[0]);
break; break;
} }
set_shared_repository(saved); repo_settings_set_shared_repository(the_repository, saved);
if (mkdir(argv[0], 0777) < 0) if (mkdir(argv[0], 0777) < 0)
die_errno(_("cannot mkdir %s"), argv[0]); die_errno(_("cannot mkdir %s"), argv[0]);
mkdir_tried = 1; mkdir_tried = 1;
@ -175,7 +175,7 @@ int cmd_init_db(int argc,
} }
if (init_shared_repository != -1) 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 * GIT_WORK_TREE makes sense only in conjunction with GIT_DIR

View File

@ -2309,8 +2309,8 @@ int cmd_format_patch(int argc,
* We consider <outdir> as 'outside of gitdir', therefore avoid * We consider <outdir> as 'outside of gitdir', therefore avoid
* applying adjust_shared_perm in s-c-l-d. * applying adjust_shared_perm in s-c-l-d.
*/ */
saved = get_shared_repository(); saved = repo_settings_get_shared_repository(the_repository);
set_shared_repository(0); repo_settings_set_shared_repository(the_repository, 0);
switch (safe_create_leading_directories_const(output_directory)) { switch (safe_create_leading_directories_const(output_directory)) {
case SCLD_OK: case SCLD_OK:
case SCLD_EXISTS: case SCLD_EXISTS:
@ -2319,7 +2319,7 @@ int cmd_format_patch(int argc,
die(_("could not create leading directories " die(_("could not create leading directories "
"of '%s'"), output_directory); "of '%s'"), output_directory);
} }
set_shared_repository(saved); repo_settings_set_shared_repository(the_repository, saved);
if (mkdir(output_directory, 0777) < 0 && errno != EEXIST) if (mkdir(output_directory, 0777) < 0 && errno != EEXIST)
die_errno(_("could not create directory '%s'"), die_errno(_("could not create directory '%s'"),
output_directory); output_directory);

View File

@ -197,7 +197,7 @@ static void prepare_note_data(const struct object_id *object, struct note_data *
struct strbuf buf = STRBUF_INIT; struct strbuf buf = STRBUF_INIT;
/* write the template message before editing: */ /* write the template message before editing: */
d->edit_path = git_pathdup("NOTES_EDITMSG"); d->edit_path = repo_git_path(the_repository, "NOTES_EDITMSG");
fd = xopen(d->edit_path, O_CREAT | O_TRUNC | O_WRONLY, 0600); fd = xopen(d->edit_path, O_CREAT | O_TRUNC | O_WRONLY, 0600);
if (d->msg_nr) if (d->msg_nr)
@ -979,6 +979,8 @@ static int merge(int argc, const char **argv, const char *prefix,
else { /* Merge has unresolved conflicts */ else { /* Merge has unresolved conflicts */
struct worktree **worktrees; struct worktree **worktrees;
const struct worktree *wt; const struct worktree *wt;
char *path;
/* Update .git/NOTES_MERGE_PARTIAL with partial merge result */ /* Update .git/NOTES_MERGE_PARTIAL with partial merge result */
refs_update_ref(get_main_ref_store(the_repository), msg.buf, refs_update_ref(get_main_ref_store(the_repository), msg.buf,
"NOTES_MERGE_PARTIAL", &result_oid, NULL, "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)) 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)"), die(_("failed to store link to current notes ref (%s)"),
notes_ref); notes_ref);
path = repo_git_path(the_repository, NOTES_MERGE_WORKTREE);
fprintf(stderr, _("Automatic notes merge failed. Fix conflicts in %s " fprintf(stderr, _("Automatic notes merge failed. Fix conflicts in %s "
"and commit the result with 'git notes merge --commit', " "and commit the result with 'git notes merge --commit', "
"or abort the merge with 'git notes merge --abort'.\n"), "or abort the merge with 'git notes merge --abort'.\n"),
git_path(NOTES_MERGE_WORKTREE)); path);
free(path);
} }
free_notes(t); free_notes(t);

View File

@ -644,7 +644,7 @@ static int run_am(struct rebase_options *opts)
return run_command(&am); 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, format_patch.out = open(rebased_patches,
O_WRONLY | O_CREAT | O_TRUNC, 0666); O_WRONLY | O_CREAT | O_TRUNC, 0666);
if (format_patch.out < 0) { if (format_patch.out < 0) {

View File

@ -1435,7 +1435,8 @@ static const char *push_to_checkout(unsigned char *hash,
static const char *update_worktree(unsigned char *sha1, const struct worktree *worktree) static const char *update_worktree(unsigned char *sha1, const struct worktree *worktree)
{ {
const char *retval, *git_dir; const char *retval;
char *git_dir;
struct strvec env = STRVEC_INIT; struct strvec env = STRVEC_INIT;
int invoked_hook; int invoked_hook;
@ -1453,6 +1454,7 @@ static const char *update_worktree(unsigned char *sha1, const struct worktree *w
retval = push_to_deploy(sha1, &env, worktree->path); retval = push_to_deploy(sha1, &env, worktree->path);
strvec_clear(&env); strvec_clear(&env);
free(git_dir);
return retval; return retval;
} }

View File

@ -644,9 +644,11 @@ static int migrate_file(struct remote *remote)
git_config_set_multivar(buf.buf, remote->fetch.items[i].raw, "^$", 0); git_config_set_multivar(buf.buf, remote->fetch.items[i].raw, "^$", 0);
#ifndef WITH_BREAKING_CHANGES #ifndef WITH_BREAKING_CHANGES
if (remote->origin == REMOTE_REMOTES) 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) 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 */ #endif /* WITH_BREAKING_CHANGES */
strbuf_release(&buf); strbuf_release(&buf);

View File

@ -345,7 +345,7 @@ static int edit_and_replace(const char *object_ref, int force, int raw)
} }
strbuf_release(&ref); strbuf_release(&ref);
tmpfile = git_pathdup("REPLACE_EDITOBJ"); tmpfile = repo_git_path(the_repository, "REPLACE_EDITOBJ");
if (export_object(&old_oid, type, raw, tmpfile)) { if (export_object(&old_oid, type, raw, tmpfile)) {
free(tmpfile); free(tmpfile);
return -1; return -1;

View File

@ -4,9 +4,9 @@
#include "config.h" #include "config.h"
#include "gettext.h" #include "gettext.h"
#include "parse-options.h" #include "parse-options.h"
#include "string-list.h"
#include "rerere.h" #include "rerere.h"
#include "strbuf.h"
#include "string-list.h"
#include "xdiff/xdiff.h" #include "xdiff/xdiff.h"
#include "xdiff-interface.h" #include "xdiff-interface.h"
#include "pathspec.h" #include "pathspec.h"
@ -112,15 +112,18 @@ int cmd_rerere(int argc,
merge_rr.items[i].util = NULL; merge_rr.items[i].util = NULL;
} }
} else if (!strcmp(argv[0], "diff")) { } else if (!strcmp(argv[0], "diff")) {
struct strbuf buf = STRBUF_INIT;
if (setup_rerere(the_repository, &merge_rr, if (setup_rerere(the_repository, &merge_rr,
flags | RERERE_READONLY) < 0) flags | RERERE_READONLY) < 0)
return 0; return 0;
for (size_t i = 0; i < merge_rr.nr; i++) { for (size_t i = 0; i < merge_rr.nr; i++) {
const char *path = merge_rr.items[i].string; const char *path = merge_rr.items[i].string;
const struct rerere_id *id = merge_rr.items[i].util; const struct rerere_id *id = merge_rr.items[i].util;
if (diff_two(rerere_path(id, "preimage"), path, path, path)) if (diff_two(rerere_path(&buf, id, "preimage"), path, path, path))
die(_("unable to generate diff for '%s'"), rerere_path(id, NULL)); die(_("unable to generate diff for '%s'"), rerere_path(&buf, id, NULL));
} }
strbuf_release(&buf);
} else } else
usage_with_options(rerere_usage, options); usage_with_options(rerere_usage, options);

View File

@ -789,8 +789,8 @@ int cmd_rev_parse(int argc,
if (!strcmp(arg, "--git-path")) { if (!strcmp(arg, "--git-path")) {
if (!argv[i + 1]) if (!argv[i + 1])
die(_("--git-path requires an argument")); die(_("--git-path requires an argument"));
strbuf_reset(&buf); print_path(repo_git_path_replace(the_repository, &buf,
print_path(git_path("%s", argv[i + 1]), prefix, "%s", argv[i + 1]), prefix,
format, format,
DEFAULT_RELATIVE_IF_SHARED); DEFAULT_RELATIVE_IF_SHARED);
i++; i++;
@ -1083,7 +1083,7 @@ int cmd_rev_parse(int argc,
die(_("Could not read the index")); die(_("Could not read the index"));
if (the_repository->index->split_index) { if (the_repository->index->split_index) {
const struct object_id *oid = &the_repository->index->split_index->base_oid; 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); print_path(path, prefix, format, DEFAULT_RELATIVE);
} }
continue; continue;

View File

@ -1301,7 +1301,7 @@ static void sync_submodule(const char *path, const char *prefix,
remote_key = xstrfmt("remote.%s.url", default_remote); remote_key = xstrfmt("remote.%s.url", default_remote);
free(default_remote); free(default_remote);
submodule_to_gitdir(&sb, path); submodule_to_gitdir(the_repository, &sb, path);
strbuf_addstr(&sb, "/config"); strbuf_addstr(&sb, "/config");
if (git_config_set_in_file_gently(sb.buf, remote_key, NULL, sub_origin_url)) if (git_config_set_in_file_gently(sb.buf, remote_key, NULL, sub_origin_url))
@ -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); 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) if (!p)
die(_("could not get submodule directory for '%s'"), clone_data_path); die(_("could not get submodule directory for '%s'"), clone_data_path);

View File

@ -667,7 +667,7 @@ int cmd_tag(int argc,
if (create_tag_object) { if (create_tag_object) {
if (force_sign_annotate && !annotate) if (force_sign_annotate && !annotate)
opt.sign = 1; opt.sign = 1;
path = git_pathdup("TAG_EDITMSG"); path = repo_git_path(the_repository, "TAG_EDITMSG");
create_tag(&object, object_ref, tag, &buf, &opt, &prev, &object, create_tag(&object, object_ref, tag, &buf, &opt, &prev, &object,
&trailer_args, path); &trailer_args, path);
} }

View File

@ -151,7 +151,7 @@ static int delete_git_dir(const char *id)
struct strbuf sb = STRBUF_INIT; struct strbuf sb = STRBUF_INIT;
int ret; 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); ret = remove_dir_recursively(&sb, 0);
if (ret < 0 && errno == ENOTDIR) if (ret < 0 && errno == ENOTDIR)
ret = unlink(sb.buf); ret = unlink(sb.buf);
@ -163,7 +163,9 @@ static int delete_git_dir(const char *id)
static void delete_worktrees_dir_if_empty(void) 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) 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 reason = STRBUF_INIT;
struct strbuf main_path = STRBUF_INIT; struct strbuf main_path = STRBUF_INIT;
struct string_list kept = STRING_LIST_INIT_DUP; struct string_list kept = STRING_LIST_INIT_DUP;
DIR *dir = opendir(git_path("worktrees")); char *path;
DIR *dir;
struct dirent *d; struct dirent *d;
path = repo_git_path(the_repository, "worktrees");
dir = opendir(path);
free(path);
if (!dir) if (!dir)
return; return;
while ((d = readdir_skip_dot_and_dotdot(dir)) != NULL) { while ((d = readdir_skip_dot_and_dotdot(dir)) != NULL) {
@ -337,7 +344,7 @@ static void check_candidate_path(const char *path,
static void copy_sparse_checkout(const char *worktree_git_dir) static void copy_sparse_checkout(const char *worktree_git_dir)
{ {
char *from_file = git_pathdup("info/sparse-checkout"); char *from_file = repo_git_path(the_repository, "info/sparse-checkout");
char *to_file = xstrfmt("%s/info/sparse-checkout", worktree_git_dir); char *to_file = xstrfmt("%s/info/sparse-checkout", worktree_git_dir);
if (file_exists(from_file)) { if (file_exists(from_file)) {
@ -353,7 +360,7 @@ static void copy_sparse_checkout(const char *worktree_git_dir)
static void copy_filtered_worktree_config(const char *worktree_git_dir) static void copy_filtered_worktree_config(const char *worktree_git_dir)
{ {
char *from_file = git_pathdup("config.worktree"); char *from_file = repo_git_path(the_repository, "config.worktree");
char *to_file = xstrfmt("%s/config.worktree", worktree_git_dir); char *to_file = xstrfmt("%s/config.worktree", worktree_git_dir);
if (file_exists(from_file)) { if (file_exists(from_file)) {
@ -457,7 +464,7 @@ static int add_worktree(const char *path, const char *refname,
BUG("How come '%s' becomes empty after sanitization?", sb.buf); BUG("How come '%s' becomes empty after sanitization?", sb.buf);
strbuf_reset(&sb); strbuf_reset(&sb);
name = sb_name.buf; name = sb_name.buf;
git_path_buf(&sb_repo, "worktrees/%s", name); repo_git_path_replace(the_repository, &sb_repo, "worktrees/%s", name);
len = sb_repo.len; len = sb_repo.len;
if (safe_create_leading_directories_const(sb_repo.buf)) if (safe_create_leading_directories_const(sb_repo.buf))
die_errno(_("could not create leading directories of '%s'"), die_errno(_("could not create leading directories of '%s'"),
@ -657,8 +664,9 @@ static int can_use_local_refs(const struct add_opts *opts)
if (!opts->quiet) { if (!opts->quiet) {
struct strbuf path = STRBUF_INIT; struct strbuf path = STRBUF_INIT;
struct strbuf contents = STRBUF_INIT; struct strbuf contents = STRBUF_INIT;
char *wt_gitdir = get_worktree_git_dir(NULL);
strbuf_add_real_path(&path, get_worktree_git_dir(NULL)); strbuf_add_real_path(&path, wt_gitdir);
strbuf_addstr(&path, "/HEAD"); strbuf_addstr(&path, "/HEAD");
strbuf_read_file(&contents, path.buf, 64); strbuf_read_file(&contents, path.buf, 64);
strbuf_stripspace(&contents, NULL); strbuf_stripspace(&contents, NULL);
@ -670,6 +678,7 @@ static int can_use_local_refs(const struct add_opts *opts)
path.buf, contents.buf); path.buf, contents.buf);
strbuf_release(&path); strbuf_release(&path);
strbuf_release(&contents); strbuf_release(&contents);
free(wt_gitdir);
} }
return 1; return 1;
} }
@ -1100,6 +1109,7 @@ static int lock_worktree(int ac, const char **av, const char *prefix,
OPT_END() OPT_END()
}; };
struct worktree **worktrees, *wt; struct worktree **worktrees, *wt;
char *path;
ac = parse_options(ac, av, prefix, options, git_worktree_lock_usage, 0); ac = parse_options(ac, av, prefix, options, git_worktree_lock_usage, 0);
if (ac != 1) if (ac != 1)
@ -1120,9 +1130,11 @@ static int lock_worktree(int ac, const char **av, const char *prefix,
die(_("'%s' is already locked"), av[0]); die(_("'%s' is already locked"), av[0]);
} }
write_file(git_common_path("worktrees/%s/locked", wt->id), path = repo_common_path(the_repository, "worktrees/%s/locked", wt->id);
"%s", reason); write_file(path, "%s", reason);
free_worktrees(worktrees); free_worktrees(worktrees);
free(path);
return 0; return 0;
} }
@ -1133,6 +1145,7 @@ static int unlock_worktree(int ac, const char **av, const char *prefix,
OPT_END() OPT_END()
}; };
struct worktree **worktrees, *wt; struct worktree **worktrees, *wt;
char *path;
int ret; int ret;
ac = parse_options(ac, av, prefix, options, git_worktree_unlock_usage, 0); ac = parse_options(ac, av, prefix, options, git_worktree_unlock_usage, 0);
@ -1147,8 +1160,12 @@ static int unlock_worktree(int ac, const char **av, const char *prefix,
die(_("The main working tree cannot be locked or unlocked")); die(_("The main working tree cannot be locked or unlocked"));
if (!worktree_lock_reason(wt)) if (!worktree_lock_reason(wt))
die(_("'%s' is not locked"), av[0]); 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_worktrees(worktrees);
free(path);
return ret; return ret;
} }
@ -1157,6 +1174,9 @@ static void validate_no_submodules(const struct worktree *wt)
struct index_state istate = INDEX_STATE_INIT(the_repository); struct index_state istate = INDEX_STATE_INIT(the_repository);
struct strbuf path = STRBUF_INIT; struct strbuf path = STRBUF_INIT;
int i, found_submodules = 0; int i, found_submodules = 0;
char *wt_gitdir;
wt_gitdir = get_worktree_git_dir(wt);
if (is_directory(worktree_git_path(the_repository, wt, "modules"))) { if (is_directory(worktree_git_path(the_repository, wt, "modules"))) {
/* /*
@ -1166,7 +1186,7 @@ static void validate_no_submodules(const struct worktree *wt)
*/ */
found_submodules = 1; found_submodules = 1;
} else if (read_index_from(&istate, worktree_git_path(the_repository, wt, "index"), } else if (read_index_from(&istate, worktree_git_path(the_repository, wt, "index"),
get_worktree_git_dir(wt)) > 0) { wt_gitdir) > 0) {
for (i = 0; i < istate.cache_nr; i++) { for (i = 0; i < istate.cache_nr; i++) {
struct cache_entry *ce = istate.cache[i]; struct cache_entry *ce = istate.cache[i];
int err; int err;
@ -1185,6 +1205,7 @@ static void validate_no_submodules(const struct worktree *wt)
} }
discard_index(&istate); discard_index(&istate);
strbuf_release(&path); strbuf_release(&path);
free(wt_gitdir);
if (found_submodules) if (found_submodules)
die(_("working trees containing submodules cannot be moved or removed")); die(_("working trees containing submodules cannot be moved or removed"));

View File

@ -2084,7 +2084,7 @@ static int write_commit_graph_file(struct write_commit_graph_context *ctx)
return -1; 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'"), error(_("unable to adjust shared permissions for '%s'"),
get_tempfile_path(graph_layer)); get_tempfile_path(graph_layer));
return -1; return -1;

View File

@ -50,15 +50,15 @@ void probe_utf8_pathname_composition(void)
int output_fd; int output_fd;
if (precomposed_unicode != -1) if (precomposed_unicode != -1)
return; /* We found it defined in the global config, respect it */ return; /* We found it defined in the global config, respect it */
git_path_buf(&path, "%s", auml_nfc); repo_git_path_replace(the_repository, &path, "%s", auml_nfc);
output_fd = open(path.buf, O_CREAT|O_EXCL|O_RDWR, 0600); output_fd = open(path.buf, O_CREAT|O_EXCL|O_RDWR, 0600);
if (output_fd >= 0) { if (output_fd >= 0) {
close(output_fd); close(output_fd);
git_path_buf(&path, "%s", auml_nfd); repo_git_path_replace(the_repository, &path, "%s", auml_nfd);
precomposed_unicode = access(path.buf, R_OK) ? 0 : 1; precomposed_unicode = access(path.buf, R_OK) ? 0 : 1;
git_config_set("core.precomposeunicode", git_config_set("core.precomposeunicode",
precomposed_unicode ? "true" : "false"); precomposed_unicode ? "true" : "false");
git_path_buf(&path, "%s", auml_nfc); repo_git_path_replace(the_repository, &path, "%s", auml_nfc);
if (unlink(path.buf)) if (unlink(path.buf))
die_errno(_("failed to unlink '%s'"), path.buf); die_errno(_("failed to unlink '%s'"), path.buf);
} }

View File

@ -1437,11 +1437,6 @@ static int git_default_core_config(const char *var, const char *value,
return git_config_pathname(&git_attributes_file, var, 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")) { if (!strcmp(var, "core.bare")) {
is_bare_repository_cfg = git_config_bool(var, value); is_bare_repository_cfg = git_config_bool(var, value);
return 0; return 0;

4
copy.c
View File

@ -1,3 +1,5 @@
#define USE_THE_REPOSITORY_VARIABLE
#include "git-compat-util.h" #include "git-compat-util.h"
#include "copy.h" #include "copy.h"
#include "path.h" #include "path.h"
@ -57,7 +59,7 @@ int copy_file(const char *dst, const char *src, int mode)
if (close(fdo) != 0) if (close(fdo) != 0)
return error_errno("%s: close error", dst); return error_errno("%s: close error", dst);
if (!status && adjust_shared_perm(dst)) if (!status && adjust_shared_perm(the_repository, dst))
return -1; return -1;
return status; return status;

2
dir.c
View File

@ -3451,7 +3451,7 @@ void setup_standard_excludes(struct dir_struct *dir)
char *get_sparse_checkout_filename(void) char *get_sparse_checkout_filename(void)
{ {
return git_pathdup("info/sparse-checkout"); return repo_git_path(the_repository, "info/sparse-checkout");
} }
int get_sparse_checkout_patterns(struct pattern_list *pl) int get_sparse_checkout_patterns(struct pattern_list *pl)

View File

@ -142,10 +142,8 @@ int strbuf_edit_interactively(struct repository *r,
struct strbuf sb = STRBUF_INIT; struct strbuf sb = STRBUF_INIT;
int fd, res = 0; int fd, res = 0;
if (!is_absolute_path(path)) { if (!is_absolute_path(path))
strbuf_repo_git_path(&sb, r, "%s", path); path = repo_git_path_append(r, &sb, "%s", path);
path = sb.buf;
}
fd = open(path, O_WRONLY | O_CREAT | O_TRUNC, 0666); fd = open(path, O_WRONLY | O_CREAT | O_TRUNC, 0666);
if (fd < 0) if (fd < 0)

View File

@ -43,7 +43,6 @@ char *git_log_output_encoding;
char *apply_default_whitespace; char *apply_default_whitespace;
char *apply_default_ignorewhitespace; char *apply_default_ignorewhitespace;
char *git_attributes_file; char *git_attributes_file;
char *git_hooks_path;
int zlib_compression_level = Z_BEST_SPEED; int zlib_compression_level = Z_BEST_SPEED;
int pack_compression_level = Z_DEFAULT_COMPRESSION; int pack_compression_level = Z_DEFAULT_COMPRESSION;
int fsync_object_files = -1; int fsync_object_files = -1;
@ -208,32 +207,6 @@ const char *get_commit_output_encoding(void)
return git_commit_encoding ? git_commit_encoding : "UTF-8"; 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) int use_optional_locks(void)
{ {
return git_env_bool(GIT_OPTIONAL_LOCKS_ENVIRONMENT, 1); return git_env_bool(GIT_OPTIONAL_LOCKS_ENVIRONMENT, 1);

View File

@ -134,16 +134,6 @@ void setup_git_env(const char *git_dir);
*/ */
int have_git_dir(void); 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; extern int is_bare_repository_cfg;
int is_bare_repository(void); int is_bare_repository(void);
extern char *git_work_tree_cfg; extern char *git_work_tree_cfg;
@ -160,7 +150,6 @@ extern int warn_on_object_refname_ambiguity;
extern char *apply_default_whitespace; extern char *apply_default_whitespace;
extern char *apply_default_ignorewhitespace; extern char *apply_default_ignorewhitespace;
extern char *git_attributes_file; extern char *git_attributes_file;
extern char *git_hooks_path;
extern int zlib_compression_level; extern int zlib_compression_level;
extern int pack_compression_level; extern int pack_compression_level;
extern size_t packed_git_window_size; extern size_t packed_git_window_size;

3
hook.c
View File

@ -16,8 +16,7 @@ const char *find_hook(struct repository *r, const char *name)
int found_hook; int found_hook;
strbuf_reset(&path); repo_git_path_replace(r, &path, "hooks/%s", name);
strbuf_repo_git_path(&path, r, "hooks/%s", name);
found_hook = access(path.buf, X_OK) >= 0; found_hook = access(path.buf, X_OK) >= 0;
#ifdef STRIP_EXTENSION #ifdef STRIP_EXTENSION
if (!found_hook) { if (!found_hook) {

View File

@ -183,7 +183,7 @@ static void send_strbuf(struct strbuf *hdr,
static void send_local_file(struct strbuf *hdr, const char *the_type, static void send_local_file(struct strbuf *hdr, const char *the_type,
const char *name) const char *name)
{ {
char *p = git_pathdup("%s", name); char *p = repo_git_path(the_repository, "%s", name);
size_t buf_alloc = 8192; size_t buf_alloc = 8192;
char *buf = xmalloc(buf_alloc); char *buf = xmalloc(buf_alloc);
int fd; int fd;

View File

@ -75,7 +75,7 @@ static int load_one_loose_object_map(struct repository *repo, struct object_dire
insert_loose_map(dir, repo->hash_algo->empty_blob, repo->compat_hash_algo->empty_blob); insert_loose_map(dir, repo->hash_algo->empty_blob, repo->compat_hash_algo->empty_blob);
insert_loose_map(dir, repo->hash_algo->null_oid, repo->compat_hash_algo->null_oid); insert_loose_map(dir, repo->hash_algo->null_oid, repo->compat_hash_algo->null_oid);
strbuf_git_common_path(&path, repo, "objects/loose-object-idx"); repo_common_path_replace(repo, &path, "objects/loose-object-idx");
fp = fopen(path.buf, "rb"); fp = fopen(path.buf, "rb");
if (!fp) { if (!fp) {
strbuf_release(&path); strbuf_release(&path);
@ -133,7 +133,7 @@ int repo_write_loose_object_map(struct repository *repo)
if (!should_use_loose_object_map(repo)) if (!should_use_loose_object_map(repo))
return 0; return 0;
strbuf_git_common_path(&path, repo, "objects/loose-object-idx"); repo_common_path_replace(repo, &path, "objects/loose-object-idx");
fd = hold_lock_file_for_update_timeout(&lock, path.buf, LOCK_DIE_ON_ERROR, -1); fd = hold_lock_file_for_update_timeout(&lock, path.buf, LOCK_DIE_ON_ERROR, -1);
iter = kh_begin(map); iter = kh_begin(map);
if (write_in_full(fd, loose_object_header, strlen(loose_object_header)) < 0) if (write_in_full(fd, loose_object_header, strlen(loose_object_header)) < 0)
@ -174,7 +174,7 @@ static int write_one_object(struct repository *repo, const struct object_id *oid
struct stat st; struct stat st;
struct strbuf buf = STRBUF_INIT, path = STRBUF_INIT; struct strbuf buf = STRBUF_INIT, path = STRBUF_INIT;
strbuf_git_common_path(&path, repo, "objects/loose-object-idx"); repo_common_path_replace(repo, &path, "objects/loose-object-idx");
hold_lock_file_for_update_timeout(&lock, path.buf, LOCK_DIE_ON_ERROR, -1); hold_lock_file_for_update_timeout(&lock, path.buf, LOCK_DIE_ON_ERROR, -1);
fd = open(path.buf, O_WRONLY | O_CREAT | O_APPEND, 0666); fd = open(path.buf, O_WRONLY | O_CREAT | O_APPEND, 0666);
@ -190,7 +190,7 @@ static int write_one_object(struct repository *repo, const struct object_id *oid
goto errout; goto errout;
if (close(fd)) if (close(fd))
goto errout; goto errout;
adjust_shared_perm(path.buf); adjust_shared_perm(repo, path.buf);
rollback_lock_file(&lock); rollback_lock_file(&lock);
strbuf_release(&buf); strbuf_release(&buf);
strbuf_release(&path); strbuf_release(&path);

View File

@ -1336,7 +1336,7 @@ static int write_midx_internal(struct repository *r, const char *object_dir,
return -1; 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'"), error(_("unable to adjust shared permissions for '%s'"),
get_tempfile_path(incr)); get_tempfile_path(incr));
return -1; return -1;

View File

@ -275,41 +275,45 @@ static void diff_tree_local(struct notes_merge_options *o,
static void check_notes_merge_worktree(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) { if (!o->has_worktree) {
/* /*
* Must establish NOTES_MERGE_WORKTREE. * Must establish NOTES_MERGE_WORKTREE.
* Abort if NOTES_MERGE_WORKTREE already exists * Abort if NOTES_MERGE_WORKTREE already exists
*/ */
if (file_exists(git_path(NOTES_MERGE_WORKTREE)) && if (file_exists(repo_git_path_replace(the_repository, &buf, NOTES_MERGE_WORKTREE)) &&
!is_empty_dir(git_path(NOTES_MERGE_WORKTREE))) { !is_empty_dir(repo_git_path_replace(the_repository, &buf, NOTES_MERGE_WORKTREE))) {
if (advice_enabled(ADVICE_RESOLVE_CONFLICT)) if (advice_enabled(ADVICE_RESOLVE_CONFLICT))
die(_("You have not concluded your previous " die(_("You have not concluded your previous "
"notes merge (%s exists).\nPlease, use " "notes merge (%s exists).\nPlease, use "
"'git notes merge --commit' or 'git notes " "'git notes merge --commit' or 'git notes "
"merge --abort' to commit/abort the " "merge --abort' to commit/abort the "
"previous merge before you start a new " "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 else
die(_("You have not concluded your notes merge " 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"))) NOTES_MERGE_WORKTREE "/.test")))
die_errno("unable to create directory %s", 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; 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 */ /* NOTES_MERGE_WORKTREE should already be established */
die("missing '%s'. This should not happen", 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, static void write_buf_to_worktree(const struct object_id *obj,
const char *buf, unsigned long size) const char *buf, unsigned long size)
{ {
int fd; int fd;
char *path = git_pathdup(NOTES_MERGE_WORKTREE "/%s", oid_to_hex(obj)); char *path = repo_git_path(the_repository, NOTES_MERGE_WORKTREE "/%s", oid_to_hex(obj));
if (safe_create_leading_directories_const(path)) if (safe_create_leading_directories_const(path))
die_errno("unable to create directory for '%s'", path); die_errno("unable to create directory for '%s'", path);
@ -695,7 +699,7 @@ int notes_merge_commit(struct notes_merge_options *o,
const char *msg = strstr(buffer, "\n\n"); const char *msg = strstr(buffer, "\n\n");
int baselen; int baselen;
git_path_buf(&path, NOTES_MERGE_WORKTREE); repo_git_path_replace(the_repository, &path, NOTES_MERGE_WORKTREE);
if (o->verbosity >= 3) if (o->verbosity >= 3)
printf("Committing notes in notes merge worktree at %s\n", printf("Committing notes in notes merge worktree at %s\n",
path.buf); path.buf);
@ -757,7 +761,7 @@ int notes_merge_abort(struct notes_merge_options *o)
struct strbuf buf = STRBUF_INIT; struct strbuf buf = STRBUF_INIT;
int ret; int ret;
git_path_buf(&buf, NOTES_MERGE_WORKTREE); repo_git_path_replace(the_repository, &buf, NOTES_MERGE_WORKTREE);
if (o->verbosity >= 3) if (o->verbosity >= 3)
printf("Removing notes merge worktree at %s/*\n", buf.buf); printf("Removing notes merge worktree at %s/*\n", buf.buf);
ret = remove_dir_recursively(&buf, REMOVE_DIR_KEEP_TOPLEVEL); ret = remove_dir_recursively(&buf, REMOVE_DIR_KEEP_TOPLEVEL);

View File

@ -394,7 +394,7 @@ int mkdir_in_gitdir(const char *path)
} }
strbuf_release(&sb); 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) static enum scld_error safe_create_leading_directories_1(char *path, int share)
@ -443,7 +443,7 @@ static enum scld_error safe_create_leading_directories_1(char *path, int share)
ret = SCLD_VANISHED; ret = SCLD_VANISHED;
else else
ret = SCLD_FAILED; ret = SCLD_FAILED;
} else if (share && adjust_shared_perm(path)) { } else if (share && adjust_shared_perm(the_repository, path)) {
ret = SCLD_PERMS; ret = SCLD_PERMS;
} }
*slash = slash_character; *slash = slash_character;
@ -482,14 +482,14 @@ int odb_mkstemp(struct strbuf *temp_filename, const char *pattern)
* restrictive except to remove write permission. * restrictive except to remove write permission.
*/ */
int mode = 0444; int mode = 0444;
git_path_buf(temp_filename, "objects/%s", pattern); repo_git_path_replace(the_repository, temp_filename, "objects/%s", pattern);
fd = git_mkstemp_mode(temp_filename->buf, mode); fd = git_mkstemp_mode(temp_filename->buf, mode);
if (0 <= fd) if (0 <= fd)
return fd; return fd;
/* slow path */ /* slow path */
/* some mkstemp implementations erase temp_filename on failure */ /* some mkstemp implementations erase temp_filename on failure */
git_path_buf(temp_filename, "objects/%s", pattern); repo_git_path_replace(the_repository, temp_filename, "objects/%s", pattern);
safe_create_leading_directories(temp_filename->buf); safe_create_leading_directories(temp_filename->buf);
return xmkstemp_mode(temp_filename->buf, mode); return xmkstemp_mode(temp_filename->buf, mode);
} }
@ -723,7 +723,7 @@ static void read_info_alternates(struct repository *r,
void add_to_alternates_file(const char *reference) void add_to_alternates_file(const char *reference)
{ {
struct lock_file lock = LOCK_INIT; struct lock_file lock = LOCK_INIT;
char *alts = git_pathdup("objects/info/alternates"); char *alts = repo_git_path(the_repository, "objects/info/alternates");
FILE *in, *out; FILE *in, *out;
int found = 0; int found = 0;
@ -2111,7 +2111,7 @@ int finalize_object_file_flags(const char *tmpfile, const char *filename,
} }
out: out:
if (adjust_shared_perm(filename)) if (adjust_shared_perm(the_repository, filename))
return error(_("unable to set permission to '%s'"), filename); return error(_("unable to set permission to '%s'"), filename);
return 0; return 0;
} }
@ -2187,7 +2187,7 @@ static int create_tmpfile(struct strbuf *tmp, const char *filename)
strbuf_add(tmp, filename, dirlen - 1); strbuf_add(tmp, filename, dirlen - 1);
if (mkdir(tmp->buf, 0777) && errno != EEXIST) if (mkdir(tmp->buf, 0777) && errno != EEXIST)
return -1; return -1;
if (adjust_shared_perm(tmp->buf)) if (adjust_shared_perm(the_repository, tmp->buf))
return -1; return -1;
/* Try again */ /* Try again */

View File

@ -1072,7 +1072,7 @@ void bitmap_writer_finish(struct bitmap_writer *writer,
finalize_hashfile(f, NULL, FSYNC_COMPONENT_PACK_METADATA, finalize_hashfile(f, NULL, FSYNC_COMPONENT_PACK_METADATA,
CSUM_HASH_IN_STREAM | CSUM_FSYNC | CSUM_CLOSE); 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"); die_errno("unable to make temporary bitmap file readable");
if (rename(tmp_file.buf, filename)) if (rename(tmp_file.buf, filename))

View File

@ -1,3 +1,5 @@
#define USE_THE_REPOSITORY_VARIABLE
#include "git-compat-util.h" #include "git-compat-util.h"
#include "environment.h" #include "environment.h"
#include "gettext.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_index_positions(f, pack_order, nr_objects);
write_rev_trailer(hash_algo, f, hash); 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); die(_("failed to make %s readable"), path);
finalize_hashfile(f, NULL, FSYNC_COMPONENT_PACK_METADATA, 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_objects(f, to_pack, objects, nr_objects);
write_mtimes_trailer(hash_algo, f, hash); 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); die(_("failed to make %s readable"), mtimes_name);
finalize_hashfile(f, NULL, FSYNC_COMPONENT_PACK_METADATA, finalize_hashfile(f, NULL, FSYNC_COMPONENT_PACK_METADATA,
@ -566,12 +568,12 @@ void stage_tmp_packfiles(const struct git_hash_algo *hash_algo,
char *rev_tmp_name = NULL; char *rev_tmp_name = NULL;
char *mtimes_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"); die_errno("unable to make temporary pack file readable");
*idx_tmp_name = (char *)write_idx_file(hash_algo, NULL, written_list, *idx_tmp_name = (char *)write_idx_file(hash_algo, NULL, written_list,
nr_written, pack_idx_opts, hash); 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"); die_errno("unable to make temporary index file readable");
rev_tmp_name = write_rev_file(hash_algo, NULL, written_list, nr_written, rev_tmp_name = write_rev_file(hash_algo, NULL, written_list, nr_written,

170
path.c
View File

@ -2,8 +2,6 @@
* Utilities for paths and pathnames * Utilities for paths and pathnames
*/ */
#define USE_THE_REPOSITORY_VARIABLE
#include "git-compat-util.h" #include "git-compat-util.h"
#include "abspath.h" #include "abspath.h"
#include "environment.h" #include "environment.h"
@ -30,7 +28,7 @@ static int get_st_mode_bits(const char *path, int *mode)
return 0; return 0;
} }
struct strbuf *get_pathname(void) static struct strbuf *get_pathname(void)
{ {
static struct strbuf pathname_array[4] = { static struct strbuf pathname_array[4] = {
STRBUF_INIT, STRBUF_INIT, STRBUF_INIT, STRBUF_INIT STRBUF_INIT, STRBUF_INIT, STRBUF_INIT, STRBUF_INIT
@ -387,10 +385,11 @@ void report_linked_checkout_garbage(struct repository *r)
strbuf_release(&sb); 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) struct strbuf *buf, int git_dir_len)
{ {
const char *base = buf->buf + git_dir_len; const char *base = buf->buf + git_dir_len;
if (is_dir_file(base, "info", "grafts")) if (is_dir_file(base, "info", "grafts"))
strbuf_splice(buf, 0, buf->len, strbuf_splice(buf, 0, buf->len,
repo->graft_file, strlen(repo->graft_file)); repo->graft_file, strlen(repo->graft_file));
@ -399,8 +398,8 @@ static void adjust_git_path(const struct repository *repo,
repo->index_file, strlen(repo->index_file)); repo->index_file, strlen(repo->index_file));
else if (dir_prefix(base, "objects")) else if (dir_prefix(base, "objects"))
replace_dir(buf, git_dir_len + 7, repo->objects->odb->path); replace_dir(buf, git_dir_len + 7, repo->objects->odb->path);
else if (git_hooks_path && dir_prefix(base, "hooks")) else if (repo_settings_get_hooks_path(repo) && dir_prefix(base, "hooks"))
replace_dir(buf, git_dir_len + 5, git_hooks_path); replace_dir(buf, git_dir_len + 5, repo_settings_get_hooks_path(repo));
else if (repo->different_commondir) else if (repo->different_commondir)
update_common_dir(buf, git_dir_len, repo->commondir); update_common_dir(buf, git_dir_len, repo->commondir);
} }
@ -414,12 +413,12 @@ static void strbuf_worktree_gitdir(struct strbuf *buf,
else if (!wt->id) else if (!wt->id)
strbuf_addstr(buf, repo->commondir); strbuf_addstr(buf, repo->commondir);
else 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, static void repo_git_pathv(struct repository *repo,
const struct worktree *wt, struct strbuf *buf, const struct worktree *wt, struct strbuf *buf,
const char *fmt, va_list args) const char *fmt, va_list args)
{ {
int gitdir_len; int gitdir_len;
strbuf_worktree_gitdir(buf, repo, wt); strbuf_worktree_gitdir(buf, repo, wt);
@ -432,7 +431,7 @@ void repo_git_pathv(const struct repository *repo,
strbuf_cleanup_path(buf); strbuf_cleanup_path(buf);
} }
char *repo_git_path(const struct repository *repo, char *repo_git_path(struct repository *repo,
const char *fmt, ...) const char *fmt, ...)
{ {
struct strbuf path = STRBUF_INIT; struct strbuf path = STRBUF_INIT;
@ -443,14 +442,27 @@ char *repo_git_path(const struct repository *repo,
return strbuf_detach(&path, NULL); return strbuf_detach(&path, NULL);
} }
void strbuf_repo_git_path(struct strbuf *sb, const char *repo_git_path_append(struct repository *repo,
const struct repository *repo, struct strbuf *sb,
const char *fmt, ...) const char *fmt, ...)
{ {
va_list args; va_list args;
va_start(args, fmt); va_start(args, fmt);
repo_git_pathv(repo, NULL, sb, fmt, args); repo_git_pathv(repo, NULL, sb, fmt, args);
va_end(args); va_end(args);
return sb->buf;
}
const char *repo_git_path_replace(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, ...) char *mkpathdup(const char *fmt, ...)
@ -506,9 +518,6 @@ char *repo_worktree_path(const struct repository *repo, const char *fmt, ...)
struct strbuf path = STRBUF_INIT; struct strbuf path = STRBUF_INIT;
va_list args; va_list args;
if (!repo->worktree)
return NULL;
va_start(args, fmt); va_start(args, fmt);
do_worktree_path(repo, &path, fmt, args); do_worktree_path(repo, &path, fmt, args);
va_end(args); va_end(args);
@ -516,29 +525,49 @@ char *repo_worktree_path(const struct repository *repo, const char *fmt, ...)
return strbuf_detach(&path, NULL); return strbuf_detach(&path, NULL);
} }
void strbuf_repo_worktree_path(struct strbuf *sb, const char *repo_worktree_path_append(const struct repository *repo,
const struct repository *repo, struct strbuf *sb,
const char *fmt, ...) const char *fmt, ...)
{ {
va_list args; va_list args;
if (!repo->worktree) if (!repo->worktree)
return; return NULL;
va_start(args, fmt); va_start(args, fmt);
do_worktree_path(repo, sb, fmt, args); do_worktree_path(repo, sb, fmt, args);
va_end(args); va_end(args);
return sb->buf;
}
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 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. */ /* 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) const char *fmt, va_list args)
{ {
struct strbuf git_submodule_common_dir = STRBUF_INIT; struct strbuf git_submodule_common_dir = STRBUF_INIT;
struct strbuf git_submodule_dir = STRBUF_INIT; struct strbuf git_submodule_dir = STRBUF_INIT;
int ret; int ret;
ret = submodule_to_gitdir(&git_submodule_dir, path); ret = submodule_to_gitdir(repo, &git_submodule_dir, path);
if (ret) if (ret)
goto cleanup; goto cleanup;
@ -557,13 +586,14 @@ static int do_submodule_path(struct strbuf *buf, const char *path,
return ret; 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; int err;
va_list args; va_list args;
struct strbuf buf = STRBUF_INIT; struct strbuf buf = STRBUF_INIT;
va_start(args, fmt); va_start(args, fmt);
err = do_submodule_path(&buf, path, fmt, args); err = do_submodule_path(repo, &buf, path, fmt, args);
va_end(args); va_end(args);
if (err) { if (err) {
strbuf_release(&buf); strbuf_release(&buf);
@ -572,22 +602,41 @@ char *git_pathdup_submodule(const char *path, const char *fmt, ...)
return strbuf_detach(&buf, NULL); return strbuf_detach(&buf, NULL);
} }
int strbuf_git_path_submodule(struct strbuf *buf, const char *path, const char *repo_submodule_path_append(struct repository *repo,
const char *fmt, ...) struct strbuf *buf,
const char *path,
const char *fmt, ...)
{ {
int err; int err;
va_list args; va_list args;
va_start(args, fmt); va_start(args, fmt);
err = do_submodule_path(buf, path, fmt, args); err = do_submodule_path(repo, buf, path, fmt, args);
va_end(args); va_end(args);
if (err)
return err; return NULL;
return buf->buf;
} }
void repo_common_pathv(const struct repository *repo, const char *repo_submodule_path_replace(struct repository *repo,
struct strbuf *sb, struct strbuf *buf,
const char *fmt, const char *path,
va_list args) 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;
}
static void repo_common_pathv(const struct repository *repo,
struct strbuf *sb,
const char *fmt,
va_list args)
{ {
strbuf_addstr(sb, repo->commondir); strbuf_addstr(sb, repo->commondir);
if (sb->len && !is_dir_sep(sb->buf[sb->len - 1])) if (sb->len && !is_dir_sep(sb->buf[sb->len - 1]))
@ -596,14 +645,38 @@ void repo_common_pathv(const struct repository *repo,
strbuf_cleanup_path(sb); strbuf_cleanup_path(sb);
} }
void strbuf_git_common_path(struct strbuf *sb, char *repo_common_path(const struct repository *repo,
const struct repository *repo, const char *fmt, ...)
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_list args;
va_start(args, fmt); va_start(args, fmt);
repo_common_pathv(repo, sb, fmt, args); repo_common_pathv(repo, sb, fmt, args);
va_end(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) static struct passwd *getpw_str(const char *username, size_t len)
@ -765,21 +838,22 @@ const char *enter_repo(const char *path, unsigned flags)
return NULL; return NULL;
} }
int calc_shared_perm(int mode) int calc_shared_perm(struct repository *repo,
int mode)
{ {
int tweak; int tweak;
if (get_shared_repository() < 0) if (repo_settings_get_shared_repository(repo) < 0)
tweak = -get_shared_repository(); tweak = -repo_settings_get_shared_repository(repo);
else else
tweak = get_shared_repository(); tweak = repo_settings_get_shared_repository(repo);
if (!(mode & S_IWUSR)) if (!(mode & S_IWUSR))
tweak &= ~0222; tweak &= ~0222;
if (mode & S_IXUSR) if (mode & S_IXUSR)
/* Copy read bits to execute bits */ /* Copy read bits to execute bits */
tweak |= (tweak & 0444) >> 2; tweak |= (tweak & 0444) >> 2;
if (get_shared_repository() < 0) if (repo_settings_get_shared_repository(repo) < 0)
mode = (mode & ~0777) | tweak; mode = (mode & ~0777) | tweak;
else else
mode |= tweak; mode |= tweak;
@ -787,17 +861,17 @@ int calc_shared_perm(int mode)
return mode; return mode;
} }
int adjust_shared_perm(struct repository *repo,
int adjust_shared_perm(const char *path) const char *path)
{ {
int old_mode, new_mode; int old_mode, new_mode;
if (!get_shared_repository()) if (!repo_settings_get_shared_repository(repo))
return 0; return 0;
if (get_st_mode_bits(path, &old_mode) < 0) if (get_st_mode_bits(path, &old_mode) < 0)
return -1; return -1;
new_mode = calc_shared_perm(old_mode); new_mode = calc_shared_perm(repo, old_mode);
if (S_ISDIR(old_mode)) { if (S_ISDIR(old_mode)) {
/* Copy read bits to execute bits */ /* Copy read bits to execute bits */
new_mode |= (new_mode & 0444) >> 2; new_mode |= (new_mode & 0444) >> 2;
@ -816,7 +890,7 @@ int adjust_shared_perm(const char *path)
return 0; 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 (mkdir(dir, 0777) < 0) {
if (errno != EEXIST) { if (errno != EEXIST) {
@ -824,7 +898,7 @@ void safe_create_dir(const char *dir, int share)
exit(1); 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); die(_("Could not make %s writable by group"), dir);
} }

197
path.h
View File

@ -25,22 +25,20 @@ char *mkpathdup(const char *fmt, ...)
__attribute__((format (printf, 1, 2))); __attribute__((format (printf, 1, 2)));
/* /*
* The `strbuf_git_common_path` family of functions will construct a path into a * The `repo_common_path` family of functions will construct a path into a
* repository's common git directory, which is shared by all worktrees. * repository's common git directory, which is shared by all worktrees.
*/ */
char *repo_common_path(const struct repository *repo,
/* const char *fmt, ...)
* Constructs a path into the common git directory of repository `repo` and __attribute__((format (printf, 2, 3)));
* append it in the provided buffer `sb`. const char *repo_common_path_append(const struct repository *repo,
*/ struct strbuf *sb,
void strbuf_git_common_path(struct strbuf *sb, const char *fmt, ...)
const struct repository *repo, __attribute__((format (printf, 3, 4)));
const char *fmt, ...) const char *repo_common_path_replace(const struct repository *repo,
struct strbuf *sb,
const char *fmt, ...)
__attribute__((format (printf, 3, 4))); __attribute__((format (printf, 3, 4)));
void repo_common_pathv(const struct repository *repo,
struct strbuf *buf,
const char *fmt,
va_list args);
/* /*
* The `repo_git_path` family of functions will construct a path into a repository's * The `repo_git_path` family of functions will construct a path into a repository's
@ -54,29 +52,16 @@ void repo_common_pathv(const struct repository *repo,
* For an exhaustive list of the adjustments made look at `common_list` and * For an exhaustive list of the adjustments made look at `common_list` and
* `adjust_git_path` in path.c. * `adjust_git_path` in path.c.
*/ */
char *repo_git_path(struct repository *repo,
/*
* Return a path into the git directory of repository `repo`.
*/
char *repo_git_path(const struct repository *repo,
const char *fmt, ...) const char *fmt, ...)
__attribute__((format (printf, 2, 3))); __attribute__((format (printf, 2, 3)));
const char *repo_git_path_append(struct repository *repo,
/* struct strbuf *sb,
* Print a path into the git directory of repository `repo` into the provided const char *fmt, ...)
* buffer. __attribute__((format (printf, 3, 4)));
*/ const char *repo_git_path_replace(struct repository *repo,
void repo_git_pathv(const struct repository *repo, struct strbuf *sb,
const struct worktree *wt, struct strbuf *buf, const char *fmt, ...)
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, ...)
__attribute__((format (printf, 3, 4))); __attribute__((format (printf, 3, 4)));
/* /*
@ -90,41 +75,45 @@ const char *worktree_git_path(struct repository *r,
__attribute__((format (printf, 3, 4))); __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, char *repo_worktree_path(const struct repository *repo,
const char *fmt, ...) const char *fmt, ...)
__attribute__((format (printf, 2, 3))); __attribute__((format (printf, 2, 3)));
const char *repo_worktree_path_append(const struct repository *repo,
/* struct strbuf *sb,
* 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 *fmt, ...) const char *fmt, ...)
__attribute__((format (printf, 3, 4))); __attribute__((format (printf, 3, 4)));
const char *repo_worktree_path_replace(const struct repository *repo,
/* struct strbuf *sb,
* Return a path into a submodule's git directory located at `path`. `path` const char *fmt, ...)
* 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).
*/
int strbuf_git_path_submodule(struct strbuf *sb, const char *path,
const char *fmt, ...)
__attribute__((format (printf, 3, 4))); __attribute__((format (printf, 3, 4)));
/*
* 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.
*/
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); void report_linked_checkout_garbage(struct repository *r);
/* /*
@ -152,8 +141,8 @@ const char *git_path_shallow(struct repository *r);
int ends_with_path_components(const char *path, const char *components); int ends_with_path_components(const char *path, const char *components);
int calc_shared_perm(int mode); int calc_shared_perm(struct repository *repo, int mode);
int adjust_shared_perm(const char *path); int adjust_shared_perm(struct repository *repo, const char *path);
char *interpolate_path(const char *path, int real_home); char *interpolate_path(const char *path, int real_home);
@ -230,101 +219,21 @@ char *xdg_cache_home(const char *filename);
* directories under $GIT_DIR. Don't use it for working tree * directories under $GIT_DIR. Don't use it for working tree
* directories. * directories.
*/ */
void safe_create_dir(const char *dir, int share); void safe_create_dir(struct repository *repo, 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 # ifdef USE_THE_REPOSITORY_VARIABLE
# include "strbuf.h" # include "strbuf.h"
# include "repository.h" # include "repository.h"
/*
* 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;
}
/*
* Construct a path into the main repository's (the_repository) git directory
* and place it in the provided buffer `buf`, the contents of the buffer will
* be overridden.
*/
__attribute__((format (printf, 2, 3)))
static inline char *git_path_buf(struct strbuf *buf, const char *fmt, ...)
{
va_list args;
strbuf_reset(buf);
va_start(args, fmt);
repo_git_pathv(the_repository, NULL, buf, fmt, args);
va_end(args);
return buf->buf;
}
/*
* Construct a path into the main repository's (the_repository) git directory
* and append it to the provided buffer `sb`.
*/
__attribute__((format (printf, 2, 3)))
static inline void strbuf_git_path(struct strbuf *sb, const char *fmt, ...)
{
va_list args;
va_start(args, fmt);
repo_git_pathv(the_repository, NULL, sb, fmt, args);
va_end(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) \ #define GIT_PATH_FUNC(func, filename) \
const char *func(void) \ const char *func(void) \
{ \ { \
static char *ret; \ static char *ret; \
if (!ret) \ if (!ret) \
ret = git_pathdup(filename); \ ret = repo_git_path(the_repository, filename); \
return ret; \ return ret; \
} }
/*
* Return a path into the main repository's (the_repository) git directory.
*/
__attribute__((format (printf, 1, 2)))
static inline char *git_pathdup(const char *fmt, ...)
{
struct strbuf path = STRBUF_INIT;
va_list args;
va_start(args, fmt);
repo_git_pathv(the_repository, NULL, &path, fmt, args);
va_end(args);
return strbuf_detach(&path, NULL);
}
# endif /* USE_THE_REPOSITORY_VARIABLE */ # endif /* USE_THE_REPOSITORY_VARIABLE */
#endif /* PATH_H */ #endif /* PATH_H */

View File

@ -65,8 +65,10 @@ static void add_rebase_files(struct rev_info *revs)
struct worktree **worktrees = get_worktrees(); struct worktree **worktrees = get_worktrees();
for (struct worktree **wt = worktrees; *wt; wt++) { for (struct worktree **wt = worktrees; *wt; wt++) {
char *wt_gitdir = get_worktree_git_dir(*wt);
strbuf_reset(&buf); strbuf_reset(&buf);
strbuf_addstr(&buf, get_worktree_git_dir(*wt)); strbuf_addstr(&buf, wt_gitdir);
strbuf_complete(&buf, '/'); strbuf_complete(&buf, '/');
len = buf.len; len = buf.len;
for (size_t i = 0; i < ARRAY_SIZE(path); i++) { for (size_t i = 0; i < ARRAY_SIZE(path); i++) {
@ -74,6 +76,8 @@ static void add_rebase_files(struct rev_info *revs)
strbuf_addstr(&buf, path[i]); strbuf_addstr(&buf, path[i]);
add_one_file(buf.buf, revs); add_one_file(buf.buf, revs);
} }
free(wt_gitdir);
} }
strbuf_release(&buf); strbuf_release(&buf);
free_worktrees(worktrees); free_worktrees(worktrees);

View File

@ -3251,15 +3251,18 @@ static int clean_shared_index_files(const char *current_hex)
while ((de = readdir(dir)) != NULL) { while ((de = readdir(dir)) != NULL) {
const char *sha1_hex; const char *sha1_hex;
const char *shared_index_path; char *shared_index_path;
if (!skip_prefix(de->d_name, "sharedindex.", &sha1_hex)) if (!skip_prefix(de->d_name, "sharedindex.", &sha1_hex))
continue; continue;
if (!strcmp(sha1_hex, current_hex)) if (!strcmp(sha1_hex, current_hex))
continue; 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 && if (should_delete_shared_index(shared_index_path) > 0 &&
unlink(shared_index_path)) unlink(shared_index_path))
warning_errno(_("unable to unlink: %s"), shared_index_path); warning_errno(_("unable to unlink: %s"), shared_index_path);
free(shared_index_path);
} }
closedir(dir); closedir(dir);
@ -3271,6 +3274,7 @@ static int write_shared_index(struct index_state *istate,
{ {
struct split_index *si = istate->split_index; struct split_index *si = istate->split_index;
int ret, was_full = !istate->sparse_index; int ret, was_full = !istate->sparse_index;
char *path;
move_cache_to_base_index(istate); move_cache_to_base_index(istate);
convert_to_sparse(istate, 0); convert_to_sparse(istate, 0);
@ -3286,18 +3290,20 @@ static int write_shared_index(struct index_state *istate,
if (ret) if (ret)
return ret; return ret;
ret = adjust_shared_perm(get_tempfile_path(*temp)); ret = adjust_shared_perm(the_repository, get_tempfile_path(*temp));
if (ret) { if (ret) {
error(_("cannot fix permission bits on '%s'"), get_tempfile_path(*temp)); error(_("cannot fix permission bits on '%s'"), get_tempfile_path(*temp));
return ret; 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) { if (!ret) {
oidcpy(&si->base_oid, &si->base->oid); oidcpy(&si->base_oid, &si->base->oid);
clean_shared_index_files(oid_to_hex(&si->base->oid)); clean_shared_index_files(oid_to_hex(&si->base->oid));
} }
free(path);
return ret; return ret;
} }
@ -3378,9 +3384,12 @@ int write_locked_index(struct index_state *istate, struct lock_file *lock,
if (new_shared_index) { if (new_shared_index) {
struct tempfile *temp; struct tempfile *temp;
int saved_errno; int saved_errno;
char *path;
/* Same initial permissions as the main .git/index file */ /* 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) { if (!temp) {
ret = do_write_locked_index(istate, lock, flags, ret = do_write_locked_index(istate, lock, flags,
~WRITE_SPLIT_INDEX_EXTENSION); ~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 */ /* Freshen the shared index only if the split-index was written */
if (!ret && !new_shared_index && !is_null_oid(&si->base_oid)) { if (!ret && !new_shared_index && !is_null_oid(&si->base_oid)) {
const char *shared_index = git_path("sharedindex.%s", char *shared_index = repo_git_path(the_repository, "sharedindex.%s",
oid_to_hex(&si->base_oid)); oid_to_hex(&si->base_oid));
freshen_shared_index(shared_index, 1); freshen_shared_index(shared_index, 1);
free(shared_index);
} }
out: out:

6
refs.c
View File

@ -2154,7 +2154,7 @@ struct ref_store *repo_get_submodule_ref_store(struct repository *repo,
if (!is_nonbare_repository_dir(&submodule_sb)) if (!is_nonbare_repository_dir(&submodule_sb))
goto done; goto done;
if (submodule_to_gitdir(&submodule_sb, submodule)) if (submodule_to_gitdir(repo, &submodule_sb, submodule))
goto done; goto done;
subrepo = xmalloc(sizeof(*subrepo)); subrepo = xmalloc(sizeof(*subrepo));
@ -2192,8 +2192,8 @@ struct ref_store *get_worktree_ref_store(const struct worktree *wt)
if (wt->id) { if (wt->id) {
struct strbuf common_path = STRBUF_INIT; struct strbuf common_path = STRBUF_INIT;
strbuf_git_common_path(&common_path, wt->repo, repo_common_path_append(wt->repo, &common_path,
"worktrees/%s", wt->id); "worktrees/%s", wt->id);
refs = ref_store_init(wt->repo, wt->repo->ref_storage_format, refs = ref_store_init(wt->repo, wt->repo->ref_storage_format,
common_path.buf, REF_STORE_ALL_CAPS); common_path.buf, REF_STORE_ALL_CAPS);
strbuf_release(&common_path); strbuf_release(&common_path);

View File

@ -1831,7 +1831,7 @@ static int log_ref_setup(struct files_ref_store *refs,
} }
if (*logfd >= 0) if (*logfd >= 0)
adjust_shared_perm(logfile); adjust_shared_perm(the_repository, logfile);
free(logfile); free(logfile);
return 0; 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. * they do not understand the reference format extension.
*/ */
strbuf_addf(&sb, "%s/refs", ref_store->gitdir); strbuf_addf(&sb, "%s/refs", ref_store->gitdir);
safe_create_dir(sb.buf, 1); safe_create_dir(the_repository, sb.buf, 1);
adjust_shared_perm(sb.buf); adjust_shared_perm(the_repository, sb.buf);
/* /*
* There is no need to create directories for common refs when creating * 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); strbuf_reset(&sb);
files_ref_path(refs, &sb, "refs/heads"); files_ref_path(refs, &sb, "refs/heads");
safe_create_dir(sb.buf, 1); safe_create_dir(the_repository, sb.buf, 1);
strbuf_reset(&sb); strbuf_reset(&sb);
files_ref_path(refs, &sb, "refs/tags"); files_ref_path(refs, &sb, "refs/tags");
safe_create_dir(sb.buf, 1); safe_create_dir(the_repository, sb.buf, 1);
} }
strbuf_release(&sb); strbuf_release(&sb);

View File

@ -380,7 +380,7 @@ static struct ref_store *reftable_be_init(struct repository *repo,
default: default:
BUG("unknown hash algorithm %d", repo->hash_algo->format_id); 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 = refs->write_options.disable_auto_compact =
!git_env_bool("GIT_TEST_REFTABLE_AUTOCOMPACTION", 1); !git_env_bool("GIT_TEST_REFTABLE_AUTOCOMPACTION", 1);
refs->write_options.lock_timeout_ms = 100; 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; struct strbuf sb = STRBUF_INIT;
strbuf_addf(&sb, "%s/reftable", refs->base.gitdir); 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_reset(&sb);
strbuf_addf(&sb, "%s/HEAD", refs->base.gitdir); strbuf_addf(&sb, "%s/HEAD", refs->base.gitdir);
write_file(sb.buf, "ref: refs/heads/.invalid"); write_file(sb.buf, "ref: refs/heads/.invalid");
adjust_shared_perm(sb.buf); adjust_shared_perm(the_repository, sb.buf);
strbuf_reset(&sb); strbuf_reset(&sb);
strbuf_addf(&sb, "%s/refs", refs->base.gitdir); 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_reset(&sb);
strbuf_addf(&sb, "%s/refs/heads", refs->base.gitdir); strbuf_addf(&sb, "%s/refs/heads", refs->base.gitdir);
write_file(sb.buf, "this repository uses the reftable format"); 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); strbuf_release(&sb);
return 0; return 0;

View File

@ -321,10 +321,11 @@ static void read_remotes_file(struct remote_state *remote_state,
struct remote *remote) struct remote *remote)
{ {
struct strbuf buf = STRBUF_INIT; 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) if (!f)
return; goto out;
warn_about_deprecated_remote_type("remotes", remote); 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)) else if (skip_prefix(buf.buf, "Pull:", &v))
refspec_append(&remote->fetch, skip_spaces(v)); refspec_append(&remote->fetch, skip_spaces(v));
} }
strbuf_release(&buf);
fclose(f); fclose(f);
out:
strbuf_release(&buf);
} }
static void read_branches_file(struct remote_state *remote_state, 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; char *frag, *to_free = NULL;
struct strbuf buf = STRBUF_INIT; 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) if (!f)
return; goto out;
warn_about_deprecated_remote_type("branches", remote); warn_about_deprecated_remote_type("branches", remote);
strbuf_getline_lf(&buf, f); strbuf_getline_lf(&buf, f);
fclose(f); fclose(f);
strbuf_trim(&buf); strbuf_trim(&buf);
if (!buf.len) { if (!buf.len)
strbuf_release(&buf); goto out;
return;
}
remote->configured_in_repo = 1; remote->configured_in_repo = 1;
remote->origin = REMOTE_BRANCHES; 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); refspec_appendf(&remote->push, "HEAD:refs/heads/%s", frag);
remote->fetch_tags = 1; /* always auto-follow */ remote->fetch_tags = 1; /* always auto-follow */
out:
strbuf_release(&buf); strbuf_release(&buf);
free(to_free); free(to_free);
} }

View File

@ -4,6 +4,7 @@
#include "repository.h" #include "repository.h"
#include "midx.h" #include "midx.h"
#include "pack-objects.h" #include "pack-objects.h"
#include "setup.h"
static void repo_cfg_bool(struct repository *r, const char *key, int *dest, static void repo_cfg_bool(struct repository *r, const char *key, int *dest,
int def) int def)
@ -21,7 +22,6 @@ static void repo_cfg_int(struct repository *r, const char *key, int *dest,
void prepare_repo_settings(struct repository *r) void prepare_repo_settings(struct repository *r)
{ {
const struct repo_settings defaults = REPO_SETTINGS_INIT;
int experimental; int experimental;
int value; int value;
const char *strval; const char *strval;
@ -35,7 +35,7 @@ void prepare_repo_settings(struct repository *r)
if (r->settings.initialized) if (r->settings.initialized)
return; return;
memcpy(&r->settings, &defaults, sizeof(defaults)); repo_settings_clear(r);
r->settings.initialized++; r->settings.initialized++;
/* Booleans config or default, cascades to other settings */ /* Booleans config or default, cascades to other settings */
@ -143,6 +143,14 @@ void prepare_repo_settings(struct repository *r)
r->settings.packed_git_limit = ulongval; r->settings.packed_git_limit = ulongval;
} }
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;
}
enum log_refs_config repo_settings_get_log_all_ref_updates(struct repository *repo) enum log_refs_config repo_settings_get_log_all_ref_updates(struct repository *repo)
{ {
const char *value; const char *value;
@ -167,3 +175,35 @@ int repo_settings_get_warn_ambiguous_refs(struct repository *repo)
&repo->settings.warn_ambiguous_refs, 1); &repo->settings.warn_ambiguous_refs, 1);
return repo->settings.warn_ambiguous_refs; 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;
}
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;
}

View File

@ -37,6 +37,9 @@ struct repo_settings {
int pack_use_bitmap_boundary_traversal; int pack_use_bitmap_boundary_traversal;
int pack_use_multi_pack_reuse; int pack_use_multi_pack_reuse;
int shared_repository;
int shared_repository_initialized;
/* /*
* Does this repository have core.useReplaceRefs=true (on by * Does this repository have core.useReplaceRefs=true (on by
* default)? This provides a repository-scoped version of this * default)? This provides a repository-scoped version of this
@ -61,8 +64,11 @@ struct repo_settings {
size_t delta_base_cache_limit; size_t delta_base_cache_limit;
size_t packed_git_window_size; size_t packed_git_window_size;
size_t packed_git_limit; size_t packed_git_limit;
char *hooks_path;
}; };
#define REPO_SETTINGS_INIT { \ #define REPO_SETTINGS_INIT { \
.shared_repository = -1, \
.index_version = -1, \ .index_version = -1, \
.core_untracked_cache = UNTRACKED_CACHE_KEEP, \ .core_untracked_cache = UNTRACKED_CACHE_KEEP, \
.fetch_negotiation_algorithm = FETCH_NEGOTIATION_CONSECUTIVE, \ .fetch_negotiation_algorithm = FETCH_NEGOTIATION_CONSECUTIVE, \
@ -73,10 +79,18 @@ struct repo_settings {
} }
void prepare_repo_settings(struct repository *r); void prepare_repo_settings(struct repository *r);
void repo_settings_clear(struct repository *r);
/* Read the value for "core.logAllRefUpdates". */ /* Read the value for "core.logAllRefUpdates". */
enum log_refs_config repo_settings_get_log_all_ref_updates(struct repository *repo); enum log_refs_config repo_settings_get_log_all_ref_updates(struct repository *repo);
/* Read the value for "core.warnAmbiguousRefs". */ /* Read the value for "core.warnAmbiguousRefs". */
int repo_settings_get_warn_ambiguous_refs(struct repository *repo); 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 */ #endif /* REPO_SETTINGS_H */

View File

@ -312,8 +312,8 @@ int repo_submodule_init(struct repository *subrepo,
struct strbuf worktree = STRBUF_INIT; struct strbuf worktree = STRBUF_INIT;
int ret = 0; int ret = 0;
strbuf_repo_worktree_path(&gitdir, superproject, "%s/.git", path); repo_worktree_path_append(superproject, &gitdir, "%s/.git", path);
strbuf_repo_worktree_path(&worktree, superproject, "%s", path); repo_worktree_path_append(superproject, &worktree, "%s", path);
if (repo_init(subrepo, gitdir.buf, worktree.buf)) { if (repo_init(subrepo, gitdir.buf, worktree.buf)) {
/* /*
@ -380,7 +380,7 @@ void repo_clear(struct repository *repo)
parsed_object_pool_clear(repo->parsed_objects); parsed_object_pool_clear(repo->parsed_objects);
FREE_AND_NULL(repo->parsed_objects); FREE_AND_NULL(repo->parsed_objects);
FREE_AND_NULL(repo->settings.fsmonitor); repo_settings_clear(repo);
if (repo->config) { if (repo->config) {
git_configset_clear(repo->config); git_configset_clear(repo->config);

101
rerere.c
View File

@ -91,16 +91,18 @@ static void assign_variant(struct rerere_id *id)
id->variant = variant; id->variant = variant;
} }
const char *rerere_path(const struct rerere_id *id, const char *file) const char *rerere_path(struct strbuf *buf, const struct rerere_id *id, const char *file)
{ {
if (!file) if (!file)
return git_path("rr-cache/%s", rerere_id_hex(id)); return repo_git_path_replace(the_repository, buf, "rr-cache/%s",
rerere_id_hex(id));
if (id->variant <= 0) if (id->variant <= 0)
return git_path("rr-cache/%s/%s", rerere_id_hex(id), file); return repo_git_path_replace(the_repository, buf, "rr-cache/%s/%s",
rerere_id_hex(id), file);
return git_path("rr-cache/%s/%s.%d", return repo_git_path_replace(the_repository, buf, "rr-cache/%s/%s.%d",
rerere_id_hex(id), file, id->variant); rerere_id_hex(id), file, id->variant);
} }
static int is_rr_file(const char *name, const char *filename, int *variant) static int is_rr_file(const char *name, const char *filename, int *variant)
@ -125,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) static void scan_rerere_dir(struct rerere_dir *rr_dir)
{ {
struct dirent *de; 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) if (!dir)
return; return;
while ((de = readdir(dir)) != NULL) { while ((de = readdir(dir)) != NULL) {
@ -624,9 +630,10 @@ static int try_merge(struct index_state *istate,
{ {
enum ll_merge_result ret; enum ll_merge_result ret;
mmfile_t base = {NULL, 0}, other = {NULL, 0}; mmfile_t base = {NULL, 0}, other = {NULL, 0};
struct strbuf buf = STRBUF_INIT;
if (read_mmfile(&base, rerere_path(id, "preimage")) || if (read_mmfile(&base, rerere_path(&buf, id, "preimage")) ||
read_mmfile(&other, rerere_path(id, "postimage"))) { read_mmfile(&other, rerere_path(&buf, id, "postimage"))) {
ret = LL_MERGE_CONFLICT; ret = LL_MERGE_CONFLICT;
} else { } else {
/* /*
@ -637,6 +644,7 @@ static int try_merge(struct index_state *istate,
istate, NULL); istate, NULL);
} }
strbuf_release(&buf);
free(base.ptr); free(base.ptr);
free(other.ptr); free(other.ptr);
@ -657,6 +665,7 @@ static int merge(struct index_state *istate, const struct rerere_id *id, const c
{ {
FILE *f; FILE *f;
int ret; int ret;
struct strbuf buf = STRBUF_INIT;
mmfile_t cur = {NULL, 0}; mmfile_t cur = {NULL, 0};
mmbuffer_t result = {NULL, 0}; mmbuffer_t result = {NULL, 0};
@ -664,8 +673,8 @@ static int merge(struct index_state *istate, const struct rerere_id *id, const c
* Normalize the conflicts in path and write it out to * Normalize the conflicts in path and write it out to
* "thisimage" temporary file. * "thisimage" temporary file.
*/ */
if ((handle_file(istate, path, NULL, rerere_path(id, "thisimage")) < 0) || if ((handle_file(istate, path, NULL, rerere_path(&buf, id, "thisimage")) < 0) ||
read_mmfile(&cur, rerere_path(id, "thisimage"))) { read_mmfile(&cur, rerere_path(&buf, id, "thisimage"))) {
ret = 1; ret = 1;
goto out; goto out;
} }
@ -678,9 +687,9 @@ static int merge(struct index_state *istate, const struct rerere_id *id, const c
* A successful replay of recorded resolution. * A successful replay of recorded resolution.
* Mark that "postimage" was used to help gc. * Mark that "postimage" was used to help gc.
*/ */
if (utime(rerere_path(id, "postimage"), NULL) < 0) if (utime(rerere_path(&buf, id, "postimage"), NULL) < 0)
warning_errno(_("failed utime() on '%s'"), warning_errno(_("failed utime() on '%s'"),
rerere_path(id, "postimage")); rerere_path(&buf, id, "postimage"));
/* Update "path" with the resolution */ /* Update "path" with the resolution */
f = fopen(path, "w"); f = fopen(path, "w");
@ -694,6 +703,7 @@ static int merge(struct index_state *istate, const struct rerere_id *id, const c
out: out:
free(cur.ptr); free(cur.ptr);
free(result.ptr); free(result.ptr);
strbuf_release(&buf);
return ret; return ret;
} }
@ -720,9 +730,11 @@ static void update_paths(struct repository *r, struct string_list *update)
static void remove_variant(struct rerere_id *id) static void remove_variant(struct rerere_id *id)
{ {
unlink_or_warn(rerere_path(id, "postimage")); struct strbuf buf = STRBUF_INIT;
unlink_or_warn(rerere_path(id, "preimage")); unlink_or_warn(rerere_path(&buf, id, "postimage"));
unlink_or_warn(rerere_path(&buf, id, "preimage"));
id->collection->status[id->variant] = 0; id->collection->status[id->variant] = 0;
strbuf_release(&buf);
} }
/* /*
@ -739,6 +751,7 @@ static void do_rerere_one_path(struct index_state *istate,
const char *path = rr_item->string; const char *path = rr_item->string;
struct rerere_id *id = rr_item->util; struct rerere_id *id = rr_item->util;
struct rerere_dir *rr_dir = id->collection; struct rerere_dir *rr_dir = id->collection;
struct strbuf buf = STRBUF_INIT;
int variant; int variant;
variant = id->variant; variant = id->variant;
@ -746,12 +759,12 @@ static void do_rerere_one_path(struct index_state *istate,
/* Has the user resolved it already? */ /* Has the user resolved it already? */
if (variant >= 0) { if (variant >= 0) {
if (!handle_file(istate, path, NULL, NULL)) { if (!handle_file(istate, path, NULL, NULL)) {
copy_file(rerere_path(id, "postimage"), path, 0666); copy_file(rerere_path(&buf, id, "postimage"), path, 0666);
id->collection->status[variant] |= RR_HAS_POSTIMAGE; id->collection->status[variant] |= RR_HAS_POSTIMAGE;
fprintf_ln(stderr, _("Recorded resolution for '%s'."), path); fprintf_ln(stderr, _("Recorded resolution for '%s'."), path);
free_rerere_id(rr_item); free_rerere_id(rr_item);
rr_item->util = NULL; rr_item->util = NULL;
return; goto out;
} }
/* /*
* There may be other variants that can cleanly * There may be other variants that can cleanly
@ -787,22 +800,25 @@ static void do_rerere_one_path(struct index_state *istate,
path); path);
free_rerere_id(rr_item); free_rerere_id(rr_item);
rr_item->util = NULL; rr_item->util = NULL;
return; goto out;
} }
/* None of the existing one applies; we need a new variant */ /* None of the existing one applies; we need a new variant */
assign_variant(id); assign_variant(id);
variant = id->variant; variant = id->variant;
handle_file(istate, path, NULL, rerere_path(id, "preimage")); handle_file(istate, path, NULL, rerere_path(&buf, id, "preimage"));
if (id->collection->status[variant] & RR_HAS_POSTIMAGE) { if (id->collection->status[variant] & RR_HAS_POSTIMAGE) {
const char *path = rerere_path(id, "postimage"); const char *path = rerere_path(&buf, id, "postimage");
if (unlink(path)) if (unlink(path))
die_errno(_("cannot unlink stray '%s'"), path); die_errno(_("cannot unlink stray '%s'"), path);
id->collection->status[variant] &= ~RR_HAS_POSTIMAGE; id->collection->status[variant] &= ~RR_HAS_POSTIMAGE;
} }
id->collection->status[variant] |= RR_HAS_PREIMAGE; id->collection->status[variant] |= RR_HAS_PREIMAGE;
fprintf_ln(stderr, _("Recorded preimage for '%s'"), path); fprintf_ln(stderr, _("Recorded preimage for '%s'"), path);
out:
strbuf_release(&buf);
} }
static int do_plain_rerere(struct repository *r, static int do_plain_rerere(struct repository *r,
@ -810,6 +826,7 @@ static int do_plain_rerere(struct repository *r,
{ {
struct string_list conflict = STRING_LIST_INIT_DUP; struct string_list conflict = STRING_LIST_INIT_DUP;
struct string_list update = STRING_LIST_INIT_DUP; struct string_list update = STRING_LIST_INIT_DUP;
struct strbuf buf = STRBUF_INIT;
int i; int i;
find_conflict(r, &conflict); find_conflict(r, &conflict);
@ -843,7 +860,7 @@ static int do_plain_rerere(struct repository *r,
string_list_insert(rr, path)->util = id; string_list_insert(rr, path)->util = id;
/* Ensure that the directory exists. */ /* Ensure that the directory exists. */
mkdir_in_gitdir(rerere_path(id, NULL)); mkdir_in_gitdir(rerere_path(&buf, id, NULL));
} }
for (i = 0; i < rr->nr; i++) for (i = 0; i < rr->nr; i++)
@ -854,6 +871,7 @@ static int do_plain_rerere(struct repository *r,
string_list_clear(&conflict, 0); string_list_clear(&conflict, 0);
string_list_clear(&update, 0); string_list_clear(&update, 0);
strbuf_release(&buf);
return write_rr(rr, fd); return write_rr(rr, fd);
} }
@ -1033,6 +1051,7 @@ static int rerere_forget_one_path(struct index_state *istate,
struct rerere_id *id; struct rerere_id *id;
unsigned char hash[GIT_MAX_RAWSZ]; unsigned char hash[GIT_MAX_RAWSZ];
int ret; int ret;
struct strbuf buf = STRBUF_INIT;
struct string_list_item *item; struct string_list_item *item;
/* /*
@ -1056,8 +1075,8 @@ static int rerere_forget_one_path(struct index_state *istate,
if (!has_rerere_resolution(id)) if (!has_rerere_resolution(id))
continue; continue;
handle_cache(istate, path, hash, rerere_path(id, "thisimage")); handle_cache(istate, path, hash, rerere_path(&buf, id, "thisimage"));
if (read_mmfile(&cur, rerere_path(id, "thisimage"))) { if (read_mmfile(&cur, rerere_path(&buf, id, "thisimage"))) {
free(cur.ptr); free(cur.ptr);
error(_("failed to update conflicted state in '%s'"), path); error(_("failed to update conflicted state in '%s'"), path);
goto fail_exit; goto fail_exit;
@ -1074,7 +1093,7 @@ static int rerere_forget_one_path(struct index_state *istate,
goto fail_exit; goto fail_exit;
} }
filename = rerere_path(id, "postimage"); filename = rerere_path(&buf, id, "postimage");
if (unlink(filename)) { if (unlink(filename)) {
if (errno == ENOENT) if (errno == ENOENT)
error(_("no remembered resolution for '%s'"), path); error(_("no remembered resolution for '%s'"), path);
@ -1088,7 +1107,7 @@ static int rerere_forget_one_path(struct index_state *istate,
* conflict in the working tree, run us again to record * conflict in the working tree, run us again to record
* the postimage. * the postimage.
*/ */
handle_cache(istate, path, hash, rerere_path(id, "preimage")); handle_cache(istate, path, hash, rerere_path(&buf, id, "preimage"));
fprintf_ln(stderr, _("Updated preimage for '%s'"), path); fprintf_ln(stderr, _("Updated preimage for '%s'"), path);
/* /*
@ -1099,9 +1118,11 @@ static int rerere_forget_one_path(struct index_state *istate,
free_rerere_id(item); free_rerere_id(item);
item->util = id; item->util = id;
fprintf(stderr, _("Forgot resolution for '%s'\n"), path); fprintf(stderr, _("Forgot resolution for '%s'\n"), path);
strbuf_release(&buf);
return 0; return 0;
fail_exit: fail_exit:
strbuf_release(&buf);
free(id); free(id);
return -1; return -1;
} }
@ -1147,16 +1168,26 @@ int rerere_forget(struct repository *r, struct pathspec *pathspec)
static timestamp_t rerere_created_at(struct rerere_id *id) static timestamp_t rerere_created_at(struct rerere_id *id)
{ {
struct strbuf buf = STRBUF_INIT;
struct stat st; struct stat st;
timestamp_t ret;
return stat(rerere_path(id, "preimage"), &st) ? (time_t) 0 : st.st_mtime; ret = stat(rerere_path(&buf, id, "preimage"), &st) ? (time_t) 0 : st.st_mtime;
strbuf_release(&buf);
return ret;
} }
static timestamp_t rerere_last_used_at(struct rerere_id *id) static timestamp_t rerere_last_used_at(struct rerere_id *id)
{ {
struct strbuf buf = STRBUF_INIT;
struct stat st; struct stat st;
timestamp_t ret;
return stat(rerere_path(id, "postimage"), &st) ? (time_t) 0 : st.st_mtime; ret = stat(rerere_path(&buf, id, "postimage"), &st) ? (time_t) 0 : st.st_mtime;
strbuf_release(&buf);
return ret;
} }
/* /*
@ -1164,9 +1195,11 @@ static timestamp_t rerere_last_used_at(struct rerere_id *id)
*/ */
static void unlink_rr_item(struct rerere_id *id) static void unlink_rr_item(struct rerere_id *id)
{ {
unlink_or_warn(rerere_path(id, "thisimage")); struct strbuf buf = STRBUF_INIT;
unlink_or_warn(rerere_path(&buf, id, "thisimage"));
remove_variant(id); remove_variant(id);
id->collection->status[id->variant] = 0; id->collection->status[id->variant] = 0;
strbuf_release(&buf);
} }
static void prune_one(struct rerere_id *id, static void prune_one(struct rerere_id *id,
@ -1205,6 +1238,7 @@ void rerere_gc(struct repository *r, struct string_list *rr)
timestamp_t now = time(NULL); timestamp_t now = time(NULL);
timestamp_t cutoff_noresolve = now - 15 * 86400; timestamp_t cutoff_noresolve = now - 15 * 86400;
timestamp_t cutoff_resolve = now - 60 * 86400; timestamp_t cutoff_resolve = now - 60 * 86400;
struct strbuf buf = STRBUF_INIT;
if (setup_rerere(r, rr, 0) < 0) if (setup_rerere(r, rr, 0) < 0)
return; return;
@ -1214,7 +1248,7 @@ void rerere_gc(struct repository *r, struct string_list *rr)
repo_config_get_expiry_in_days(the_repository, "gc.rerereunresolved", repo_config_get_expiry_in_days(the_repository, "gc.rerereunresolved",
&cutoff_noresolve, now); &cutoff_noresolve, now);
git_config(git_default_config, NULL); 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) if (!dir)
die_errno(_("unable to open rr-cache directory")); die_errno(_("unable to open rr-cache directory"));
/* Collect stale conflict IDs ... */ /* Collect stale conflict IDs ... */
@ -1243,9 +1277,12 @@ void rerere_gc(struct repository *r, struct string_list *rr)
/* ... and then remove the empty directories */ /* ... and then remove the empty directories */
for (i = 0; i < to_remove.nr; i++) 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); string_list_clear(&to_remove, 0);
rollback_lock_file(&write_lock); rollback_lock_file(&write_lock);
strbuf_release(&buf);
} }
/* /*
@ -1264,10 +1301,14 @@ void rerere_clear(struct repository *r, struct string_list *merge_rr)
for (i = 0; i < merge_rr->nr; i++) { for (i = 0; i < merge_rr->nr; i++) {
struct rerere_id *id = merge_rr->items[i].util; struct rerere_id *id = merge_rr->items[i].util;
struct strbuf buf = STRBUF_INIT;
if (!has_rerere_resolution(id)) { if (!has_rerere_resolution(id)) {
unlink_rr_item(id); unlink_rr_item(id);
rmdir(rerere_path(id, NULL)); rmdir(rerere_path(&buf, id, NULL));
} }
strbuf_release(&buf);
} }
unlink_or_warn(git_path_merge_rr(r)); unlink_or_warn(git_path_merge_rr(r));
rollback_lock_file(&write_lock); rollback_lock_file(&write_lock);

View File

@ -32,7 +32,8 @@ int repo_rerere(struct repository *, int);
* path to that filesystem entity. With "file" specified with NULL, * path to that filesystem entity. With "file" specified with NULL,
* return the path to the directory that houses these files. * return the path to the directory that houses these files.
*/ */
const char *rerere_path(const struct rerere_id *, const char *file); const char *rerere_path(struct strbuf *buf, const struct rerere_id *,
const char *file);
int rerere_forget(struct repository *, struct pathspec *); int rerere_forget(struct repository *, struct pathspec *);
int rerere_remaining(struct repository *, struct string_list *); int rerere_remaining(struct repository *, struct string_list *);
void rerere_clear(struct repository *, struct string_list *); void rerere_clear(struct repository *, struct string_list *);

View File

@ -1874,15 +1874,20 @@ void add_index_objects_to_pending(struct rev_info *revs, unsigned int flags)
for (p = worktrees; *p; p++) { for (p = worktrees; *p; p++) {
struct worktree *wt = *p; struct worktree *wt = *p;
struct index_state istate = INDEX_STATE_INIT(revs->repo); struct index_state istate = INDEX_STATE_INIT(revs->repo);
char *wt_gitdir;
if (wt->is_current) if (wt->is_current)
continue; /* current index already taken care of */ continue; /* current index already taken care of */
wt_gitdir = get_worktree_git_dir(wt);
if (read_index_from(&istate, if (read_index_from(&istate,
worktree_git_path(the_repository, wt, "index"), worktree_git_path(the_repository, wt, "index"),
get_worktree_git_dir(wt)) > 0) wt_gitdir) > 0)
do_add_index_objects_to_pending(revs, &istate, flags); do_add_index_objects_to_pending(revs, &istate, flags);
discard_index(&istate); discard_index(&istate);
free(wt_gitdir);
} }
free_worktrees(worktrees); free_worktrees(worktrees);
} }

View File

@ -125,7 +125,7 @@ static int update_info_file(struct repository *r, char *path,
uic.cur_fp = NULL; uic.cur_fp = NULL;
if (uic_is_stale(&uic)) { 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; goto out;
if (rename_tempfile(&f, path) < 0) if (rename_tempfile(&f, path) < 0)
goto out; goto out;

70
setup.c
View File

@ -792,7 +792,7 @@ int upgrade_repository_format(int target_version)
struct repository_format repo_fmt = REPOSITORY_FORMAT_INIT; struct repository_format repo_fmt = REPOSITORY_FORMAT_INIT;
int ret; int ret;
strbuf_git_common_path(&sb, the_repository, "config"); repo_common_path_append(the_repository, &sb, "config");
read_repository_format(&repo_fmt, sb.buf); read_repository_format(&repo_fmt, sb.buf);
strbuf_release(&sb); strbuf_release(&sb);
@ -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 * with the way the namespace under .git/ is organized, should
* be really carefully chosen. * be really carefully chosen.
*/ */
safe_create_dir(path->buf, 1); safe_create_dir(the_repository, path->buf, 1);
while ((de = readdir(dir)) != NULL) { while ((de = readdir(dir)) != NULL) {
struct stat st_git, st_template; struct stat st_git, st_template;
int exists = 0; int exists = 0;
@ -2242,7 +2242,7 @@ void initialize_repository_version(int hash_algo,
struct strbuf config = STRBUF_INIT; struct strbuf config = STRBUF_INIT;
struct repository_format repo_fmt = REPOSITORY_FORMAT_INIT; struct repository_format repo_fmt = REPOSITORY_FORMAT_INIT;
strbuf_git_common_path(&config, the_repository, "config"); repo_common_path_append(the_repository, &config, "config");
read_repository_format(&repo_fmt, config.buf); read_repository_format(&repo_fmt, config.buf);
if (repo_fmt.v1_only_extensions.nr) if (repo_fmt.v1_only_extensions.nr)
@ -2264,7 +2264,7 @@ static int is_reinit(void)
char junk[2]; char junk[2];
int ret; int ret;
git_path_buf(&buf, "HEAD"); repo_git_path_replace(the_repository, &buf, "HEAD");
ret = !access(buf.buf, R_OK) || readlink(buf.buf, junk, sizeof(junk) - 1) != -1; ret = !access(buf.buf, R_OK) || readlink(buf.buf, junk, sizeof(junk) - 1) != -1;
strbuf_release(&buf); strbuf_release(&buf);
return ret; return ret;
@ -2316,8 +2316,7 @@ static int create_default_files(const char *template_path,
int init_shared_repository) int init_shared_repository)
{ {
struct stat st1; struct stat st1;
struct strbuf buf = STRBUF_INIT; struct strbuf path = STRBUF_INIT;
char *path;
int reinit; int reinit;
int filemode; int filemode;
const char *work_tree = repo_get_work_tree(the_repository); const char *work_tree = repo_get_work_tree(the_repository);
@ -2333,7 +2332,7 @@ static int create_default_files(const char *template_path,
*/ */
copy_templates(template_path); copy_templates(template_path);
git_config_clear(); git_config_clear();
reset_shared_repository(); repo_settings_reset_shared_repository(the_repository);
git_config(git_default_config, NULL); git_config(git_default_config, NULL);
reinit = is_reinit(); reinit = is_reinit();
@ -2343,7 +2342,8 @@ static int create_default_files(const char *template_path,
* values we might have just re-read from the config. * values we might have just re-read from the config.
*/ */
if (init_shared_repository != -1) 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; is_bare_repository_cfg = !work_tree;
@ -2351,21 +2351,21 @@ static int create_default_files(const char *template_path,
* We would have created the above under user's umask -- under * We would have created the above under user's umask -- under
* shared-repository settings, we would need to fix them up. * 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)); adjust_shared_perm(the_repository, repo_get_git_dir(the_repository));
} }
initialize_repository_version(fmt->hash_algo, fmt->ref_storage_format, reinit); initialize_repository_version(fmt->hash_algo, fmt->ref_storage_format, reinit);
/* Check filemode trustability */ /* Check filemode trustability */
path = git_path_buf(&buf, "config"); repo_git_path_replace(the_repository, &path, "config");
filemode = TEST_FILEMODE; filemode = TEST_FILEMODE;
if (TEST_FILEMODE && !lstat(path, &st1)) { if (TEST_FILEMODE && !lstat(path.buf, &st1)) {
struct stat st2; struct stat st2;
filemode = (!chmod(path, st1.st_mode ^ S_IXUSR) && filemode = (!chmod(path.buf, st1.st_mode ^ S_IXUSR) &&
!lstat(path, &st2) && !lstat(path.buf, &st2) &&
st1.st_mode != st2.st_mode && st1.st_mode != st2.st_mode &&
!chmod(path, st1.st_mode)); !chmod(path.buf, st1.st_mode));
if (filemode && !reinit && (st1.st_mode & S_IXUSR)) if (filemode && !reinit && (st1.st_mode & S_IXUSR))
filemode = 0; filemode = 0;
} }
@ -2384,24 +2384,24 @@ static int create_default_files(const char *template_path,
if (!reinit) { if (!reinit) {
/* Check if symlink is supported in the work tree */ /* Check if symlink is supported in the work tree */
path = git_path_buf(&buf, "tXXXXXX"); repo_git_path_replace(the_repository, &path, "tXXXXXX");
if (!close(xmkstemp(path)) && if (!close(xmkstemp(path.buf)) &&
!unlink(path) && !unlink(path.buf) &&
!symlink("testing", path) && !symlink("testing", path.buf) &&
!lstat(path, &st1) && !lstat(path.buf, &st1) &&
S_ISLNK(st1.st_mode)) S_ISLNK(st1.st_mode))
unlink(path); /* good */ unlink(path.buf); /* good */
else else
git_config_set("core.symlinks", "false"); git_config_set("core.symlinks", "false");
/* Check if the filesystem is case-insensitive */ /* Check if the filesystem is case-insensitive */
path = git_path_buf(&buf, "CoNfIg"); repo_git_path_replace(the_repository, &path, "CoNfIg");
if (!access(path, F_OK)) if (!access(path.buf, F_OK))
git_config_set("core.ignorecase", "true"); git_config_set("core.ignorecase", "true");
probe_utf8_pathname_composition(); probe_utf8_pathname_composition();
} }
strbuf_release(&buf); strbuf_release(&path);
return reinit; return reinit;
} }
@ -2413,15 +2413,15 @@ static void create_object_directory(void)
strbuf_addstr(&path, repo_get_object_directory(the_repository)); strbuf_addstr(&path, repo_get_object_directory(the_repository));
baselen = path.len; baselen = path.len;
safe_create_dir(path.buf, 1); safe_create_dir(the_repository, path.buf, 1);
strbuf_setlen(&path, baselen); strbuf_setlen(&path, baselen);
strbuf_addstr(&path, "/pack"); strbuf_addstr(&path, "/pack");
safe_create_dir(path.buf, 1); safe_create_dir(the_repository, path.buf, 1);
strbuf_setlen(&path, baselen); strbuf_setlen(&path, baselen);
strbuf_addstr(&path, "/info"); strbuf_addstr(&path, "/info");
safe_create_dir(path.buf, 1); safe_create_dir(the_repository, path.buf, 1);
strbuf_release(&path); strbuf_release(&path);
} }
@ -2592,7 +2592,7 @@ int init_db(const char *git_dir, const char *real_git_dir,
*/ */
git_config(platform_core_config, NULL); 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, reinit = create_default_files(template_dir, original_git_dir,
&repo_fmt, init_shared_repository); &repo_fmt, init_shared_repository);
@ -2602,7 +2602,7 @@ int init_db(const char *git_dir, const char *real_git_dir,
initial_branch, flags & INIT_DB_QUIET); initial_branch, flags & INIT_DB_QUIET);
create_object_directory(); create_object_directory();
if (get_shared_repository()) { if (repo_settings_get_shared_repository(the_repository)) {
char buf[10]; char buf[10];
/* We do not spell "group" and such, so that /* We do not spell "group" and such, so that
* the configuration can be read by older version * the configuration can be read by older version
@ -2610,12 +2610,12 @@ int init_db(const char *git_dir, const char *real_git_dir,
* and compatibility values for PERM_GROUP and * and compatibility values for PERM_GROUP and
* PERM_EVERYBODY. * PERM_EVERYBODY.
*/ */
if (get_shared_repository() < 0) if (repo_settings_get_shared_repository(the_repository) < 0)
/* force to the mode value */ /* force to the mode value */
xsnprintf(buf, sizeof(buf), "0%o", -get_shared_repository()); xsnprintf(buf, sizeof(buf), "0%o", -repo_settings_get_shared_repository(the_repository));
else if (get_shared_repository() == PERM_GROUP) else if (repo_settings_get_shared_repository(the_repository) == PERM_GROUP)
xsnprintf(buf, sizeof(buf), "%d", OLD_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); xsnprintf(buf, sizeof(buf), "%d", OLD_PERM_EVERYBODY);
else else
BUG("invalid value for shared_repository"); BUG("invalid value for shared_repository");
@ -2627,12 +2627,12 @@ int init_db(const char *git_dir, const char *real_git_dir,
int len = strlen(git_dir); int len = strlen(git_dir);
if (reinit) 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 shared Git repository in %s%s\n")
: _("Reinitialized existing Git repository in %s%s\n"), : _("Reinitialized existing Git repository in %s%s\n"),
git_dir, len && git_dir[len-1] != '/' ? "/" : ""); git_dir, len && git_dir[len-1] != '/' ? "/" : "");
else else
printf(get_shared_repository() printf(repo_settings_get_shared_repository(the_repository)
? _("Initialized empty shared Git repository in %s%s\n") ? _("Initialized empty shared Git repository in %s%s\n")
: _("Initialized empty Git repository in %s%s\n"), : _("Initialized empty Git repository in %s%s\n"),
git_dir, len && git_dir[len-1] != '/' ? "/" : ""); git_dir, len && git_dir[len-1] != '/' ? "/" : "");

View File

@ -364,7 +364,9 @@ const char *setup_temporary_shallow(const struct oid_array *extra)
struct strbuf sb = STRBUF_INIT; struct strbuf sb = STRBUF_INIT;
if (write_shallow_commits(&sb, 0, extra)) { 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 || if (write_in_full(temp->fd, sb.buf, sb.len) < 0 ||
close_tempfile_gently(temp) < 0) close_tempfile_gently(temp) < 0)

View File

@ -536,7 +536,8 @@ static struct repository *open_submodule(const char *path)
struct strbuf sb = STRBUF_INIT; struct strbuf sb = STRBUF_INIT;
struct repository *out = xmalloc(sizeof(*out)); 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); strbuf_release(&sb);
free(out); free(out);
return NULL; return NULL;
@ -1315,7 +1316,7 @@ static int repo_has_absorbed_submodules(struct repository *r)
int ret; int ret;
struct strbuf buf = STRBUF_INIT; 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); ret = file_exists(buf.buf) && !is_empty_dir(buf.buf);
strbuf_release(&buf); strbuf_release(&buf);
return ret; return ret;
@ -2572,7 +2573,8 @@ int get_superproject_working_tree(struct strbuf *buf)
* Put the gitdir for a submodule (given relative to the main * Put the gitdir for a submodule (given relative to the main
* repository worktree) into `buf`, or return -1 on error. * 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 struct submodule *sub;
const char *git_dir; const char *git_dir;
@ -2592,14 +2594,13 @@ int submodule_to_gitdir(struct strbuf *buf, const char *submodule)
strbuf_addstr(buf, git_dir); strbuf_addstr(buf, git_dir);
} }
if (!is_git_directory(buf->buf)) { if (!is_git_directory(buf->buf)) {
sub = submodule_from_path(the_repository, null_oid(), sub = submodule_from_path(repo, null_oid(), submodule);
submodule);
if (!sub) { if (!sub) {
ret = -1; ret = -1;
goto cleanup; goto cleanup;
} }
strbuf_reset(buf); strbuf_reset(buf);
submodule_name_to_gitdir(buf, the_repository, sub->name); submodule_name_to_gitdir(buf, repo, sub->name);
} }
cleanup: cleanup:
@ -2629,6 +2630,6 @@ void submodule_name_to_gitdir(struct strbuf *buf, struct repository *r,
* administrators can explicitly set. Nothing has been decided, * administrators can explicitly set. Nothing has been decided,
* so for now, just append the name at the end of the path. * 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); strbuf_addstr(buf, submodule_name);
} }

View File

@ -136,7 +136,8 @@ int push_unpushed_submodules(struct repository *r,
* path of that submodule in 'buf'. Return -1 on error or when the * path of that submodule in 'buf'. Return -1 on error or when the
* submodule is not initialized. * 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 * Given a submodule name, create a path to where the submodule's gitdir lives

View File

@ -75,11 +75,10 @@ static const char **get_store(const char **argv, struct ref_store **refs)
*refs = get_main_ref_store(the_repository); *refs = get_main_ref_store(the_repository);
} else if (skip_prefix(argv[0], "submodule:", &gitdir)) { } else if (skip_prefix(argv[0], "submodule:", &gitdir)) {
struct strbuf sb = STRBUF_INIT; struct strbuf sb = STRBUF_INIT;
int ret;
ret = strbuf_git_path_submodule(&sb, gitdir, "objects/"); if (!repo_submodule_path_append(the_repository,
if (ret) &sb, gitdir, "objects/"))
die("strbuf_git_path_submodule failed: %d", ret); die("computing submodule path failed");
add_to_alternates_memory(sb.buf); add_to_alternates_memory(sb.buf);
strbuf_release(&sb); strbuf_release(&sb);

View File

@ -42,6 +42,8 @@
* file created by its parent. * file created by its parent.
*/ */
#define USE_THE_REPOSITORY_VARIABLE
#include "git-compat-util.h" #include "git-compat-util.h"
#include "abspath.h" #include "abspath.h"
#include "path.h" #include "path.h"
@ -148,7 +150,7 @@ struct tempfile *create_tempfile_mode(const char *path, int mode)
return NULL; return NULL;
} }
activate_tempfile(tempfile); activate_tempfile(tempfile);
if (adjust_shared_perm(tempfile->filename.buf)) { if (adjust_shared_perm(the_repository, tempfile->filename.buf)) {
int save_errno = errno; int save_errno = errno;
error("cannot fix permission bits on %s", tempfile->filename.buf); error("cannot fix permission bits on %s", tempfile->filename.buf);
delete_tempfile(&tempfile); delete_tempfile(&tempfile);

View File

@ -207,10 +207,12 @@ static int read_dir_paths(struct string_list *out, const char *path)
return 0; 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); 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) enum finalize_object_file_flags flags)
{ {
struct stat st; struct stat st;
@ -219,11 +221,11 @@ static int migrate_one(struct strbuf *src, struct strbuf *dst,
return -1; return -1;
if (S_ISDIR(st.st_mode)) { if (S_ISDIR(st.st_mode)) {
if (!mkdir(dst->buf, 0777)) { if (!mkdir(dst->buf, 0777)) {
if (adjust_shared_perm(dst->buf)) if (adjust_shared_perm(t->repo, dst->buf))
return -1; return -1;
} else if (errno != EEXIST) } else if (errno != EEXIST)
return -1; 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); 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]); 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) enum finalize_object_file_flags flags)
{ {
size_t src_len = src->len, dst_len = dst->len; 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)) if (is_loose_object_shard(name))
flags_copy |= FOF_SKIP_COLLISION_CHECK; 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(src, src_len);
strbuf_setlen(dst, dst_len); strbuf_setlen(dst, dst_len);
@ -283,7 +286,7 @@ int tmp_objdir_migrate(struct tmp_objdir *t)
strbuf_addbuf(&src, &t->path); strbuf_addbuf(&src, &t->path);
strbuf_addstr(&dst, repo_get_object_directory(t->repo)); 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(&src);
strbuf_release(&dst); strbuf_release(&dst);

View File

@ -59,8 +59,9 @@ static void add_head_info(struct worktree *wt)
static int is_current_worktree(struct worktree *wt) static int is_current_worktree(struct worktree *wt)
{ {
char *git_dir = absolute_pathdup(repo_get_git_dir(the_repository)); char *git_dir = absolute_pathdup(repo_get_git_dir(the_repository));
const char *wt_git_dir = get_worktree_git_dir(wt); char *wt_git_dir = get_worktree_git_dir(wt);
int is_current = !fspathcmp(git_dir, absolute_path(wt_git_dir)); int is_current = !fspathcmp(git_dir, absolute_path(wt_git_dir));
free(wt_git_dir);
free(git_dir); free(git_dir);
return is_current; return is_current;
} }
@ -127,7 +128,7 @@ struct worktree *get_linked_worktree(const char *id,
if (!id) if (!id)
die("Missing linked worktree name"); die("Missing linked worktree name");
strbuf_git_common_path(&path, the_repository, "worktrees/%s/gitdir", id); repo_common_path_append(the_repository, &path, "worktrees/%s/gitdir", id);
if (strbuf_read_file(&worktree_path, path.buf, 0) <= 0) if (strbuf_read_file(&worktree_path, path.buf, 0) <= 0)
/* invalid gitdir file */ /* invalid gitdir file */
goto done; goto done;
@ -198,14 +199,14 @@ struct worktree **get_worktrees(void)
return get_worktrees_internal(0); return get_worktrees_internal(0);
} }
const char *get_worktree_git_dir(const struct worktree *wt) char *get_worktree_git_dir(const struct worktree *wt)
{ {
if (!wt) if (!wt)
return repo_get_git_dir(the_repository); return xstrdup(repo_get_git_dir(the_repository));
else if (!wt->id) else if (!wt->id)
return repo_get_common_dir(the_repository); return xstrdup(repo_get_common_dir(the_repository));
else else
return 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, static struct worktree *find_worktree_by_suffix(struct worktree **list,
@ -336,6 +337,7 @@ int validate_worktree(const struct worktree *wt, struct strbuf *errmsg,
{ {
struct strbuf wt_path = STRBUF_INIT; struct strbuf wt_path = STRBUF_INIT;
struct strbuf realpath = STRBUF_INIT; struct strbuf realpath = STRBUF_INIT;
struct strbuf buf = STRBUF_INIT;
char *path = NULL; char *path = NULL;
int err, ret = -1; int err, ret = -1;
@ -365,7 +367,7 @@ int validate_worktree(const struct worktree *wt, struct strbuf *errmsg,
if (!is_absolute_path(wt->path)) { if (!is_absolute_path(wt->path)) {
strbuf_addf_gently(errmsg, strbuf_addf_gently(errmsg,
_("'%s' file does not contain absolute path to the working tree location"), _("'%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; goto done;
} }
@ -387,14 +389,16 @@ int validate_worktree(const struct worktree *wt, struct strbuf *errmsg,
goto done; 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); ret = fspathcmp(path, realpath.buf);
if (ret) if (ret)
strbuf_addf_gently(errmsg, _("'%s' does not point back to '%s'"), 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: done:
free(path); free(path);
strbuf_release(&buf);
strbuf_release(&wt_path); strbuf_release(&wt_path);
strbuf_release(&realpath); strbuf_release(&realpath);
return ret; return ret;
@ -406,11 +410,13 @@ void update_worktree_location(struct worktree *wt, const char *path_,
struct strbuf path = STRBUF_INIT; struct strbuf path = STRBUF_INIT;
struct strbuf dotgit = STRBUF_INIT; struct strbuf dotgit = STRBUF_INIT;
struct strbuf gitdir = STRBUF_INIT; struct strbuf gitdir = STRBUF_INIT;
char *wt_gitdir;
if (is_main_worktree(wt)) if (is_main_worktree(wt))
BUG("can't relocate main worktree"); 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_realpath(&path, path_, 1);
strbuf_addf(&dotgit, "%s/.git", path.buf); strbuf_addf(&dotgit, "%s/.git", path.buf);
if (fspathcmp(wt->path, path.buf)) { if (fspathcmp(wt->path, path.buf)) {
@ -422,6 +428,7 @@ void update_worktree_location(struct worktree *wt, const char *path_,
strbuf_release(&path); strbuf_release(&path);
strbuf_release(&dotgit); strbuf_release(&dotgit);
strbuf_release(&gitdir); strbuf_release(&gitdir);
free(wt_gitdir);
} }
int is_worktree_being_rebased(const struct worktree *wt, int is_worktree_being_rebased(const struct worktree *wt,
@ -510,7 +517,8 @@ int submodule_uses_worktrees(const char *path)
int ret = 0; int ret = 0;
struct repository_format format = REPOSITORY_FORMAT_INIT; 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) if (!submodule_gitdir)
return 0; return 0;
@ -606,6 +614,7 @@ static void repair_gitfile(struct worktree *wt,
struct strbuf backlink = STRBUF_INIT; struct strbuf backlink = STRBUF_INIT;
char *dotgit_contents = NULL; char *dotgit_contents = NULL;
const char *repair = NULL; const char *repair = NULL;
char *path = NULL;
int err; int err;
/* missing worktree can't be repaired */ /* missing worktree can't be repaired */
@ -617,7 +626,8 @@ static void repair_gitfile(struct worktree *wt,
goto done; 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(&dotgit, "%s/.git", wt->path);
strbuf_addf(&gitdir, "%s/gitdir", repo.buf); strbuf_addf(&gitdir, "%s/gitdir", repo.buf);
dotgit_contents = xstrdup_or_null(read_gitfile_gently(dotgit.buf, &err)); dotgit_contents = xstrdup_or_null(read_gitfile_gently(dotgit.buf, &err));
@ -647,6 +657,7 @@ static void repair_gitfile(struct worktree *wt,
done: done:
free(dotgit_contents); free(dotgit_contents);
free(path);
strbuf_release(&repo); strbuf_release(&repo);
strbuf_release(&dotgit); strbuf_release(&dotgit);
strbuf_release(&gitdir); strbuf_release(&gitdir);
@ -678,11 +689,13 @@ void repair_worktree_after_gitdir_move(struct worktree *wt, const char *old_path
struct strbuf gitdir = STRBUF_INIT; struct strbuf gitdir = STRBUF_INIT;
struct strbuf dotgit = STRBUF_INIT; struct strbuf dotgit = STRBUF_INIT;
int is_relative_path; int is_relative_path;
char *path = NULL;
if (is_main_worktree(wt)) if (is_main_worktree(wt))
goto done; 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) if (strbuf_read_file(&dotgit, gitdir.buf, 0) < 0)
goto done; goto done;
@ -701,6 +714,7 @@ void repair_worktree_after_gitdir_move(struct worktree *wt, const char *old_path
done: done:
strbuf_release(&gitdir); strbuf_release(&gitdir);
strbuf_release(&dotgit); strbuf_release(&dotgit);
free(path);
} }
void repair_worktrees_after_gitdir_move(const char *old_path) void repair_worktrees_after_gitdir_move(const char *old_path)
@ -754,8 +768,7 @@ static ssize_t infer_backlink(const char *gitfile, struct strbuf *inferred)
id++; /* advance past '/' to point at <id> */ id++; /* advance past '/' to point at <id> */
if (!*id) if (!*id)
goto error; goto error;
strbuf_reset(inferred); repo_common_path_replace(the_repository, inferred, "worktrees/%s", id);
strbuf_git_common_path(inferred, the_repository, "worktrees/%s", id);
if (!is_directory(inferred->buf)) if (!is_directory(inferred->buf))
goto error; goto error;
@ -893,7 +906,11 @@ int should_prune_worktree(const char *id, struct strbuf *reason, char **wtpath,
ssize_t read_result; ssize_t read_result;
*wtpath = NULL; *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); strbuf_addf(&gitdir, "%s/gitdir", repo.buf);
if (!is_directory(repo.buf)) { if (!is_directory(repo.buf)) {
strbuf_addstr(reason, _("not a valid directory")); strbuf_addstr(reason, _("not a valid directory"));

View File

@ -39,7 +39,7 @@ int submodule_uses_worktrees(const char *path);
* Return git dir of the worktree. Note that the path may be relative. * Return git dir of the worktree. Note that the path may be relative.
* If wt is NULL, git dir of current worktree is returned. * If wt is NULL, git dir of current worktree is returned.
*/ */
const char *get_worktree_git_dir(const struct worktree *wt); char *get_worktree_git_dir(const struct worktree *wt);
/* /*
* Search for the worktree identified unambiguously by `arg` -- typically * Search for the worktree identified unambiguously by `arg` -- typically

View File

@ -1289,7 +1289,8 @@ static void show_am_in_progress(struct wt_status *s,
static char *read_line_from_git_path(const char *filename) static char *read_line_from_git_path(const char *filename)
{ {
struct strbuf buf = STRBUF_INIT; 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) { if (!fp) {
strbuf_release(&buf); 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) static int read_rebase_todolist(const char *fname, struct string_list *lines)
{ {
struct strbuf line = STRBUF_INIT; struct strbuf buf = STRBUF_INIT;
FILE *f = fopen(git_path("%s", fname), "r"); FILE *f = fopen(repo_git_path_append(the_repository, &buf, "%s", fname), "r");
int ret;
if (!f) { if (!f) {
if (errno == ENOENT) if (errno == ENOENT) {
return -1; ret = -1;
goto out;
}
die_errno("Could not open file %s for reading", 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)) { while (!strbuf_getline_lf(&buf, f)) {
if (starts_with(line.buf, comment_line_str)) if (starts_with(buf.buf, comment_line_str))
continue; continue;
strbuf_trim(&line); strbuf_trim(&buf);
if (!line.len) if (!buf.len)
continue; continue;
abbrev_oid_in_line(&line); abbrev_oid_in_line(&buf);
string_list_append(lines, line.buf); string_list_append(lines, buf.buf);
} }
fclose(f); fclose(f);
strbuf_release(&line);
return 0; ret = 0;
out:
strbuf_release(&buf);
return ret;
} }
static void show_rebase_information(struct wt_status *s, 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 < have_done.nr;
i++) i++)
status_printf_ln(s, color, " %s", have_done.items[i].string); 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, 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) if (yet_to_do.nr == 0)