diff options
Diffstat (limited to 'refs.c')
| -rw-r--r-- | refs.c | 201 |
1 files changed, 140 insertions, 61 deletions
@@ -24,7 +24,7 @@ #include "submodule.h" #include "worktree.h" #include "strvec.h" -#include "repository.h" +#include "repo-settings.h" #include "setup.h" #include "sigchain.h" #include "date.h" @@ -318,6 +318,12 @@ int check_refname_format(const char *refname, int flags) return check_or_sanitize_refname(refname, flags, NULL); } +int refs_fsck(struct ref_store *refs, struct fsck_options *o, + struct worktree *wt) +{ + return refs->be->fsck(refs, o, wt); +} + void sanitize_refname_component(const char *refname, struct strbuf *out) { if (check_or_sanitize_refname(refname, REFNAME_ALLOW_ONELEVEL, out)) @@ -414,7 +420,7 @@ int refs_ref_exists(struct ref_store *refs, const char *refname) NULL, NULL); } -static int for_each_filter_refs(const char *refname, +static int for_each_filter_refs(const char *refname, const char *referent, const struct object_id *oid, int flags, void *data) { @@ -424,7 +430,7 @@ static int for_each_filter_refs(const char *refname, return 0; if (filter->prefix) skip_prefix(refname, filter->prefix, &refname); - return filter->fn(refname, oid, flags, filter->cb_data); + return filter->fn(refname, referent, oid, flags, filter->cb_data); } struct warn_if_dangling_data { @@ -435,7 +441,7 @@ struct warn_if_dangling_data { const char *msg_fmt; }; -static int warn_if_dangling_symref(const char *refname, +static int warn_if_dangling_symref(const char *refname, const char *referent UNUSED, const struct object_id *oid UNUSED, int flags, void *cb_data) { @@ -506,7 +512,7 @@ int refs_head_ref_namespaced(struct ref_store *refs, each_ref_fn fn, void *cb_da strbuf_addf(&buf, "%sHEAD", get_git_namespace()); if (!refs_read_ref_full(refs, buf.buf, RESOLVE_REF_READING, &oid, &flag)) - ret = fn(buf.buf, &oid, flag, cb_data); + ret = fn(buf.buf, NULL, &oid, flag, cb_data); strbuf_release(&buf); return ret; @@ -692,6 +698,53 @@ static char *substitute_branch_name(struct repository *r, return NULL; } +void copy_branchname(struct strbuf *sb, const char *name, unsigned allowed) +{ + int len = strlen(name); + struct interpret_branch_name_options options = { + .allowed = allowed + }; + int used = repo_interpret_branch_name(the_repository, name, len, sb, + &options); + + if (used < 0) + used = 0; + strbuf_add(sb, name + used, len - used); +} + +int check_branch_ref(struct strbuf *sb, const char *name) +{ + if (startup_info->have_repository) + copy_branchname(sb, name, INTERPRET_BRANCH_LOCAL); + else + strbuf_addstr(sb, name); + + /* + * This splice must be done even if we end up rejecting the + * name; builtin/branch.c::copy_or_rename_branch() still wants + * to see what the name expanded to so that "branch -m" can be + * used as a tool to correct earlier mistakes. + */ + strbuf_splice(sb, 0, 0, "refs/heads/", 11); + + if (*name == '-' || + !strcmp(sb->buf, "refs/heads/HEAD")) + return -1; + + return check_refname_format(sb->buf, 0); +} + +int check_tag_ref(struct strbuf *sb, const char *name) +{ + if (name[0] == '-' || !strcmp(name, "HEAD")) + return -1; + + strbuf_reset(sb); + strbuf_addf(sb, "refs/tags/%s", name); + + return check_refname_format(sb->buf, 0); +} + int repo_dwim_ref(struct repository *r, const char *str, int len, struct object_id *oid, char **ref, int nonfatal_dangling_mark) { @@ -725,7 +778,7 @@ int expand_ref(struct repository *repo, const char *str, int len, if (r) { if (!refs_found++) *ref = xstrdup(r); - if (!warn_ambiguous_refs) + if (!repo_settings_get_warn_ambiguous_refs(repo)) break; } else if ((flag & REF_ISSYMREF) && strcmp(fullref.buf, "HEAD")) { warning(_("ignoring dangling symref %s"), fullref.buf); @@ -770,7 +823,7 @@ int repo_dwim_log(struct repository *r, const char *str, int len, if (oid) oidcpy(oid, &hash); } - if (!warn_ambiguous_refs) + if (!repo_settings_get_warn_ambiguous_refs(r)) break; } strbuf_release(&path); @@ -913,7 +966,7 @@ int refs_delete_ref(struct ref_store *refs, const char *msg, struct ref_transaction *transaction; struct strbuf err = STRBUF_INIT; - transaction = ref_store_transaction_begin(refs, &err); + transaction = ref_store_transaction_begin(refs, 0, &err); if (!transaction || ref_transaction_delete(transaction, refname, old_oid, NULL, flags, msg, &err) || @@ -953,7 +1006,8 @@ static char *normalize_reflog_message(const char *msg) return strbuf_detach(&sb, NULL); } -int should_autocreate_reflog(const char *refname) +int should_autocreate_reflog(enum log_refs_config log_all_ref_updates, + const char *refname) { switch (log_all_ref_updates) { case LOG_REFS_ALWAYS: @@ -1110,6 +1164,7 @@ int read_ref_at(struct ref_store *refs, const char *refname, } struct ref_transaction *ref_store_transaction_begin(struct ref_store *refs, + unsigned int flags, struct strbuf *err) { struct ref_transaction *tr; @@ -1117,6 +1172,7 @@ struct ref_transaction *ref_store_transaction_begin(struct ref_store *refs, CALLOC_ARRAY(tr, 1); tr->ref_store = refs; + tr->flags = flags; return tr; } @@ -1180,8 +1236,9 @@ struct ref_update *ref_transaction_add_update( oidcpy(&update->new_oid, new_oid); if ((flags & REF_HAVE_OLD) && old_oid) oidcpy(&update->old_oid, old_oid); + if (!(flags & REF_SKIP_CREATE_REFLOG)) + update->msg = normalize_reflog_message(msg); - update->msg = normalize_reflog_message(msg); return update; } @@ -1303,7 +1360,7 @@ int refs_update_ref(struct ref_store *refs, const char *msg, struct strbuf err = STRBUF_INIT; int ret = 0; - t = ref_store_transaction_begin(refs, &err); + t = ref_store_transaction_begin(refs, 0, &err); if (!t || ref_transaction_update(t, refname, new_oid, old_oid, NULL, NULL, flags, msg, &err) || @@ -1512,6 +1569,19 @@ const char **hidden_refs_to_excludes(const struct strvec *hide_refs) return hide_refs->v; } +const char **get_namespaced_exclude_patterns(const char **exclude_patterns, + const char *namespace, + struct strvec *out) +{ + if (!namespace || !*namespace || !exclude_patterns || !*exclude_patterns) + return exclude_patterns; + + for (size_t i = 0; exclude_patterns[i]; i++) + strvec_pushf(out, "%s%s", namespace, exclude_patterns[i]); + + return out->v; +} + const char *find_descendant_ref(const char *dirname, const struct string_list *extras, const struct string_list *skip) @@ -1547,7 +1617,7 @@ int refs_head_ref(struct ref_store *refs, each_ref_fn fn, void *cb_data) if (refs_resolve_ref_unsafe(refs, "HEAD", RESOLVE_REF_READING, &oid, &flag)) - return fn("HEAD", &oid, flag, cb_data); + return fn("HEAD", NULL, &oid, flag, cb_data); return 0; } @@ -1629,11 +1699,19 @@ int refs_for_each_namespaced_ref(struct ref_store *refs, const char **exclude_patterns, each_ref_fn fn, void *cb_data) { - struct strbuf buf = STRBUF_INIT; + struct strvec namespaced_exclude_patterns = STRVEC_INIT; + struct strbuf prefix = STRBUF_INIT; int ret; - strbuf_addf(&buf, "%srefs/", get_git_namespace()); - ret = do_for_each_ref(refs, buf.buf, exclude_patterns, fn, 0, 0, cb_data); - strbuf_release(&buf); + + exclude_patterns = get_namespaced_exclude_patterns(exclude_patterns, + get_git_namespace(), + &namespaced_exclude_patterns); + + strbuf_addf(&prefix, "%srefs/", get_git_namespace()); + ret = do_for_each_ref(refs, prefix.buf, exclude_patterns, fn, 0, 0, cb_data); + + strvec_clear(&namespaced_exclude_patterns); + strbuf_release(&prefix); return ret; } @@ -1714,6 +1792,7 @@ int refs_for_each_fullref_in_prefixes(struct ref_store *ref_store, const char **exclude_patterns, each_ref_fn fn, void *cb_data) { + struct strvec namespaced_exclude_patterns = STRVEC_INIT; struct string_list prefixes = STRING_LIST_INIT_DUP; struct string_list_item *prefix; struct strbuf buf = STRBUF_INIT; @@ -1725,6 +1804,10 @@ int refs_for_each_fullref_in_prefixes(struct ref_store *ref_store, strbuf_addstr(&buf, namespace); namespace_len = buf.len; + exclude_patterns = get_namespaced_exclude_patterns(exclude_patterns, + namespace, + &namespaced_exclude_patterns); + for_each_string_list_item(prefix, &prefixes) { strbuf_addstr(&buf, prefix->string); ret = refs_for_each_fullref_in(ref_store, buf.buf, @@ -1734,6 +1817,7 @@ int refs_for_each_fullref_in_prefixes(struct ref_store *ref_store, strbuf_setlen(&buf, namespace_len); } + strvec_clear(&namespaced_exclude_patterns); string_list_clear(&prefixes, 0); strbuf_release(&buf); return ret; @@ -1754,8 +1838,8 @@ static int refs_read_special_head(struct ref_store *ref_store, goto done; } - result = parse_loose_ref_contents(content.buf, oid, referent, type, - failure_errno); + result = parse_loose_ref_contents(ref_store->repo->hash_algo, content.buf, + oid, referent, type, NULL, failure_errno); done: strbuf_release(&full_path); @@ -1838,7 +1922,7 @@ const char *refs_resolve_ref_unsafe(struct ref_store *refs, failure_errno != ENOTDIR) return NULL; - oidclr(oid, the_repository->hash_algo); + oidclr(oid, refs->repo->hash_algo); if (*flags & REF_BAD_NAME) *flags |= REF_ISBROKEN; return refname; @@ -1848,7 +1932,7 @@ const char *refs_resolve_ref_unsafe(struct ref_store *refs, if (!(read_flags & REF_ISSYMREF)) { if (*flags & REF_BAD_NAME) { - oidclr(oid, the_repository->hash_algo); + oidclr(oid, refs->repo->hash_algo); *flags |= REF_ISBROKEN; } return refname; @@ -1856,7 +1940,7 @@ const char *refs_resolve_ref_unsafe(struct ref_store *refs, refname = sb_refname.buf; if (resolve_flags & RESOLVE_REF_NO_RECURSE) { - oidclr(oid, the_repository->hash_algo); + oidclr(oid, refs->repo->hash_algo); return refname; } if (check_refname_format(refname, REFNAME_ALLOW_ONELEVEL)) { @@ -2011,7 +2095,7 @@ struct ref_store *repo_get_submodule_ref_store(struct repository *repo, free(subrepo); goto done; } - refs = ref_store_init(subrepo, the_repository->ref_storage_format, + refs = ref_store_init(subrepo, subrepo->ref_storage_format, submodule_sb.buf, REF_STORE_READ | REF_STORE_ODB); register_ref_store_map(&repo->submodule_ref_stores, "submodule", @@ -2045,7 +2129,7 @@ struct ref_store *get_worktree_ref_store(const struct worktree *wt) common_path.buf, REF_STORE_ALL_CAPS); strbuf_release(&common_path); } else { - refs = ref_store_init(wt->repo, the_repository->ref_storage_format, + refs = ref_store_init(wt->repo, wt->repo->ref_storage_format, wt->repo->commondir, REF_STORE_ALL_CAPS); } @@ -2087,7 +2171,7 @@ int refs_update_symref(struct ref_store *refs, const char *ref, struct strbuf err = STRBUF_INIT; int ret = 0; - transaction = ref_store_transaction_begin(refs, &err); + transaction = ref_store_transaction_begin(refs, 0, &err); if (!transaction || ref_transaction_update(transaction, ref, NULL, NULL, target, NULL, REF_NO_DEREF, @@ -2134,7 +2218,7 @@ static int run_transaction_hook(struct ref_transaction *transaction, const char *hook; int ret = 0, i; - hook = find_hook("reference-transaction"); + hook = find_hook(transaction->ref_store->repo, "reference-transaction"); if (!hook) return ret; @@ -2152,6 +2236,9 @@ static int run_transaction_hook(struct ref_transaction *transaction, for (i = 0; i < transaction->nr; i++) { struct ref_update *update = transaction->updates[i]; + if (update->flags & REF_LOG_ONLY) + continue; + strbuf_reset(&buf); if (!(update->flags & REF_HAVE_OLD)) @@ -2280,7 +2367,7 @@ int ref_transaction_commit(struct ref_transaction *transaction, } ret = refs->be->transaction_finish(refs, transaction, err); - if (!ret) + if (!ret && !(transaction->flags & REF_TRANSACTION_FLAG_INITIAL)) run_transaction_hook(transaction, "committed"); return ret; } @@ -2289,6 +2376,7 @@ int refs_verify_refname_available(struct ref_store *refs, const char *refname, const struct string_list *extras, const struct string_list *skip, + unsigned int initial_transaction, struct strbuf *err) { const char *slash; @@ -2297,8 +2385,6 @@ int refs_verify_refname_available(struct ref_store *refs, struct strbuf referent = STRBUF_INIT; struct object_id oid; unsigned int type; - struct ref_iterator *iter; - int ok; int ret = -1; /* @@ -2328,7 +2414,8 @@ int refs_verify_refname_available(struct ref_store *refs, if (skip && string_list_has_string(skip, dirname.buf)) continue; - if (!refs_read_raw_ref(refs, dirname.buf, &oid, &referent, + if (!initial_transaction && + !refs_read_raw_ref(refs, dirname.buf, &oid, &referent, &type, &ignore_errno)) { strbuf_addf(err, _("'%s' exists; cannot create '%s'"), dirname.buf, refname); @@ -2353,21 +2440,26 @@ int refs_verify_refname_available(struct ref_store *refs, strbuf_addstr(&dirname, refname + dirname.len); strbuf_addch(&dirname, '/'); - iter = refs_ref_iterator_begin(refs, dirname.buf, NULL, 0, - DO_FOR_EACH_INCLUDE_BROKEN); - while ((ok = ref_iterator_advance(iter)) == ITER_OK) { - if (skip && - string_list_has_string(skip, iter->refname)) - continue; + if (!initial_transaction) { + struct ref_iterator *iter; + int ok; - strbuf_addf(err, _("'%s' exists; cannot create '%s'"), - iter->refname, refname); - ref_iterator_abort(iter); - goto cleanup; - } + iter = refs_ref_iterator_begin(refs, dirname.buf, NULL, 0, + DO_FOR_EACH_INCLUDE_BROKEN); + while ((ok = ref_iterator_advance(iter)) == ITER_OK) { + if (skip && + string_list_has_string(skip, iter->refname)) + continue; - if (ok != ITER_DONE) - BUG("error while iterating over references"); + strbuf_addf(err, _("'%s' exists; cannot create '%s'"), + iter->refname, refname); + ref_iterator_abort(iter); + goto cleanup; + } + + if (ok != ITER_DONE) + BUG("error while iterating over references"); + } extra_refname = find_descendant_ref(dirname.buf, extras, skip); if (extra_refname) @@ -2388,8 +2480,9 @@ struct do_for_each_reflog_help { }; static int do_for_each_reflog_helper(const char *refname, + const char *referent UNUSED, const struct object_id *oid UNUSED, - int flags, + int flags UNUSED, void *cb_data) { struct do_for_each_reflog_help *hp = cb_data; @@ -2450,14 +2543,6 @@ int refs_reflog_expire(struct ref_store *refs, cleanup_fn, policy_cb_data); } -int initial_ref_transaction_commit(struct ref_transaction *transaction, - struct strbuf *err) -{ - struct ref_store *refs = transaction->ref_store; - - return refs->be->initial_transaction_commit(refs, transaction, err); -} - void ref_transaction_for_each_queued_update(struct ref_transaction *transaction, ref_transaction_for_each_queued_update_fn cb, void *cb_data) @@ -2493,7 +2578,7 @@ int refs_delete_refs(struct ref_store *refs, const char *logmsg, * individual updates can't fail, so we can pack all of the * updates into a single transaction. */ - transaction = ref_store_transaction_begin(refs, &err); + transaction = ref_store_transaction_begin(refs, 0, &err); if (!transaction) { ret = error("%s", err.buf); goto out; @@ -2593,7 +2678,7 @@ struct migration_data { struct strbuf *errbuf; }; -static int migrate_one_ref(const char *refname, const struct object_id *oid, +static int migrate_one_ref(const char *refname, const char *referent UNUSED, const struct object_id *oid, int flags, void *cb_data) { struct migration_data *data = cb_data; @@ -2799,7 +2884,8 @@ int repo_migrate_ref_storage_format(struct repository *repo, if (ret < 0) goto done; - transaction = ref_store_transaction_begin(new_refs, errbuf); + transaction = ref_store_transaction_begin(new_refs, REF_TRANSACTION_FLAG_INITIAL, + errbuf); if (!transaction) goto done; @@ -2824,13 +2910,6 @@ int repo_migrate_ref_storage_format(struct repository *repo, if (ret < 0) goto done; - /* - * TODO: we might want to migrate to `initial_ref_transaction_commit()` - * here, which is more efficient for the files backend because it would - * write new refs into the packed-refs file directly. At this point, - * the files backend doesn't handle pseudo-refs and symrefs correctly - * though, so this requires some more work. - */ ret = ref_transaction_commit(transaction, errbuf); if (ret < 0) goto done; |
