diff options
Diffstat (limited to 'refs.c')
| -rw-r--r-- | refs.c | 220 |
1 files changed, 129 insertions, 91 deletions
@@ -19,7 +19,7 @@ #include "run-command.h" #include "hook.h" #include "object-name.h" -#include "object-store.h" +#include "odb.h" #include "object.h" #include "path.h" #include "submodule.h" @@ -32,6 +32,7 @@ #include "commit.h" #include "wildmatch.h" #include "ident.h" +#include "fsck.h" /* * List of all available backends @@ -323,6 +324,9 @@ int check_refname_format(const char *refname, int flags) int refs_fsck(struct ref_store *refs, struct fsck_options *o, struct worktree *wt) { + if (o->verbose) + fprintf_ln(stderr, _("Checking references consistency")); + return refs->be->fsck(refs, o, wt); } @@ -376,7 +380,8 @@ int ref_resolves_to_object(const char *refname, { if (flags & REF_ISBROKEN) return 0; - if (!has_object(repo, oid, HAS_OBJECT_RECHECK_PACKED | HAS_OBJECT_FETCH_PROMISOR)) { + if (!odb_has_object(repo->objects, oid, + HAS_OBJECT_RECHECK_PACKED | HAS_OBJECT_FETCH_PROMISOR)) { error(_("%s does not point to a valid object!"), refname); return 0; } @@ -438,9 +443,9 @@ static int for_each_filter_refs(const char *refname, const char *referent, struct warn_if_dangling_data { struct ref_store *refs; FILE *fp; - const char *refname; const struct string_list *refnames; - const char *msg_fmt; + const char *indent; + int dry_run; }; static int warn_if_dangling_symref(const char *refname, const char *referent UNUSED, @@ -448,44 +453,34 @@ static int warn_if_dangling_symref(const char *refname, const char *referent UNU int flags, void *cb_data) { struct warn_if_dangling_data *d = cb_data; - const char *resolves_to; + const char *resolves_to, *msg; if (!(flags & REF_ISSYMREF)) return 0; resolves_to = refs_resolve_ref_unsafe(d->refs, refname, 0, NULL, NULL); if (!resolves_to - || (d->refname - ? strcmp(resolves_to, d->refname) - : !string_list_has_string(d->refnames, resolves_to))) { + || !string_list_has_string(d->refnames, resolves_to)) { return 0; } - fprintf(d->fp, d->msg_fmt, refname); - fputc('\n', d->fp); + msg = d->dry_run + ? _("%s%s will become dangling after %s is deleted\n") + : _("%s%s has become dangling after %s was deleted\n"); + fprintf(d->fp, msg, d->indent, refname, resolves_to); return 0; } -void refs_warn_dangling_symref(struct ref_store *refs, FILE *fp, - const char *msg_fmt, const char *refname) -{ - struct warn_if_dangling_data data = { - .refs = refs, - .fp = fp, - .refname = refname, - .msg_fmt = msg_fmt, - }; - refs_for_each_rawref(refs, warn_if_dangling_symref, &data); -} - void refs_warn_dangling_symrefs(struct ref_store *refs, FILE *fp, - const char *msg_fmt, const struct string_list *refnames) + const char *indent, int dry_run, + const struct string_list *refnames) { struct warn_if_dangling_data data = { .refs = refs, .fp = fp, .refnames = refnames, - .msg_fmt = msg_fmt, + .indent = indent, + .dry_run = dry_run, }; refs_for_each_rawref(refs, warn_if_dangling_symref, &data); } @@ -636,10 +631,12 @@ void expand_ref_prefix(struct strvec *prefixes, const char *prefix) strvec_pushf(prefixes, *p, len, prefix); } +#ifndef WITH_BREAKING_CHANGES static const char default_branch_name_advice[] = N_( "Using '%s' as the name for the initial branch. This default branch name\n" -"is subject to change. To configure the initial branch name to use in all\n" -"of your new repositories, which will suppress this warning, call:\n" +"will change to \"main\" in Git 3.0. To configure the initial branch name\n" +"to use in all of your new repositories, which will suppress this warning,\n" +"call:\n" "\n" "\tgit config --global init.defaultBranch <name>\n" "\n" @@ -648,6 +645,15 @@ static const char default_branch_name_advice[] = N_( "\n" "\tgit branch -m <name>\n" ); +#else +static const char default_branch_name_advice[] = N_( +"Using '%s' as the name for the initial branch since Git 3.0.\n" +"If you expected Git to create 'master', the just-created\n" +"branch can be renamed via this command:\n" +"\n" +"\tgit branch -m master\n" +); +#endif /* WITH_BREAKING_CHANGES */ char *repo_default_branch_name(struct repository *r, int quiet) { @@ -658,11 +664,15 @@ char *repo_default_branch_name(struct repository *r, int quiet) if (env && *env) ret = xstrdup(env); - else if (repo_config_get_string(r, config_key, &ret) < 0) + if (!ret && repo_config_get_string(r, config_key, &ret) < 0) die(_("could not retrieve `%s`"), config_display_key); if (!ret) { +#ifdef WITH_BREAKING_CHANGES + ret = xstrdup("main"); +#else ret = xstrdup("master"); +#endif /* WITH_BREAKING_CHANGES */ if (!quiet) advise_if_enabled(ADVICE_DEFAULT_BRANCH_NAME, _(default_branch_name_advice), ret); @@ -954,7 +964,7 @@ long get_files_ref_lock_timeout_ms(void) static int timeout_ms = 100; if (!configured) { - git_config_get_int("core.filesreflocktimeout", &timeout_ms); + repo_config_get_int(the_repository, "core.filesreflocktimeout", &timeout_ms); configured = 1; } @@ -1031,7 +1041,6 @@ int is_branch(const char *refname) } struct read_ref_at_cb { - const char *refname; timestamp_t at_time; int cnt; int reccnt; @@ -1061,7 +1070,8 @@ static void set_read_ref_cutoffs(struct read_ref_at_cb *cb, *cb->cutoff_cnt = cb->reccnt; } -static int read_ref_at_ent(struct object_id *ooid, struct object_id *noid, +static int read_ref_at_ent(const char *refname, + struct object_id *ooid, struct object_id *noid, const char *email UNUSED, timestamp_t timestamp, int tz, const char *message, void *cb_data) @@ -1081,14 +1091,13 @@ static int read_ref_at_ent(struct object_id *ooid, struct object_id *noid, oidcpy(cb->oid, noid); if (!oideq(&cb->ooid, noid)) warning(_("log for ref %s has gap after %s"), - cb->refname, show_date(cb->date, cb->tz, DATE_MODE(RFC2822))); + refname, show_date(cb->date, cb->tz, DATE_MODE(RFC2822))); } else if (cb->date == cb->at_time) oidcpy(cb->oid, noid); else if (!oideq(noid, cb->oid)) warning(_("log for ref %s unexpectedly ended on %s"), - cb->refname, show_date(cb->date, cb->tz, - DATE_MODE(RFC2822))); + refname, show_date(cb->date, cb->tz, DATE_MODE(RFC2822))); cb->reccnt++; oidcpy(&cb->ooid, ooid); oidcpy(&cb->noid, noid); @@ -1103,7 +1112,8 @@ static int read_ref_at_ent(struct object_id *ooid, struct object_id *noid, return 0; } -static int read_ref_at_ent_oldest(struct object_id *ooid, struct object_id *noid, +static int read_ref_at_ent_oldest(const char *refname UNUSED, + struct object_id *ooid, struct object_id *noid, const char *email UNUSED, timestamp_t timestamp, int tz, const char *message, void *cb_data) @@ -1126,7 +1136,6 @@ int read_ref_at(struct ref_store *refs, const char *refname, struct read_ref_at_cb cb; memset(&cb, 0, sizeof(cb)); - cb.refname = refname; cb.at_time = at_time; cb.cnt = cnt; cb.msg = msg; @@ -1232,7 +1241,7 @@ int ref_transaction_maybe_set_rejected(struct ref_transaction *transaction, return 0; if (!transaction->rejections) - BUG("transaction not inititalized with failure support"); + BUG("transaction not initialized with failure support"); /* * Don't accept generic errors, since these errors are not user @@ -1241,6 +1250,13 @@ int ref_transaction_maybe_set_rejected(struct ref_transaction *transaction, if (err == REF_TRANSACTION_ERROR_GENERIC) return 0; + /* + * Rejected refnames shouldn't be considered in the availability + * checks, so remove them from the list. + */ + string_list_remove(&transaction->refnames, + transaction->updates[update_idx]->refname, 0); + transaction->updates[update_idx]->rejection_err = err; ALLOC_GROW(transaction->rejections->update_indices, transaction->rejections->nr + 1, @@ -1371,27 +1387,22 @@ int ref_transaction_update(struct ref_transaction *transaction, return 0; } -/* - * Similar to`ref_transaction_update`, but this function is only for adding - * a reflog update. Supports providing custom committer information. The index - * field can be utiltized to order updates as desired. When not used, the - * updates default to being ordered by refname. - */ -static int ref_transaction_update_reflog(struct ref_transaction *transaction, - const char *refname, - const struct object_id *new_oid, - const struct object_id *old_oid, - const char *committer_info, - unsigned int flags, - const char *msg, - uint64_t index, - struct strbuf *err) +int ref_transaction_update_reflog(struct ref_transaction *transaction, + const char *refname, + const struct object_id *new_oid, + const struct object_id *old_oid, + const char *committer_info, + const char *msg, + uint64_t index, + struct strbuf *err) { struct ref_update *update; + unsigned int flags; assert(err); - flags |= REF_LOG_ONLY | REF_FORCE_CREATE_REFLOG | REF_NO_DEREF; + flags = REF_HAVE_OLD | REF_HAVE_NEW | REF_LOG_ONLY | REF_FORCE_CREATE_REFLOG | REF_NO_DEREF | + REF_LOG_USE_PROVIDED_OIDS; if (!transaction_refname_valid(refname, new_oid, flags, err)) return -1; @@ -1399,11 +1410,6 @@ static int ref_transaction_update_reflog(struct ref_transaction *transaction, update = ref_transaction_add_update(transaction, refname, flags, new_oid, old_oid, NULL, NULL, committer_info, msg); - /* - * While we do set the old_oid value, we unset the flag to skip - * old_oid verification which only makes sense for refs. - */ - update->flags &= ~REF_HAVE_OLD; update->index = index; /* @@ -1859,7 +1865,13 @@ int refs_for_each_namespaced_ref(struct ref_store *refs, int refs_for_each_rawref(struct ref_store *refs, each_ref_fn fn, void *cb_data) { - return do_for_each_ref(refs, "", NULL, fn, 0, + return refs_for_each_rawref_in(refs, "", fn, cb_data); +} + +int refs_for_each_rawref_in(struct ref_store *refs, const char *prefix, + each_ref_fn fn, void *cb_data) +{ + return do_for_each_ref(refs, prefix, NULL, fn, 0, DO_FOR_EACH_INCLUDE_BROKEN, cb_data); } @@ -2296,6 +2308,11 @@ int refs_pack_refs(struct ref_store *refs, struct pack_refs_opts *opts) return refs->be->pack_refs(refs, opts); } +int refs_optimize(struct ref_store *refs, struct pack_refs_opts *opts) +{ + return refs->be->optimize(refs, opts); +} + int peel_iterated_oid(struct repository *r, const struct object_id *base, struct object_id *peeled) { if (current_ref_iter && @@ -2477,7 +2494,7 @@ int ref_transaction_prepare(struct ref_transaction *transaction, break; } - if (refs->repo->objects->odb->disable_ref_updates) { + if (refs->repo->objects->sources->disable_ref_updates) { strbuf_addstr(err, _("ref updates forbidden inside quarantine environment")); return -1; @@ -2666,12 +2683,12 @@ enum ref_transaction_error refs_verify_refnames_available(struct ref_store *refs if (!initial_transaction) { int ok; - if (!iter) { + if (!iter) iter = refs_ref_iterator_begin(refs, dirname.buf, NULL, 0, DO_FOR_EACH_INCLUDE_BROKEN); - } else if (ref_iterator_seek(iter, dirname.buf) < 0) { + else if (ref_iterator_seek(iter, dirname.buf, + REF_ITERATOR_SEEK_SET_PREFIX) < 0) goto cleanup; - } while ((ok = ref_iterator_advance(iter)) == ITER_OK) { if (skip && @@ -2960,7 +2977,8 @@ struct migration_data { struct ref_store *old_refs; struct ref_transaction *transaction; struct strbuf *errbuf; - struct strbuf sb; + struct strbuf sb, name, mail; + uint64_t index; }; static int migrate_one_ref(const char *refname, const char *referent UNUSED, const struct object_id *oid, @@ -2993,50 +3011,41 @@ done: return ret; } -struct reflog_migration_data { - uint64_t index; - const char *refname; - struct ref_store *old_refs; - struct ref_transaction *transaction; - struct strbuf *errbuf; - struct strbuf *sb; -}; - -static int migrate_one_reflog_entry(struct object_id *old_oid, +static int migrate_one_reflog_entry(const char *refname, + struct object_id *old_oid, struct object_id *new_oid, const char *committer, timestamp_t timestamp, int tz, const char *msg, void *cb_data) { - struct reflog_migration_data *data = cb_data; + struct migration_data *data = cb_data; + struct ident_split ident; const char *date; int ret; + if (split_ident_line(&ident, committer, strlen(committer)) < 0) + return -1; + + strbuf_reset(&data->name); + strbuf_add(&data->name, ident.name_begin, ident.name_end - ident.name_begin); + strbuf_reset(&data->mail); + strbuf_add(&data->mail, ident.mail_begin, ident.mail_end - ident.mail_begin); + date = show_date(timestamp, tz, DATE_MODE(NORMAL)); - strbuf_reset(data->sb); - /* committer contains name and email */ - strbuf_addstr(data->sb, fmt_ident("", committer, WANT_BLANK_IDENT, date, 0)); - - ret = ref_transaction_update_reflog(data->transaction, data->refname, - new_oid, old_oid, data->sb->buf, - REF_HAVE_NEW | REF_HAVE_OLD, msg, - data->index++, data->errbuf); + strbuf_reset(&data->sb); + strbuf_addstr(&data->sb, fmt_ident(data->name.buf, data->mail.buf, WANT_BLANK_IDENT, date, 0)); + + ret = ref_transaction_update_reflog(data->transaction, refname, + new_oid, old_oid, data->sb.buf, + msg, data->index++, data->errbuf); return ret; } static int migrate_one_reflog(const char *refname, void *cb_data) { struct migration_data *migration_data = cb_data; - struct reflog_migration_data data = { - .refname = refname, - .old_refs = migration_data->old_refs, - .transaction = migration_data->transaction, - .errbuf = migration_data->errbuf, - .sb = &migration_data->sb, - }; - return refs_for_each_reflog_ent(migration_data->old_refs, refname, - migrate_one_reflog_entry, &data); + migrate_one_reflog_entry, migration_data); } static int move_files(const char *from_path, const char *to_path, struct strbuf *errbuf) @@ -3131,6 +3140,8 @@ int repo_migrate_ref_storage_format(struct repository *repo, struct strbuf new_gitdir = STRBUF_INIT; struct migration_data data = { .sb = STRBUF_INIT, + .name = STRBUF_INIT, + .mail = STRBUF_INIT, }; int did_migrate_refs = 0; int ret; @@ -3306,11 +3317,38 @@ done: ref_transaction_free(transaction); strbuf_release(&new_gitdir); strbuf_release(&data.sb); + strbuf_release(&data.name); + strbuf_release(&data.mail); return ret; } int ref_update_expects_existing_old_ref(struct ref_update *update) { + if (update->flags & REF_LOG_ONLY) + return 0; + return (update->flags & REF_HAVE_OLD) && (!is_null_oid(&update->old_oid) || update->old_target); } + +const char *ref_transaction_error_msg(enum ref_transaction_error err) +{ + switch (err) { + case REF_TRANSACTION_ERROR_NAME_CONFLICT: + return "refname conflict"; + case REF_TRANSACTION_ERROR_CREATE_EXISTS: + return "reference already exists"; + case REF_TRANSACTION_ERROR_NONEXISTENT_REF: + return "reference does not exist"; + case REF_TRANSACTION_ERROR_INCORRECT_OLD_VALUE: + return "incorrect old value provided"; + case REF_TRANSACTION_ERROR_INVALID_NEW_VALUE: + return "invalid new value provided"; + case REF_TRANSACTION_ERROR_EXPECTED_SYMREF: + return "expected symref but found regular ref"; + case REF_TRANSACTION_ERROR_CASE_CONFLICT: + return "reference conflict due to case-insensitive filesystem"; + default: + return "unknown failure"; + } +} |
