aboutsummaryrefslogtreecommitdiffstats
path: root/refs.c
diff options
context:
space:
mode:
Diffstat (limited to 'refs.c')
-rw-r--r--refs.c220
1 files changed, 129 insertions, 91 deletions
diff --git a/refs.c b/refs.c
index dce5c49ca2..c83e3d7a4d 100644
--- a/refs.c
+++ b/refs.c
@@ -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";
+ }
+}