diff --git a/branch.c b/branch.c index 243db7d0fc..4f38905bad 100644 --- a/branch.c +++ b/branch.c @@ -372,7 +372,7 @@ int read_branch_desc(struct strbuf *buf, const char *branch_name) */ int validate_branchname(const char *name, struct strbuf *ref) { - if (check_branch_ref(ref, name)) { + if (check_branch_ref(the_repository, ref, name)) { int code = die_message(_("'%s' is not a valid branch name"), name); advise_if_enabled(ADVICE_REF_SYNTAX, _("See 'git help check-ref-format'")); @@ -394,7 +394,7 @@ static void prepare_checked_out_branches(void) return; initialized_checked_out_branches = 1; - worktrees = get_worktrees(); + worktrees = get_worktrees(the_repository); while (worktrees[i]) { char *old, *wt_gitdir; @@ -846,7 +846,7 @@ void remove_branch_state(struct repository *r, int verbose) void die_if_checked_out(const char *branch, int ignore_current_worktree) { - struct worktree **worktrees = get_worktrees(); + struct worktree **worktrees = get_worktrees(the_repository); for (int i = 0; worktrees[i]; i++) { if (worktrees[i]->is_current && ignore_current_worktree) diff --git a/builtin/branch.c b/builtin/branch.c index dede60d27b..031a4a9d05 100644 --- a/builtin/branch.c +++ b/builtin/branch.c @@ -259,7 +259,8 @@ static int delete_branches(int argc, const char **argv, int force, int kinds, char *target = NULL; int flags = 0; - copy_branchname(&bname, argv[i], allowed_interpret); + copy_branchname(the_repository, &bname, + argv[i], allowed_interpret); free(name); name = mkpathdup(fmt, bname.buf); @@ -579,9 +580,9 @@ static void copy_or_rename_branch(const char *oldname, const char *newname, int const char *interpreted_oldname = NULL; const char *interpreted_newname = NULL; int recovery = 0, oldref_usage = 0; - struct worktree **worktrees = get_worktrees(); + struct worktree **worktrees = get_worktrees(the_repository); - if (check_branch_ref(&oldref, oldname)) { + if (check_branch_ref(the_repository, &oldref, oldname)) { /* * Bad name --- this could be an attempt to rename a * ref that we used to allow to be created by accident. @@ -921,7 +922,8 @@ int cmd_branch(int argc, die(_("cannot give description to detached HEAD")); branch_name = head; } else if (argc == 1) { - copy_branchname(&buf, argv[0], INTERPRET_BRANCH_LOCAL); + copy_branchname(the_repository, &buf, argv[0], + INTERPRET_BRANCH_LOCAL); branch_name = buf.buf; } else { die(_("cannot edit description of more than one branch")); @@ -964,7 +966,8 @@ int cmd_branch(int argc, if (!argc) branch = branch_get(NULL); else if (argc == 1) { - copy_branchname(&buf, argv[0], INTERPRET_BRANCH_LOCAL); + copy_branchname(the_repository, &buf, argv[0], + INTERPRET_BRANCH_LOCAL); branch = branch_get(buf.buf); } else die(_("too many arguments to set new upstream")); @@ -1003,7 +1006,8 @@ int cmd_branch(int argc, if (!argc) branch = branch_get(NULL); else if (argc == 1) { - copy_branchname(&buf, argv[0], INTERPRET_BRANCH_LOCAL); + copy_branchname(the_repository, &buf, argv[0], + INTERPRET_BRANCH_LOCAL); branch = branch_get(buf.buf); } else die(_("too many arguments to unset upstream")); diff --git a/builtin/check-ref-format.c b/builtin/check-ref-format.c index e42b0444ea..fd1c9c0e0c 100644 --- a/builtin/check-ref-format.c +++ b/builtin/check-ref-format.c @@ -45,7 +45,7 @@ static int check_ref_format_branch(const char *arg) int nongit; setup_git_directory_gently(the_repository, &nongit); - if (check_branch_ref(&sb, arg) || + if (check_branch_ref(the_repository, &sb, arg) || !skip_prefix(sb.buf, "refs/heads/", &name)) die("'%s' is not a valid branch name", arg); printf("%s\n", name); diff --git a/builtin/checkout.c b/builtin/checkout.c index aee84ca897..55e3a89a85 100644 --- a/builtin/checkout.c +++ b/builtin/checkout.c @@ -805,7 +805,7 @@ static void setup_branch_path(struct branch_info *branch) &branch->oid, &branch->refname, 0)) repo_get_oid_committish(the_repository, branch->name, &branch->oid); - copy_branchname(&buf, branch->name, INTERPRET_BRANCH_LOCAL); + copy_branchname(the_repository, &buf, branch->name, INTERPRET_BRANCH_LOCAL); if (strcmp(buf.buf, branch->name)) { free(branch->name); branch->name = xstrdup(buf.buf); diff --git a/builtin/config.c b/builtin/config.c index 8d8ec0beea..0882899c3f 100644 --- a/builtin/config.c +++ b/builtin/config.c @@ -974,7 +974,7 @@ static void location_options_init(struct config_location_options *opts, opts->source.file = opts->file_to_free = repo_git_path(the_repository, "config"); opts->source.scope = CONFIG_SCOPE_LOCAL; } else if (opts->use_worktree_config) { - struct worktree **worktrees = get_worktrees(); + struct worktree **worktrees = get_worktrees(the_repository); if (the_repository->repository_format_worktree_config) opts->source.file = opts->file_to_free = repo_git_path(the_repository, "config.worktree"); diff --git a/builtin/fsck.c b/builtin/fsck.c index 76b723f36d..a6c054e45b 100644 --- a/builtin/fsck.c +++ b/builtin/fsck.c @@ -632,7 +632,7 @@ static void snapshot_refs(struct repository *repo, refs_for_each_ref_ext(get_main_ref_store(repo), snapshot_ref, &data, &opts); - worktrees = get_worktrees(); + worktrees = get_worktrees(repo); for (p = worktrees; *p; p++) { struct worktree *wt = *p; struct strbuf refname = STRBUF_INIT; @@ -685,7 +685,7 @@ static void process_refs(struct repository *repo, struct snapshot *snap) } if (include_reflogs) { - worktrees = get_worktrees(); + worktrees = get_worktrees(repo); for (p = worktrees; *p; p++) { struct worktree *wt = *p; @@ -1121,7 +1121,7 @@ int cmd_fsck(int argc, verify_index_checksum = 1; verify_ce_order = 1; - worktrees = get_worktrees(); + worktrees = get_worktrees(repo); for (p = worktrees; *p; p++) { struct worktree *wt = *p; struct index_state istate = diff --git a/builtin/gc.c b/builtin/gc.c index d32af422af..46999a99ab 100644 --- a/builtin/gc.c +++ b/builtin/gc.c @@ -412,7 +412,7 @@ static int worktree_prune_condition(struct gc_config *cfg) while (limit && (d = readdir_skip_dot_and_dotdot(dir))) { char *wtpath; strbuf_reset(&buf); - if (should_prune_worktree(d->d_name, &buf, &wtpath, expiry_date)) + if (should_prune_worktree(the_repository, d->d_name, &buf, &wtpath, expiry_date)) limit--; free(wtpath); } diff --git a/builtin/merge.c b/builtin/merge.c index 5b46a596f0..58d1b7bb07 100644 --- a/builtin/merge.c +++ b/builtin/merge.c @@ -553,7 +553,7 @@ static void merge_name(const char *remote, struct strbuf *msg) char *found_ref = NULL; int len, early; - copy_branchname(&bname, remote, 0); + copy_branchname(the_repository, &bname, remote, 0); remote = bname.buf; oidclr(&branch_head, the_repository->hash_algo); diff --git a/builtin/notes.c b/builtin/notes.c index 962df867c8..9f1f0ec840 100644 --- a/builtin/notes.c +++ b/builtin/notes.c @@ -989,7 +989,7 @@ static int merge(int argc, const char **argv, const char *prefix, "NOTES_MERGE_PARTIAL", &result_oid, NULL, 0, UPDATE_REFS_DIE_ON_ERR); /* Store ref-to-be-updated into .git/NOTES_MERGE_REF */ - worktrees = get_worktrees(); + worktrees = get_worktrees(the_repository); wt = find_shared_symref(worktrees, "NOTES_MERGE_REF", notes_ref); if (wt) diff --git a/builtin/receive-pack.c b/builtin/receive-pack.c index 7190d7f430..86933d8d7e 100644 --- a/builtin/receive-pack.c +++ b/builtin/receive-pack.c @@ -1500,7 +1500,7 @@ static const char *update(struct command *cmd, struct shallow_info *si) struct object_id *old_oid = &cmd->old_oid; struct object_id *new_oid = &cmd->new_oid; int do_update_worktree = 0; - struct worktree **worktrees = get_worktrees(); + struct worktree **worktrees = get_worktrees(the_repository); const struct worktree *worktree = find_shared_symref(worktrees, "HEAD", name); diff --git a/builtin/reflog.c b/builtin/reflog.c index dcbfe89339..1211c58fa4 100644 --- a/builtin/reflog.c +++ b/builtin/reflog.c @@ -250,7 +250,7 @@ static int cmd_reflog_expire(int argc, const char **argv, const char *prefix, struct string_list_item *item; struct worktree **worktrees, **p; - worktrees = get_worktrees(); + worktrees = get_worktrees(the_repository); for (p = worktrees; *p; p++) { if (single_worktree && !(*p)->is_current) continue; @@ -374,7 +374,7 @@ static int cmd_reflog_drop(int argc, const char **argv, const char *prefix, struct string_list_item *item; struct worktree **worktrees, **p; - worktrees = get_worktrees(); + worktrees = get_worktrees(the_repository); for (p = worktrees; *p; p++) { if (single_worktree && !(*p)->is_current) continue; diff --git a/builtin/refs.c b/builtin/refs.c index a9ca2058ee..5cd21c25fe 100644 --- a/builtin/refs.c +++ b/builtin/refs.c @@ -113,7 +113,7 @@ static int cmd_refs_verify(int argc, const char **argv, const char *prefix, repo_config(repo, git_fsck_config, &fsck_refs_options); prepare_repo_settings(repo); - worktrees = get_worktrees_without_reading_head(); + worktrees = get_worktrees_without_reading_head(repo); for (size_t i = 0; worktrees[i]; i++) ret |= refs_fsck(get_worktree_ref_store(worktrees[i]), &fsck_refs_options, worktrees[i]); diff --git a/builtin/worktree.c b/builtin/worktree.c index 4bc7b4f6e7..f0442b202d 100644 --- a/builtin/worktree.c +++ b/builtin/worktree.c @@ -226,7 +226,7 @@ static void prune_worktrees(void) while ((d = readdir_skip_dot_and_dotdot(dir)) != NULL) { char *path; strbuf_reset(&reason); - if (should_prune_worktree(d->d_name, &reason, &path, expire)) + if (should_prune_worktree(the_repository, d->d_name, &reason, &path, expire)) prune_worktree(d->d_name, reason.buf); else if (path) string_list_append_nodup(&kept, path)->util = xstrdup(d->d_name); @@ -475,13 +475,13 @@ static int add_worktree(const char *path, const char *refname, struct ref_store *wt_refs; struct repo_config_values *cfg = repo_config_values(the_repository); - worktrees = get_worktrees(); + worktrees = get_worktrees(the_repository); check_candidate_path(path, opts->force, worktrees, "add"); free_worktrees(worktrees); worktrees = NULL; /* is 'refname' a branch or commit? */ - if (!opts->detach && !check_branch_ref(&symref, refname) && + if (!opts->detach && !check_branch_ref(the_repository, &symref, refname) && refs_ref_exists(get_main_ref_store(the_repository), symref.buf)) { is_branch = 1; if (!opts->force) @@ -539,7 +539,8 @@ static int add_worktree(const char *path, const char *refname, strbuf_reset(&sb); strbuf_addf(&sb, "%s/gitdir", sb_repo.buf); - write_worktree_linking_files(sb_git.buf, sb.buf, opts->relative_paths); + write_worktree_linking_files(the_repository, sb_git.buf, + sb.buf, opts->relative_paths); strbuf_reset(&sb); strbuf_addf(&sb, "%s/commondir", sb_repo.buf); write_file(sb.buf, "../.."); @@ -547,7 +548,7 @@ static int add_worktree(const char *path, const char *refname, /* * Set up the ref store of the worktree and create the HEAD reference. */ - wt = get_linked_worktree(name, 1); + wt = get_linked_worktree(the_repository, name, 1); if (!wt) { ret = error(_("could not find created worktree '%s'"), name); goto done; @@ -649,7 +650,7 @@ static void print_preparing_worktree_line(int detach, fprintf_ln(stderr, _("Preparing worktree (new branch '%s')"), new_branch); } else { struct strbuf s = STRBUF_INIT; - if (!detach && !check_branch_ref(&s, branch) && + if (!detach && !check_branch_ref(the_repository, &s, branch) && refs_ref_exists(get_main_ref_store(the_repository), s.buf)) fprintf_ln(stderr, _("Preparing worktree (checking out '%s')"), branch); @@ -771,7 +772,7 @@ static char *dwim_branch(const char *path, char **new_branch) char *branchname = xstrndup(s, n); struct strbuf ref = STRBUF_INIT; - branch_exists = !check_branch_ref(&ref, branchname) && + branch_exists = !check_branch_ref(the_repository, &ref, branchname) && refs_ref_exists(get_main_ref_store(the_repository), ref.buf); strbuf_release(&ref); @@ -868,7 +869,7 @@ static int add(int ac, const char **av, const char *prefix, new_branch = new_branch_force; if (!opts.force && - !check_branch_ref(&symref, new_branch) && + !check_branch_ref(the_repository, &symref, new_branch) && refs_ref_exists(get_main_ref_store(the_repository), symref.buf)) die_if_checked_out(symref.buf, 0); strbuf_release(&symref); @@ -1106,7 +1107,7 @@ static int list(int ac, const char **av, const char *prefix, else if (!line_terminator && !porcelain) die(_("the option '%s' requires '%s'"), "-z", "--porcelain"); else { - struct worktree **worktrees = get_worktrees(); + struct worktree **worktrees = get_worktrees(the_repository); int path_maxwidth = 0, abbrev = DEFAULT_ABBREV, i; struct worktree_display *display = NULL; @@ -1149,7 +1150,7 @@ static int lock_worktree(int ac, const char **av, const char *prefix, if (ac != 1) usage_with_options(git_worktree_lock_usage, options); - worktrees = get_worktrees(); + worktrees = get_worktrees(the_repository); wt = find_worktree(worktrees, prefix, av[0]); if (!wt) die(_("'%s' is not a working tree"), av[0]); @@ -1186,7 +1187,7 @@ static int unlock_worktree(int ac, const char **av, const char *prefix, if (ac != 1) usage_with_options(git_worktree_unlock_usage, options); - worktrees = get_worktrees(); + worktrees = get_worktrees(the_repository); wt = find_worktree(worktrees, prefix, av[0]); if (!wt) die(_("'%s' is not a working tree"), av[0]); @@ -1272,7 +1273,7 @@ static int move_worktree(int ac, const char **av, const char *prefix, strbuf_addstr(&dst, path); free(path); - worktrees = get_worktrees(); + worktrees = get_worktrees(the_repository); wt = find_worktree(worktrees, prefix, av[0]); if (!wt) die(_("'%s' is not a working tree"), av[0]); @@ -1397,7 +1398,7 @@ static int remove_worktree(int ac, const char **av, const char *prefix, if (ac != 1) usage_with_options(git_worktree_remove_usage, options); - worktrees = get_worktrees(); + worktrees = get_worktrees(the_repository); wt = find_worktree(worktrees, prefix, av[0]); if (!wt) die(_("'%s' is not a working tree"), av[0]); @@ -1459,8 +1460,9 @@ static int repair(int ac, const char **av, const char *prefix, ac = parse_options(ac, av, prefix, options, git_worktree_repair_usage, 0); p = ac > 0 ? av : self; for (; *p; p++) - repair_worktree_at_path(*p, report_repair, &rc, use_relative_paths); - repair_worktrees(report_repair, &rc, use_relative_paths); + repair_worktree_at_path(the_repository, *p, report_repair, + &rc, use_relative_paths); + repair_worktrees(the_repository, report_repair, &rc, use_relative_paths); return rc; } diff --git a/reachable.c b/reachable.c index caadacc02a..3079d2c5f4 100644 --- a/reachable.c +++ b/reachable.c @@ -62,7 +62,7 @@ static void add_rebase_files(struct rev_info *revs) "rebase-merge/autostash", "rebase-merge/orig-head", }; - struct worktree **worktrees = get_worktrees(); + struct worktree **worktrees = get_worktrees(the_repository); for (struct worktree **wt = worktrees; *wt; wt++) { char *wt_gitdir = get_worktree_git_dir(*wt); @@ -322,7 +322,7 @@ void mark_reachable_objects(struct rev_info *revs, int mark_reflog, /* detached HEAD is not included in the list above */ refs_head_ref(get_main_ref_store(the_repository), add_one_ref, revs); - other_head_refs(add_one_ref, revs); + other_head_refs(the_repository, add_one_ref, revs); /* rebase autostash and orig-head */ add_rebase_files(revs); diff --git a/ref-filter.c b/ref-filter.c index 284796c49b..29aca08ce7 100644 --- a/ref-filter.c +++ b/ref-filter.c @@ -2402,7 +2402,7 @@ static void lazy_init_worktree_map(void) if (ref_to_worktree_map.worktrees) return; - ref_to_worktree_map.worktrees = get_worktrees(); + ref_to_worktree_map.worktrees = get_worktrees(the_repository); hashmap_init(&(ref_to_worktree_map.map), ref_to_worktree_map_cmpfnc, NULL, 0); populate_worktree_map(&(ref_to_worktree_map.map), ref_to_worktree_map.worktrees); } diff --git a/refs.c b/refs.c index 1d24637891..92d5df5b71 100644 --- a/refs.c +++ b/refs.c @@ -2,8 +2,6 @@ * The backend-independent part of the reference module. */ -#define USE_THE_REPOSITORY_VARIABLE - #include "git-compat-util.h" #include "abspath.h" #include "advice.h" @@ -744,14 +742,15 @@ static char *substitute_branch_name(struct repository *r, return NULL; } -void copy_branchname(struct strbuf *sb, const char *name, +void copy_branchname(struct repository *repo, + struct strbuf *sb, const char *name, enum interpret_branch_kind allowed) { int len = strlen(name); struct interpret_branch_name_options options = { .allowed = allowed }; - int used = repo_interpret_branch_name(the_repository, name, len, sb, + int used = repo_interpret_branch_name(repo, name, len, sb, &options); if (used < 0) @@ -759,10 +758,10 @@ void copy_branchname(struct strbuf *sb, const char *name, strbuf_add(sb, name + used, len - used); } -int check_branch_ref(struct strbuf *sb, const char *name) +int check_branch_ref(struct repository *repo, struct strbuf *sb, const char *name) { if (startup_info->have_repository) - copy_branchname(sb, name, INTERPRET_BRANCH_LOCAL); + copy_branchname(repo, sb, name, INTERPRET_BRANCH_LOCAL); else strbuf_addstr(sb, name); @@ -3326,9 +3325,9 @@ done: return ret; } -static int has_worktrees(void) +static int has_worktrees(struct repository *repo) { - struct worktree **worktrees = get_worktrees(); + struct worktree **worktrees = get_worktrees(repo); int ret = 0; size_t i; @@ -3373,12 +3372,8 @@ int repo_migrate_ref_storage_format(struct repository *repo, * Worktrees complicate the migration because every worktree has a * separate ref storage. While it should be feasible to implement, this * is pushed out to a future iteration. - * - * TODO: we should really be passing the caller-provided repository to - * `has_worktrees()`, but our worktree subsystem doesn't yet support - * that. */ - if (has_worktrees()) { + if (has_worktrees(repo)) { strbuf_addstr(errbuf, "migrating repositories with worktrees is not supported yet"); ret = -1; goto done; @@ -3503,7 +3498,7 @@ int repo_migrate_ref_storage_format(struct repository *repo, * repository format so that clients will use the new ref store. * We also need to swap out the repository's main ref store. */ - initialize_repository_version(the_repository, hash_algo_by_ptr(repo->hash_algo), format, 1); + initialize_repository_version(repo, hash_algo_by_ptr(repo->hash_algo), format, 1); /* * Unset the old ref store and release it. `get_main_ref_store()` will diff --git a/refs.h b/refs.h index a381022c77..9979446d15 100644 --- a/refs.h +++ b/refs.h @@ -234,7 +234,8 @@ char *repo_default_branch_name(struct repository *r, int quiet); * If "allowed" is non-zero, restrict the set of allowed expansions. See * repo_interpret_branch_name() for details. */ -void copy_branchname(struct strbuf *sb, const char *name, +void copy_branchname(struct repository *repo, + struct strbuf *sb, const char *name, enum interpret_branch_kind allowed); /* @@ -243,7 +244,7 @@ void copy_branchname(struct strbuf *sb, const char *name, * * The return value is "0" if the result is valid, and "-1" otherwise. */ -int check_branch_ref(struct strbuf *sb, const char *name); +int check_branch_ref(struct repository *repo, struct strbuf *sb, const char *name); /* * Similar for a tag name in refs/tags/. diff --git a/refs/files-backend.c b/refs/files-backend.c index e1d963a6f3..3ba1b4eac4 100644 --- a/refs/files-backend.c +++ b/refs/files-backend.c @@ -1,4 +1,3 @@ -#define USE_THE_REPOSITORY_VARIABLE #define DISABLE_SIGN_COMPARE_WARNINGS #include "../git-compat-util.h" @@ -29,6 +28,9 @@ #include "../revision.h" #include +/* So that we can drop `USE_THE_REPOSITORY_VARIABLE`. */ +extern int ignore_case; + /* * This backend uses the following flags in `ref_update::flags` for * internal bookkeeping purposes. Their numerical values must not @@ -788,7 +790,7 @@ static enum ref_transaction_error lock_raw_ref(struct files_ref_store *refs, files_ref_path(refs, &ref_file, refname); retry: - switch (safe_create_leading_directories(the_repository, ref_file.buf)) { + switch (safe_create_leading_directories(refs->base.repo, ref_file.buf)) { case SCLD_OK: break; /* success */ case SCLD_EXISTS: @@ -857,7 +859,7 @@ retry: } else { unable_to_lock_message(ref_file.buf, myerr, err); if (myerr == EEXIST) { - if (repo_ignore_case(the_repository) && + if (repo_ignore_case(refs->base.repo) && transaction_has_case_conflicting_update(transaction, update)) { /* * In case-insensitive filesystems, ensure that conflicts within a @@ -971,7 +973,7 @@ retry: * conflicts between 'foo' and 'Foo/bar'. So let's lowercase * the refname. */ - if (repo_ignore_case(the_repository)) { + if (repo_ignore_case(refs->base.repo)) { struct strbuf lower = STRBUF_INIT; strbuf_addstr(&lower, refname); @@ -1164,7 +1166,8 @@ typedef int create_file_fn(const char *path, void *cb); * recent call of fn. fn is always called at least once, and will be * called more than once if it returns ENOENT or EISDIR. */ -static int raceproof_create_file(const char *path, create_file_fn fn, void *cb) +static int raceproof_create_file(struct files_ref_store *refs, + const char *path, create_file_fn fn, void *cb) { /* * The number of times we will try to remove empty directories @@ -1220,7 +1223,7 @@ retry_fn: strbuf_addstr(&path_copy, path); do { - scld_result = safe_create_leading_directories(the_repository, path_copy.buf); + scld_result = safe_create_leading_directories(refs->base.repo, path_copy.buf); if (scld_result == SCLD_OK) goto retry_fn; } while (scld_result == SCLD_VANISHED && create_directories_remaining-- > 0); @@ -1289,7 +1292,7 @@ static struct ref_lock *lock_ref_oid_basic(struct files_ref_store *refs, cb_data.lk = &lock->lk; cb_data.repo = refs->base.repo; - if (raceproof_create_file(ref_file.buf, create_reflock, &cb_data)) { + if (raceproof_create_file(refs, ref_file.buf, create_reflock, &cb_data)) { unable_to_lock_message(ref_file.buf, errno, err); goto error_return; } @@ -1383,7 +1386,7 @@ static void prune_ref(struct files_ref_store *refs, struct ref_to_prune *r) ref_transaction_add_update( transaction, r->name, REF_NO_DEREF | REF_HAVE_NEW | REF_HAVE_OLD | REF_IS_PRUNING, - null_oid(the_hash_algo), &r->oid, NULL, NULL, NULL, + null_oid(refs->base.repo->hash_algo), &r->oid, NULL, NULL, NULL, NULL, NULL); if (ref_transaction_commit(transaction, &err)) goto cleanup; @@ -1629,7 +1632,7 @@ static int rename_tmp_log(struct files_ref_store *refs, const char *newrefname) files_reflog_path(refs, &path, newrefname); files_reflog_path(refs, &tmp, TMP_RENAMED_LOG); cb.tmp_renamed_log = tmp.buf; - ret = raceproof_create_file(path.buf, rename_tmp_log_callback, &cb); + ret = raceproof_create_file(refs, path.buf, rename_tmp_log_callback, &cb); if (ret) { if (errno == EISDIR) error("directory not empty: %s", path.buf); @@ -1916,13 +1919,13 @@ static int log_ref_setup(struct files_ref_store *refs, char *logfile; if (log_refs_cfg == LOG_REFS_UNSET) - log_refs_cfg = is_bare_repository(the_repository) ? LOG_REFS_NONE : LOG_REFS_NORMAL; + log_refs_cfg = is_bare_repository(refs->base.repo) ? LOG_REFS_NONE : LOG_REFS_NORMAL; files_reflog_path(refs, &logfile_sb, refname); logfile = strbuf_detach(&logfile_sb, NULL); if (force_create || should_autocreate_reflog(log_refs_cfg, refname)) { - if (raceproof_create_file(logfile, open_or_create_logfile, logfd)) { + if (raceproof_create_file(refs, logfile, open_or_create_logfile, logfd)) { if (errno == ENOENT) strbuf_addf(err, "unable to create directory for '%s': " "%s", logfile, strerror(errno)); @@ -1955,7 +1958,7 @@ static int log_ref_setup(struct files_ref_store *refs, } if (*logfd >= 0) - adjust_shared_perm(the_repository, logfile); + adjust_shared_perm(refs->base.repo, logfile); free(logfile); return 0; @@ -3672,8 +3675,8 @@ static int files_ref_store_create_on_disk(struct ref_store *ref_store, * they do not understand the reference format extension. */ strbuf_addf(&sb, "%s/refs", ref_store->gitdir); - safe_create_dir(the_repository, sb.buf, 1); - adjust_shared_perm(the_repository, sb.buf); + safe_create_dir(refs->base.repo, sb.buf, 1); + adjust_shared_perm(refs->base.repo, sb.buf); /* * There is no need to create directories for common refs when creating @@ -3685,11 +3688,11 @@ static int files_ref_store_create_on_disk(struct ref_store *ref_store, */ strbuf_reset(&sb); files_ref_path(refs, &sb, "refs/heads"); - safe_create_dir(the_repository, sb.buf, 1); + safe_create_dir(refs->base.repo, sb.buf, 1); strbuf_reset(&sb); files_ref_path(refs, &sb, "refs/tags"); - safe_create_dir(the_repository, sb.buf, 1); + safe_create_dir(refs->base.repo, sb.buf, 1); } strbuf_release(&sb); diff --git a/refs/packed-backend.c b/refs/packed-backend.c index 499cb55dfa..c5d96793fa 100644 --- a/refs/packed-backend.c +++ b/refs/packed-backend.c @@ -1,4 +1,3 @@ -#define USE_THE_REPOSITORY_VARIABLE #define DISABLE_SIGN_COMPARE_WARNINGS #include "../git-compat-util.h" @@ -162,6 +161,13 @@ struct packed_ref_store { * `packed_ref_store`) must not be freed. */ struct tempfile *tempfile; + + /* + * Timeout when taking the "packed-refs.lock" file. configurable via + * "core.packedRefsTimeout". + */ + bool timeout_configured; + int timeout_value; }; /* @@ -1233,12 +1239,12 @@ int packed_refs_lock(struct ref_store *ref_store, int flags, struct strbuf *err) struct packed_ref_store *refs = packed_downcast(ref_store, REF_STORE_WRITE | REF_STORE_MAIN, "packed_refs_lock"); - static int timeout_configured = 0; - static int timeout_value = 1000; - if (!timeout_configured) { - repo_config_get_int(the_repository, "core.packedrefstimeout", &timeout_value); - timeout_configured = 1; + if (!refs->timeout_configured) { + if (repo_config_get_int(ref_store->repo, "core.packedrefstimeout", + &refs->timeout_value)) + refs->timeout_value = 1000; + refs->timeout_configured = true; } /* @@ -1249,7 +1255,7 @@ int packed_refs_lock(struct ref_store *ref_store, int flags, struct strbuf *err) if (hold_lock_file_for_update_timeout( &refs->lock, refs->path, - flags, timeout_value) < 0) { + flags, refs->timeout_value) < 0) { unable_to_lock_message(refs->path, errno, err); return -1; } diff --git a/revision.c b/revision.c index b77f5e2fa7..8eb7cb9bbc 100644 --- a/revision.c +++ b/revision.c @@ -1711,7 +1711,7 @@ static void add_other_reflogs_to_pending(struct all_refs_cb *cb) { struct worktree **worktrees, **p; - worktrees = get_worktrees(); + worktrees = get_worktrees(the_repository); for (p = worktrees; *p; p++) { struct worktree *wt = *p; @@ -1837,7 +1837,7 @@ void add_index_objects_to_pending(struct rev_info *revs, unsigned int flags) if (revs->single_worktree) return; - worktrees = get_worktrees(); + worktrees = get_worktrees(the_repository); for (p = worktrees; *p; p++) { struct worktree *wt = *p; struct index_state istate = INDEX_STATE_INIT(revs->repo); @@ -2824,7 +2824,7 @@ static int handle_revision_pseudo_opt(struct rev_info *revs, struct all_refs_cb cb; init_all_refs_cb(&cb, revs, *flags); - other_head_refs(handle_one_ref, &cb); + other_head_refs(the_repository, handle_one_ref, &cb); } clear_ref_exclusions(&revs->ref_excludes); } else if (!strcmp(arg, "--branches")) { diff --git a/setup.c b/setup.c index d31808130b..e4cb5d1925 100644 --- a/setup.c +++ b/setup.c @@ -2674,7 +2674,8 @@ static void create_object_directory(struct repository *repo) strbuf_release(&path); } -static void separate_git_dir(const char *git_dir, const char *git_link) +static void separate_git_dir(struct repository *repo, + const char *git_dir, const char *git_link) { struct stat st; @@ -2690,7 +2691,7 @@ static void separate_git_dir(const char *git_dir, const char *git_link) if (rename(src, git_dir)) die_errno(_("unable to move %s to %s"), src, git_dir); - repair_worktrees_after_gitdir_move(src); + repair_worktrees_after_gitdir_move(repo, src); } write_file(git_link, "gitdir: %s", git_dir); @@ -2849,7 +2850,7 @@ int init_db(struct repository *repo, apply_and_export_relative_gitdir(repo, real_git_dir, 1); git_dir = repo_get_git_dir(repo); - separate_git_dir(git_dir, original_git_dir); + separate_git_dir(repo, git_dir, original_git_dir); } else { apply_and_export_relative_gitdir(repo, git_dir, 1); git_dir = repo_get_git_dir(repo); diff --git a/submodule.c b/submodule.c index b30bb9679e..5c92575888 100644 --- a/submodule.c +++ b/submodule.c @@ -2494,7 +2494,7 @@ static void relocate_single_git_dir_into_superproject(const char *path, if (validate_submodule_path(path) < 0) exit(128); - if (submodule_uses_worktrees(path)) + if (submodule_uses_worktrees(the_repository, path)) die(_("relocate_gitdir for submodule '%s' with " "more than one worktree not supported"), path); diff --git a/t/helper/test-ref-store.c b/t/helper/test-ref-store.c index 3866d0aca4..5a9a3053d9 100644 --- a/t/helper/test-ref-store.c +++ b/t/helper/test-ref-store.c @@ -84,7 +84,7 @@ static const char **get_store(const char **argv, struct ref_store **refs) *refs = repo_get_submodule_ref_store(the_repository, gitdir); } else if (skip_prefix(argv[0], "worktree:", &gitdir)) { - struct worktree **p, **worktrees = get_worktrees(); + struct worktree **p, **worktrees = get_worktrees(the_repository); for (p = worktrees; *p; p++) { struct worktree *wt = *p; diff --git a/worktree.c b/worktree.c index 30125827fd..cbf95328a3 100644 --- a/worktree.c +++ b/worktree.c @@ -1,4 +1,3 @@ -#define USE_THE_REPOSITORY_VARIABLE #define DISABLE_SIGN_COMPARE_WARNINGS #include "git-compat-util.h" @@ -111,34 +110,36 @@ static int is_main_worktree_bare(struct repository *repo) /** * get the main worktree */ -static struct worktree *get_main_worktree(int skip_reading_head) +static struct worktree *get_main_worktree(struct repository *repo, + int skip_reading_head) { struct worktree *worktree = NULL; struct strbuf worktree_path = STRBUF_INIT; - strbuf_add_real_path(&worktree_path, repo_get_common_dir(the_repository)); + strbuf_add_real_path(&worktree_path, repo_get_common_dir(repo)); strbuf_strip_suffix(&worktree_path, "/.git"); CALLOC_ARRAY(worktree, 1); - worktree->repo = the_repository; + worktree->repo = repo; worktree->path = strbuf_detach(&worktree_path, NULL); worktree->is_current = is_current_worktree(worktree); - worktree->is_bare = (the_repository->bare_cfg == 1) || - is_bare_repository(the_repository) || + worktree->is_bare = (repo->bare_cfg == 1) || + is_bare_repository(repo) || /* * When in a secondary worktree we have to also verify if the main * worktree is bare in $commondir/config.worktree. * This check is unnecessary if we're currently in the main worktree, * as prior checks already consulted all configs of the current worktree. */ - (!worktree->is_current && is_main_worktree_bare(the_repository)); + (!worktree->is_current && is_main_worktree_bare(repo)); if (!skip_reading_head) add_head_info(worktree); return worktree; } -struct worktree *get_linked_worktree(const char *id, +struct worktree *get_linked_worktree(struct repository *repo, + const char *id, int skip_reading_head) { struct worktree *worktree = NULL; @@ -148,7 +149,7 @@ struct worktree *get_linked_worktree(const char *id, if (!id) die("Missing linked worktree name"); - repo_common_path_append(the_repository, &path, "worktrees/%s/gitdir", id); + repo_common_path_append(repo, &path, "worktrees/%s/gitdir", id); if (strbuf_read_file(&worktree_path, path.buf, 0) <= 0) /* invalid gitdir file */ goto done; @@ -162,7 +163,7 @@ struct worktree *get_linked_worktree(const char *id, } CALLOC_ARRAY(worktree, 1); - worktree->repo = the_repository; + worktree->repo = repo; worktree->path = strbuf_detach(&worktree_path, NULL); worktree->id = xstrdup(id); worktree->is_current = is_current_worktree(worktree); @@ -182,7 +183,8 @@ done: * retrieving worktree metadata that could be used when the worktree is known * to not be in a healthy state, e.g. when creating or repairing it. */ -static struct worktree **get_worktrees_internal(int skip_reading_head) +static struct worktree **get_worktrees_internal(struct repository *repo, + int skip_reading_head) { struct worktree **list = NULL; struct strbuf path = STRBUF_INIT; @@ -192,16 +194,16 @@ static struct worktree **get_worktrees_internal(int skip_reading_head) ALLOC_ARRAY(list, alloc); - list[counter++] = get_main_worktree(skip_reading_head); + list[counter++] = get_main_worktree(repo, skip_reading_head); - strbuf_addf(&path, "%s/worktrees", repo_get_common_dir(the_repository)); + strbuf_addf(&path, "%s/worktrees", repo_get_common_dir(repo)); dir = opendir(path.buf); strbuf_release(&path); if (dir) { while ((d = readdir_skip_dot_and_dotdot(dir)) != NULL) { struct worktree *linked = NULL; - if ((linked = get_linked_worktree(d->d_name, skip_reading_head))) { + if ((linked = get_linked_worktree(repo, d->d_name, skip_reading_head))) { ALLOC_GROW(list, counter + 1, alloc); list[counter++] = linked; } @@ -214,14 +216,14 @@ static struct worktree **get_worktrees_internal(int skip_reading_head) return list; } -struct worktree **get_worktrees(void) +struct worktree **get_worktrees(struct repository *repo) { - return get_worktrees_internal(0); + return get_worktrees_internal(repo, 0); } -struct worktree **get_worktrees_without_reading_head(void) +struct worktree **get_worktrees_without_reading_head(struct repository *repo) { - return get_worktrees_internal(1); + return get_worktrees_internal(repo, 1); } char *get_worktree_git_dir(const struct worktree *wt) @@ -334,7 +336,7 @@ const char *worktree_prune_reason(struct worktree *wt, timestamp_t expire) if (wt->prune_reason_valid) return wt->prune_reason; - if (should_prune_worktree(wt->id, &reason, &path, expire)) + if (should_prune_worktree(wt->repo, wt->id, &reason, &path, expire)) wt->prune_reason = strbuf_detach(&reason, NULL); wt->prune_reason_valid = 1; @@ -392,7 +394,7 @@ int validate_worktree(const struct worktree *wt, struct strbuf *errmsg, if (!is_absolute_path(wt->path)) { strbuf_addf_gently(errmsg, _("'%s' file does not contain absolute path to the working tree location"), - repo_common_path_replace(the_repository, &buf, "worktrees/%s/gitdir", wt->id)); + repo_common_path_replace(wt->repo, &buf, "worktrees/%s/gitdir", wt->id)); goto done; } @@ -414,12 +416,12 @@ int validate_worktree(const struct worktree *wt, struct strbuf *errmsg, goto done; } - strbuf_realpath(&realpath, repo_common_path_replace(the_repository, &buf, "worktrees/%s", wt->id), 1); + strbuf_realpath(&realpath, repo_common_path_replace(wt->repo, &buf, "worktrees/%s", wt->id), 1); ret = fspathcmp(path, realpath.buf); if (ret) strbuf_addf_gently(errmsg, _("'%s' does not point back to '%s'"), - wt->path, repo_common_path_replace(the_repository, &buf, + wt->path, repo_common_path_replace(wt->repo, &buf, "worktrees/%s", wt->id)); done: free(path); @@ -440,12 +442,13 @@ void update_worktree_location(struct worktree *wt, const char *path_, if (is_main_worktree(wt)) BUG("can't relocate main worktree"); - wt_gitdir = repo_common_path(the_repository, "worktrees/%s/gitdir", wt->id); + wt_gitdir = repo_common_path(wt->repo, "worktrees/%s/gitdir", wt->id); strbuf_realpath(&gitdir, wt_gitdir, 1); strbuf_realpath(&path, path_, 1); strbuf_addf(&dotgit, "%s/.git", path.buf); if (fspathcmp(wt->path, path.buf)) { - write_worktree_linking_files(dotgit.buf, gitdir.buf, use_relative_paths); + write_worktree_linking_files(wt->repo, dotgit.buf, + gitdir.buf, use_relative_paths); free(wt->path); wt->path = strbuf_detach(&path, NULL); @@ -533,7 +536,8 @@ const struct worktree *find_shared_symref(struct worktree **worktrees, return NULL; } -int submodule_uses_worktrees(const char *path) +int submodule_uses_worktrees(struct repository *repo, + const char *path) { char *submodule_gitdir; struct strbuf sb = STRBUF_INIT, err = STRBUF_INIT; @@ -542,7 +546,7 @@ int submodule_uses_worktrees(const char *path) int ret = 0; struct repository_format format = REPOSITORY_FORMAT_INIT; - submodule_gitdir = repo_submodule_path(the_repository, + submodule_gitdir = repo_submodule_path(repo, path, "%s", ""); if (!submodule_gitdir) return 0; @@ -595,13 +599,14 @@ void strbuf_worktree_ref(const struct worktree *wt, strbuf_addstr(sb, refname); } -int other_head_refs(refs_for_each_cb fn, void *cb_data) +int other_head_refs(struct repository *repo, + refs_for_each_cb fn, void *cb_data) { struct worktree **worktrees, **p; struct strbuf refname = STRBUF_INIT; int ret = 0; - worktrees = get_worktrees(); + worktrees = get_worktrees(repo); for (p = worktrees; *p; p++) { struct worktree *wt = *p; struct object_id oid; @@ -612,7 +617,7 @@ int other_head_refs(refs_for_each_cb fn, void *cb_data) strbuf_reset(&refname); strbuf_worktree_ref(wt, &refname, "HEAD"); - if (refs_resolve_ref_unsafe(get_main_ref_store(the_repository), + if (refs_resolve_ref_unsafe(get_main_ref_store(repo), refname.buf, RESOLVE_REF_READING, &oid, &flag)) { @@ -658,7 +663,7 @@ static void repair_gitfile(struct worktree *wt, goto done; } - path = repo_common_path(the_repository, "worktrees/%s", wt->id); + path = repo_common_path(wt->repo, "worktrees/%s", wt->id); strbuf_realpath(&repo, path, 1); strbuf_addf(&dotgit, "%s/.git", wt->path); strbuf_addf(&gitdir, "%s/gitdir", repo.buf); @@ -685,7 +690,8 @@ static void repair_gitfile(struct worktree *wt, if (repair) { fn(0, wt->path, repair, cb_data); - write_worktree_linking_files(dotgit.buf, gitdir.buf, use_relative_paths); + write_worktree_linking_files(wt->repo, dotgit.buf, + gitdir.buf, use_relative_paths); } done: @@ -705,9 +711,10 @@ static void repair_noop(int iserr UNUSED, /* nothing */ } -void repair_worktrees(worktree_repair_fn fn, void *cb_data, int use_relative_paths) +void repair_worktrees(struct repository *repo, worktree_repair_fn fn, + void *cb_data, int use_relative_paths) { - struct worktree **worktrees = get_worktrees_internal(1); + struct worktree **worktrees = get_worktrees_internal(repo, 1); struct worktree **wt = worktrees + 1; /* +1 skips main worktree */ if (!fn) @@ -727,7 +734,7 @@ void repair_worktree_after_gitdir_move(struct worktree *wt, const char *old_path if (is_main_worktree(wt)) goto done; - path = repo_common_path(the_repository, "worktrees/%s/gitdir", wt->id); + path = repo_common_path(wt->repo, "worktrees/%s/gitdir", wt->id); strbuf_realpath(&gitdir, path, 1); if (strbuf_read_file(&dotgit, gitdir.buf, 0) < 0) @@ -743,16 +750,17 @@ void repair_worktree_after_gitdir_move(struct worktree *wt, const char *old_path if (!file_exists(dotgit.buf)) goto done; - write_worktree_linking_files(dotgit.buf, gitdir.buf, is_relative_path); + write_worktree_linking_files(wt->repo, dotgit.buf, + gitdir.buf, is_relative_path); done: strbuf_release(&gitdir); strbuf_release(&dotgit); free(path); } -void repair_worktrees_after_gitdir_move(const char *old_path) +void repair_worktrees_after_gitdir_move(struct repository *repo, const char *old_path) { - struct worktree **worktrees = get_worktrees_internal(1); + struct worktree **worktrees = get_worktrees_internal(repo, 1); struct worktree **wt = worktrees + 1; /* +1 skips main worktree */ for (; *wt; wt++) @@ -760,7 +768,7 @@ void repair_worktrees_after_gitdir_move(const char *old_path) free_worktrees(worktrees); } -static int is_main_worktree_path(const char *path) +static int is_main_worktree_path(struct repository *repo, const char *path) { struct strbuf target = STRBUF_INIT; struct strbuf maindir = STRBUF_INIT; @@ -768,7 +776,7 @@ static int is_main_worktree_path(const char *path) strbuf_add_real_path(&target, path); strbuf_strip_suffix(&target, "/.git"); - strbuf_add_real_path(&maindir, repo_get_common_dir(the_repository)); + strbuf_add_real_path(&maindir, repo_get_common_dir(repo)); strbuf_strip_suffix(&maindir, "/.git"); cmp = fspathcmp(maindir.buf, target.buf); @@ -786,7 +794,9 @@ static int is_main_worktree_path(const char *path) * * Returns -1 on failure and strbuf.len on success. */ -static ssize_t infer_backlink(const char *gitfile, struct strbuf *inferred) +static ssize_t infer_backlink(struct repository *repo, + const char *gitfile, + struct strbuf *inferred) { struct strbuf actual = STRBUF_INIT; const char *id; @@ -801,7 +811,7 @@ static ssize_t infer_backlink(const char *gitfile, struct strbuf *inferred) id++; /* advance past '/' to point at */ if (!*id) goto error; - repo_common_path_replace(the_repository, inferred, "worktrees/%s", id); + repo_common_path_replace(repo, inferred, "worktrees/%s", id); if (!is_directory(inferred->buf)) goto error; @@ -817,7 +827,8 @@ error: * Repair /worktrees//gitdir if missing, corrupt, or not pointing at * the worktree's path. */ -void repair_worktree_at_path(const char *path, +void repair_worktree_at_path(struct repository *repo, + const char *path, worktree_repair_fn fn, void *cb_data, int use_relative_paths) { @@ -833,7 +844,7 @@ void repair_worktree_at_path(const char *path, if (!fn) fn = repair_noop; - if (is_main_worktree_path(path)) + if (is_main_worktree_path(repo, path)) goto done; strbuf_addf(&dotgit, "%s/.git", path); @@ -842,7 +853,7 @@ void repair_worktree_at_path(const char *path, goto done; } - infer_backlink(dotgit.buf, &inferred_backlink); + infer_backlink(repo, dotgit.buf, &inferred_backlink); strbuf_realpath_forgiving(&inferred_backlink, inferred_backlink.buf, 0); dotgit_contents = xstrdup_or_null(read_gitfile_gently(dotgit.buf, &err)); if (dotgit_contents) { @@ -915,7 +926,8 @@ void repair_worktree_at_path(const char *path, if (repair) { fn(0, gitdir.buf, repair, cb_data); - write_worktree_linking_files(dotgit.buf, gitdir.buf, use_relative_paths); + write_worktree_linking_files(repo, dotgit.buf, + gitdir.buf, use_relative_paths); } done: free(dotgit_contents); @@ -926,12 +938,16 @@ done: strbuf_release(&dotgit); } -int should_prune_worktree(const char *id, struct strbuf *reason, char **wtpath, timestamp_t expire) +int should_prune_worktree(struct repository *repo, + const char *id, + struct strbuf *reason, + char **wtpath, + timestamp_t expire) { struct stat st; struct strbuf dotgit = STRBUF_INIT; struct strbuf gitdir = STRBUF_INIT; - struct strbuf repo = STRBUF_INIT; + struct strbuf repo_path = STRBUF_INIT; struct strbuf file = STRBUF_INIT; char *path = NULL; int rc = 0; @@ -941,17 +957,17 @@ int should_prune_worktree(const char *id, struct strbuf *reason, char **wtpath, *wtpath = NULL; - path = repo_common_path(the_repository, "worktrees/%s", id); - strbuf_realpath(&repo, path, 1); + path = repo_common_path(repo, "worktrees/%s", id); + strbuf_realpath(&repo_path, path, 1); FREE_AND_NULL(path); - strbuf_addf(&gitdir, "%s/gitdir", repo.buf); - if (!is_directory(repo.buf)) { + strbuf_addf(&gitdir, "%s/gitdir", repo_path.buf); + if (!is_directory(repo_path.buf)) { strbuf_addstr(reason, _("not a valid directory")); rc = 1; goto done; } - strbuf_addf(&file, "%s/locked", repo.buf); + strbuf_addf(&file, "%s/locked", repo_path.buf); if (file_exists(file.buf)) { goto done; } @@ -995,12 +1011,12 @@ int should_prune_worktree(const char *id, struct strbuf *reason, char **wtpath, if (is_absolute_path(path)) { strbuf_addstr(&dotgit, path); } else { - strbuf_addf(&dotgit, "%s/%s", repo.buf, path); + strbuf_addf(&dotgit, "%s/%s", repo_path.buf, path); strbuf_realpath_forgiving(&dotgit, dotgit.buf, 0); } if (!file_exists(dotgit.buf)) { strbuf_reset(&file); - strbuf_addf(&file, "%s/index", repo.buf); + strbuf_addf(&file, "%s/index", repo_path.buf); if (stat(file.buf, &st) || st.st_mtime <= expire) { strbuf_addstr(reason, _("gitdir file points to non-existent location")); rc = 1; @@ -1012,17 +1028,18 @@ done: free(path); strbuf_release(&dotgit); strbuf_release(&gitdir); - strbuf_release(&repo); + strbuf_release(&repo_path); strbuf_release(&file); return rc; } -static int move_config_setting(const char *key, const char *value, +static int move_config_setting(struct repository *repo, + const char *key, const char *value, const char *from_file, const char *to_file) { - if (repo_config_set_in_file_gently(the_repository, to_file, key, NULL, value)) + if (repo_config_set_in_file_gently(repo, to_file, key, NULL, value)) return error(_("unable to set %s in '%s'"), key, to_file); - if (repo_config_set_in_file_gently(the_repository, from_file, key, NULL, NULL)) + if (repo_config_set_in_file_gently(repo, from_file, key, NULL, NULL)) return error(_("unable to unset %s in '%s'"), key, from_file); return 0; } @@ -1042,7 +1059,7 @@ int init_worktree_config(struct repository *r) */ if (r->repository_format_worktree_config) return 0; - if ((res = repo_config_set_gently(the_repository, "extensions.worktreeConfig", "true"))) + if ((res = repo_config_set_gently(r, "extensions.worktreeConfig", "true"))) return error(_("failed to set extensions.worktreeConfig setting")); common_config_file = xstrfmt("%s/config", r->commondir); @@ -1058,7 +1075,7 @@ int init_worktree_config(struct repository *r) * _could_ be negating a global core.bare=true. */ if (!git_configset_get_bool(&cs, "core.bare", &bare) && bare) { - if ((res = move_config_setting("core.bare", "true", + if ((res = move_config_setting(r, "core.bare", "true", common_config_file, main_worktree_file))) goto cleanup; @@ -1070,7 +1087,7 @@ int init_worktree_config(struct repository *r) * upgrade to worktree config. */ if (!git_configset_get_value(&cs, "core.worktree", &core_worktree, NULL)) { - if ((res = move_config_setting("core.worktree", core_worktree, + if ((res = move_config_setting(r, "core.worktree", core_worktree, common_config_file, main_worktree_file))) goto cleanup; @@ -1089,37 +1106,38 @@ cleanup: return res; } -void write_worktree_linking_files(const char *dotgit, const char *gitdir, +void write_worktree_linking_files(struct repository *repo, + const char *dotgit, const char *gitdir, int use_relative_paths) { struct strbuf path = STRBUF_INIT; - struct strbuf repo = STRBUF_INIT; + struct strbuf repo_path = STRBUF_INIT; struct strbuf tmp = STRBUF_INIT; strbuf_addstr(&path, dotgit); strbuf_strip_suffix(&path, "/.git"); strbuf_realpath(&path, path.buf, 1); - strbuf_addstr(&repo, gitdir); - strbuf_strip_suffix(&repo, "/gitdir"); - strbuf_realpath(&repo, repo.buf, 1); + strbuf_addstr(&repo_path, gitdir); + strbuf_strip_suffix(&repo_path, "/gitdir"); + strbuf_realpath(&repo_path, repo_path.buf, 1); - if (use_relative_paths && !the_repository->repository_format_relative_worktrees) { - if (upgrade_repository_format(the_repository, 1) < 0) + if (use_relative_paths && !repo->repository_format_relative_worktrees) { + if (upgrade_repository_format(repo, 1) < 0) die(_("unable to upgrade repository format to support relative worktrees")); - if (repo_config_set_gently(the_repository, "extensions.relativeWorktrees", "true")) + if (repo_config_set_gently(repo, "extensions.relativeWorktrees", "true")) die(_("unable to set extensions.relativeWorktrees setting")); - the_repository->repository_format_relative_worktrees = 1; + repo->repository_format_relative_worktrees = 1; } if (use_relative_paths) { - write_file(gitdir, "%s/.git", relative_path(path.buf, repo.buf, &tmp)); - write_file(dotgit, "gitdir: %s", relative_path(repo.buf, path.buf, &tmp)); + write_file(gitdir, "%s/.git", relative_path(path.buf, repo_path.buf, &tmp)); + write_file(dotgit, "gitdir: %s", relative_path(repo_path.buf, path.buf, &tmp)); } else { write_file(gitdir, "%s/.git", path.buf); - write_file(dotgit, "gitdir: %s", repo.buf); + write_file(dotgit, "gitdir: %s", repo_path.buf); } strbuf_release(&path); - strbuf_release(&repo); + strbuf_release(&repo_path); strbuf_release(&tmp); } diff --git a/worktree.h b/worktree.h index 1075409f9a..fbb2757f5b 100644 --- a/worktree.h +++ b/worktree.h @@ -28,7 +28,7 @@ struct worktree { * The caller is responsible for freeing the memory from the returned * worktrees by calling free_worktrees(). */ -struct worktree **get_worktrees(void); +struct worktree **get_worktrees(struct repository *repo); /* * Like `get_worktrees`, but does not read HEAD. Skip reading HEAD allows to @@ -36,7 +36,7 @@ struct worktree **get_worktrees(void); * the HEAD ref. This is useful in contexts where it is assumed that the * refdb may not be in a consistent state. */ -struct worktree **get_worktrees_without_reading_head(void); +struct worktree **get_worktrees_without_reading_head(struct repository *repo); /* * Construct a struct worktree corresponding to repo->gitdir and @@ -47,7 +47,7 @@ struct worktree *get_current_worktree(struct repository *repo); /* * Returns 1 if linked worktrees exist, 0 otherwise. */ -int submodule_uses_worktrees(const char *path); +int submodule_uses_worktrees(struct repository *repo, const char *path); /* * Return git dir of the worktree. Note that the path may be relative. @@ -76,7 +76,8 @@ struct worktree *find_worktree(struct worktree **list, * Look up the worktree corresponding to `id`, or NULL of no such worktree * exists. */ -struct worktree *get_linked_worktree(const char *id, +struct worktree *get_linked_worktree(struct repository *repo, + const char *id, int skip_reading_head); /* @@ -112,7 +113,8 @@ const char *worktree_prune_reason(struct worktree *wt, timestamp_t expire); * `expire` defines a grace period to prune the worktree when its path * does not exist. */ -int should_prune_worktree(const char *id, +int should_prune_worktree(struct repository *repo, + const char *id, struct strbuf *reason, char **wtpath, timestamp_t expire); @@ -142,12 +144,14 @@ typedef void (* worktree_repair_fn)(int iserr, const char *path, * function, if non-NULL, is called with the path of the worktree and a * description of the repair or error, along with the callback user-data. */ -void repair_worktrees(worktree_repair_fn, void *cb_data, int use_relative_paths); +void repair_worktrees(struct repository *repo, worktree_repair_fn, + void *cb_data, int use_relative_paths); /* * Repair the linked worktrees after the gitdir has been moved. */ -void repair_worktrees_after_gitdir_move(const char *old_path); +void repair_worktrees_after_gitdir_move(struct repository *repo, + const char *old_path); /* * Repair the linked worktree after the gitdir has been moved. @@ -164,7 +168,9 @@ void repair_worktree_after_gitdir_move(struct worktree *wt, const char *old_path * worktree and a description of the repair or error, along with the callback * user-data. */ -void repair_worktree_at_path(const char *, worktree_repair_fn, +void repair_worktree_at_path(struct repository *repo, + const char *path, + worktree_repair_fn fn, void *cb_data, int use_relative_paths); /* @@ -196,7 +202,7 @@ int is_shared_symref(const struct worktree *wt, * Similar to head_ref() for all HEADs _except_ one from the current * worktree, which is covered by head_ref(). */ -int other_head_refs(refs_for_each_cb fn, void *cb_data); +int other_head_refs(struct repository *repo, refs_for_each_cb fn, void *cb_data); int is_worktree_being_rebased(const struct worktree *wt, const char *target); int is_worktree_being_bisected(const struct worktree *wt, const char *target); @@ -239,7 +245,8 @@ int init_worktree_config(struct repository *r); * dotgit: "/path/to/foo/.git" * gitdir: "/path/to/repo/worktrees/foo/gitdir" */ -void write_worktree_linking_files(const char *dotgit, const char *gitdir, +void write_worktree_linking_files(struct repository *repo, + const char *dotgit, const char *gitdir, int use_relative_paths); #endif