#include "iterator.h"
#include "refs.h"
#include "refs/refs-internal.h"
+#include "object-store.h"
#include "object.h"
#include "tag.h"
#include "submodule.h"
#include "worktree.h"
+#include "argv-array.h"
+#include "repository.h"
/*
* List of all available backends
if (flags & REF_ISBROKEN)
return 0;
if (!has_sha1_file(oid->hash)) {
- error("%s does not point to a valid object!", refname);
+ error(_("%s does not point to a valid object!"), refname);
return 0;
}
return 1;
char *resolve_refdup(const char *refname, int resolve_flags,
struct object_id *oid, int *flags)
{
- return refs_resolve_refdup(get_main_ref_store(),
+ return refs_resolve_refdup(get_main_ref_store(the_repository),
refname, resolve_flags,
oid, flags);
}
int read_ref_full(const char *refname, int resolve_flags, struct object_id *oid, int *flags)
{
- return refs_read_ref_full(get_main_ref_store(), refname,
+ return refs_read_ref_full(get_main_ref_store(the_repository), refname,
resolve_flags, oid, flags);
}
struct object *o = lookup_unknown_object(name->hash);
if (o->type == OBJ_NONE) {
- int type = sha1_object_info(name->hash, NULL);
- if (type < 0 || !object_as_type(o, type, 0))
+ int type = oid_object_info(the_repository, name, NULL);
+ if (type < 0 || !object_as_type(the_repository, o, type, 0))
return PEEL_INVALID;
}
int for_each_tag_ref(each_ref_fn fn, void *cb_data)
{
- return refs_for_each_tag_ref(get_main_ref_store(), fn, cb_data);
+ return refs_for_each_tag_ref(get_main_ref_store(the_repository), fn, cb_data);
}
int refs_for_each_branch_ref(struct ref_store *refs, each_ref_fn fn, void *cb_data)
int for_each_branch_ref(each_ref_fn fn, void *cb_data)
{
- return refs_for_each_branch_ref(get_main_ref_store(), fn, cb_data);
+ return refs_for_each_branch_ref(get_main_ref_store(the_repository), fn, cb_data);
}
int refs_for_each_remote_ref(struct ref_store *refs, each_ref_fn fn, void *cb_data)
int for_each_remote_ref(each_ref_fn fn, void *cb_data)
{
- return refs_for_each_remote_ref(get_main_ref_store(), fn, cb_data);
+ return refs_for_each_remote_ref(get_main_ref_store(the_repository), fn, cb_data);
}
int head_ref_namespaced(each_ref_fn fn, void *cb_data)
NULL
};
+#define NUM_REV_PARSE_RULES (ARRAY_SIZE(ref_rev_parse_rules) - 1)
+
+/*
+ * Is it possible that the caller meant full_name with abbrev_name?
+ * If so return a non-zero value to signal "yes"; the magnitude of
+ * the returned value gives the precedence used for disambiguation.
+ *
+ * If abbrev_name cannot mean full_name, return 0.
+ */
int refname_match(const char *abbrev_name, const char *full_name)
{
const char **p;
const int abbrev_name_len = strlen(abbrev_name);
+ const int num_rules = NUM_REV_PARSE_RULES;
- for (p = ref_rev_parse_rules; *p; p++) {
- if (!strcmp(full_name, mkpath(*p, abbrev_name_len, abbrev_name))) {
- return 1;
- }
- }
+ for (p = ref_rev_parse_rules; *p; p++)
+ if (!strcmp(full_name, mkpath(*p, abbrev_name_len, abbrev_name)))
+ return &ref_rev_parse_rules[num_rules] - p;
return 0;
}
+/*
+ * Given a 'prefix' expand it by the rules in 'ref_rev_parse_rules' and add
+ * the results to 'prefixes'
+ */
+void expand_ref_prefix(struct argv_array *prefixes, const char *prefix)
+{
+ const char **p;
+ int len = strlen(prefix);
+
+ for (p = ref_rev_parse_rules; *p; p++)
+ argv_array_pushf(prefixes, *p, len, prefix);
+}
+
/*
* *string and *len will only be substituted, and *string returned (for
* later free()ing) if the string passed in is a magic short-hand form
if (!warn_ambiguous_refs)
break;
} else if ((flag & REF_ISSYMREF) && strcmp(fullref.buf, "HEAD")) {
- warning("ignoring dangling symref %s.", fullref.buf);
+ warning(_("ignoring dangling symref %s"), fullref.buf);
} else if ((flag & REF_ISBROKEN) && strchr(fullref.buf, '/')) {
- warning("ignoring broken ref %s.", fullref.buf);
+ warning(_("ignoring broken ref %s"), fullref.buf);
}
}
strbuf_release(&fullref);
static int is_per_worktree_ref(const char *refname)
{
return !strcmp(refname, "HEAD") ||
- starts_with(refname, "refs/bisect/");
+ starts_with(refname, "refs/worktree/") ||
+ starts_with(refname, "refs/bisect/") ||
+ starts_with(refname, "refs/rewritten/");
}
static int is_pseudoref_syntax(const char *refname)
return REF_TYPE_PER_WORKTREE;
if (is_pseudoref_syntax(refname))
return REF_TYPE_PSEUDOREF;
- return REF_TYPE_NORMAL;
+ return REF_TYPE_NORMAL;
}
long get_files_ref_lock_timeout_ms(void)
{
const char *filename;
int fd;
- static struct lock_file lock;
+ struct lock_file lock = LOCK_INIT;
struct strbuf buf = STRBUF_INIT;
int ret = -1;
strbuf_addf(&buf, "%s\n", oid_to_hex(oid));
filename = git_path("%s", pseudoref);
- fd = hold_lock_file_for_update_timeout(&lock, filename,
- LOCK_DIE_ON_ERROR,
+ fd = hold_lock_file_for_update_timeout(&lock, filename, 0,
get_files_ref_lock_timeout_ms());
if (fd < 0) {
- strbuf_addf(err, "could not open '%s' for writing: %s",
+ strbuf_addf(err, _("could not open '%s' for writing: %s"),
filename, strerror(errno));
goto done;
}
if (old_oid) {
struct object_id actual_old_oid;
- if (read_ref(pseudoref, &actual_old_oid))
- die("could not read ref '%s'", pseudoref);
- if (oidcmp(&actual_old_oid, old_oid)) {
- strbuf_addf(err, "unexpected sha1 when writing '%s'", pseudoref);
+ if (read_ref(pseudoref, &actual_old_oid)) {
+ if (!is_null_oid(old_oid)) {
+ strbuf_addf(err, _("could not read ref '%s'"),
+ pseudoref);
+ rollback_lock_file(&lock);
+ goto done;
+ }
+ } else if (is_null_oid(old_oid)) {
+ strbuf_addf(err, _("ref '%s' already exists"),
+ pseudoref);
+ rollback_lock_file(&lock);
+ goto done;
+ } else if (!oideq(&actual_old_oid, old_oid)) {
+ strbuf_addf(err, _("unexpected object ID when writing '%s'"),
+ pseudoref);
rollback_lock_file(&lock);
goto done;
}
}
if (write_in_full(fd, buf.buf, buf.len) < 0) {
- strbuf_addf(err, "could not write to '%s'", filename);
+ strbuf_addf(err, _("could not write to '%s'"), filename);
rollback_lock_file(&lock);
goto done;
}
static int delete_pseudoref(const char *pseudoref, const struct object_id *old_oid)
{
- static struct lock_file lock;
const char *filename;
filename = git_path("%s", pseudoref);
if (old_oid && !is_null_oid(old_oid)) {
+ struct lock_file lock = LOCK_INIT;
int fd;
struct object_id actual_old_oid;
fd = hold_lock_file_for_update_timeout(
- &lock, filename, LOCK_DIE_ON_ERROR,
+ &lock, filename, 0,
get_files_ref_lock_timeout_ms());
- if (fd < 0)
- die_errno(_("Could not open '%s' for writing"), filename);
+ if (fd < 0) {
+ error_errno(_("could not open '%s' for writing"),
+ filename);
+ return -1;
+ }
if (read_ref(pseudoref, &actual_old_oid))
- die("could not read ref '%s'", pseudoref);
- if (oidcmp(&actual_old_oid, old_oid)) {
- warning("Unexpected sha1 when deleting %s", pseudoref);
+ die(_("could not read ref '%s'"), pseudoref);
+ if (!oideq(&actual_old_oid, old_oid)) {
+ error(_("unexpected object ID when deleting '%s'"),
+ pseudoref);
rollback_lock_file(&lock);
return -1;
}
struct strbuf err = STRBUF_INIT;
if (ref_type(refname) == REF_TYPE_PSEUDOREF) {
- assert(refs == get_main_ref_store());
+ assert(refs == get_main_ref_store(the_repository));
return delete_pseudoref(refname, old_oid);
}
int delete_ref(const char *msg, const char *refname,
const struct object_id *old_oid, unsigned int flags)
{
- return refs_delete_ref(get_main_ref_store(), msg, refname,
+ return refs_delete_ref(get_main_ref_store(the_repository), msg, refname,
old_oid, flags);
}
-int copy_reflog_msg(char *buf, const char *msg)
+void copy_reflog_msg(struct strbuf *sb, const char *msg)
{
- char *cp = buf;
char c;
int wasspace = 1;
- *cp++ = '\t';
+ strbuf_addch(sb, '\t');
while ((c = *msg++)) {
if (wasspace && isspace(c))
continue;
wasspace = isspace(c);
if (wasspace)
c = ' ';
- *cp++ = c;
+ strbuf_addch(sb, c);
}
- while (buf < cp && isspace(cp[-1]))
- cp--;
- *cp++ = '\n';
- return cp - buf;
+ strbuf_rtrim(sb);
}
int should_autocreate_reflog(const char *refname)
*/
if (!is_null_oid(&cb->ooid)) {
oidcpy(cb->oid, noid);
- if (oidcmp(&cb->ooid, noid))
- warning("Log for ref %s has gap after %s.",
+ 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)));
}
else if (cb->date == cb->at_time)
oidcpy(cb->oid, noid);
- else if (oidcmp(noid, cb->oid))
- warning("Log for ref %s unexpectedly ended on %s.",
+ 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)));
oidcpy(&cb->ooid, ooid);
if (flags & GET_OID_QUIETLY)
exit(128);
else
- die("Log for %s is empty.", refname);
+ die(_("log for %s is empty"), refname);
}
if (cb.found_it)
return 0;
struct ref_transaction *ref_transaction_begin(struct strbuf *err)
{
- return ref_store_transaction_begin(get_main_ref_store(), err);
+ return ref_store_transaction_begin(get_main_ref_store(the_repository), err);
}
void ref_transaction_free(struct ref_transaction *transaction)
/* OK */
break;
case REF_TRANSACTION_PREPARED:
- die("BUG: free called on a prepared reference transaction");
+ BUG("free called on a prepared reference transaction");
break;
default:
- die("BUG: unexpected reference transaction state");
+ BUG("unexpected reference transaction state");
break;
}
struct ref_update *update;
if (transaction->state != REF_TRANSACTION_OPEN)
- die("BUG: update called for transaction that is not open");
+ BUG("update called for transaction that is not open");
FLEX_ALLOC_STR(update, refname, refname);
ALLOC_GROW(transaction->updates, transaction->nr + 1, transaction->alloc);
if ((new_oid && !is_null_oid(new_oid)) ?
check_refname_format(refname, REFNAME_ALLOW_ONELEVEL) :
!refname_is_safe(refname)) {
- strbuf_addf(err, "refusing to update ref with bad name '%s'",
+ strbuf_addf(err, _("refusing to update ref with bad name '%s'"),
refname);
return -1;
}
struct strbuf *err)
{
if (!new_oid || is_null_oid(new_oid))
- die("BUG: create called without valid new_oid");
+ BUG("create called without valid new_oid");
return ref_transaction_update(transaction, refname, new_oid,
&null_oid, flags, msg, err);
}
struct strbuf *err)
{
if (old_oid && is_null_oid(old_oid))
- die("BUG: delete called with old_oid set to zeros");
+ BUG("delete called with old_oid set to zeros");
return ref_transaction_update(transaction, refname,
&null_oid, old_oid,
flags, msg, err);
struct strbuf *err)
{
if (!old_oid)
- die("BUG: verify called with old_oid set to NULL");
+ BUG("verify called with old_oid set to NULL");
return ref_transaction_update(transaction, refname,
NULL, old_oid,
flags, NULL, err);
int ret = 0;
if (ref_type(refname) == REF_TYPE_PSEUDOREF) {
- assert(refs == get_main_ref_store());
+ assert(refs == get_main_ref_store(the_repository));
ret = write_pseudoref(refname, new_oid, old_oid, &err);
} else {
t = ref_store_transaction_begin(refs, &err);
}
}
if (ret) {
- const char *str = "update_ref failed for ref '%s': %s";
+ const char *str = _("update_ref failed for ref '%s': %s");
switch (onerr) {
case UPDATE_REFS_MSG_ON_ERR:
const struct object_id *old_oid,
unsigned int flags, enum action_on_err onerr)
{
- return refs_update_ref(get_main_ref_store(), msg, refname, new_oid,
+ return refs_update_ref(get_main_ref_store(the_repository), msg, refname, new_oid,
old_oid, flags, onerr);
}
for (i = 0; i < nr_rules; i++) {
assert(offset < total_len);
scanf_fmts[i] = (char *)&scanf_fmts[nr_rules] + offset;
- offset += snprintf(scanf_fmts[i], total_len - offset,
- ref_rev_parse_rules[i], 2, "%s") + 1;
+ offset += xsnprintf(scanf_fmts[i], total_len - offset,
+ ref_rev_parse_rules[i], 2, "%s") + 1;
}
}
int head_ref(each_ref_fn fn, void *cb_data)
{
- return refs_head_ref(get_main_ref_store(), fn, cb_data);
+ return refs_head_ref(get_main_ref_store(the_repository), fn, cb_data);
}
struct ref_iterator *refs_ref_iterator_begin(
int for_each_ref(each_ref_fn fn, void *cb_data)
{
- return refs_for_each_ref(get_main_ref_store(), fn, cb_data);
+ return refs_for_each_ref(get_main_ref_store(the_repository), fn, cb_data);
}
int refs_for_each_ref_in(struct ref_store *refs, const char *prefix,
int for_each_ref_in(const char *prefix, each_ref_fn fn, void *cb_data)
{
- return refs_for_each_ref_in(get_main_ref_store(), prefix, fn, cb_data);
+ return refs_for_each_ref_in(get_main_ref_store(the_repository), prefix, fn, cb_data);
}
int for_each_fullref_in(const char *prefix, each_ref_fn fn, void *cb_data, unsigned int broken)
if (broken)
flag = DO_FOR_EACH_INCLUDE_BROKEN;
- return do_for_each_ref(get_main_ref_store(),
+ return do_for_each_ref(get_main_ref_store(the_repository),
prefix, fn, 0, flag, cb_data);
}
return do_for_each_ref(refs, prefix, fn, 0, flag, cb_data);
}
-int for_each_replace_ref(each_ref_fn fn, void *cb_data)
+int for_each_replace_ref(struct repository *r, each_ref_fn fn, void *cb_data)
{
- return do_for_each_ref(get_main_ref_store(),
+ return do_for_each_ref(get_main_ref_store(r),
git_replace_ref_base, fn,
strlen(git_replace_ref_base),
DO_FOR_EACH_INCLUDE_BROKEN, cb_data);
struct strbuf buf = STRBUF_INIT;
int ret;
strbuf_addf(&buf, "%srefs/", get_git_namespace());
- ret = do_for_each_ref(get_main_ref_store(),
+ ret = do_for_each_ref(get_main_ref_store(the_repository),
buf.buf, fn, 0, 0, cb_data);
strbuf_release(&buf);
return ret;
int for_each_rawref(each_ref_fn fn, void *cb_data)
{
- return refs_for_each_rawref(get_main_ref_store(), fn, cb_data);
+ return refs_for_each_rawref(get_main_ref_store(the_repository), fn, cb_data);
}
int refs_read_raw_ref(struct ref_store *ref_store,
/* backend functions */
int refs_init_db(struct strbuf *err)
{
- struct ref_store *refs = get_main_ref_store();
+ struct ref_store *refs = get_main_ref_store(the_repository);
return refs->be->init_db(refs, err);
}
const char *resolve_ref_unsafe(const char *refname, int resolve_flags,
struct object_id *oid, int *flags)
{
- return refs_resolve_ref_unsafe(get_main_ref_store(), refname,
+ return refs_resolve_ref_unsafe(get_main_ref_store(the_repository), refname,
resolve_flags, oid, flags);
}
return entry;
}
-/* A pointer to the ref_store for the main repository: */
-static struct ref_store *main_ref_store;
-
/* A hashmap of ref_stores, stored by submodule name: */
static struct hashmap submodule_ref_stores;
struct ref_store *refs;
if (!be)
- die("BUG: reference backend %s is unknown", be_name);
+ BUG("reference backend %s is unknown", be_name);
refs = be->init(gitdir, flags);
return refs;
}
-struct ref_store *get_main_ref_store(void)
+struct ref_store *get_main_ref_store(struct repository *r)
{
- if (main_ref_store)
- return main_ref_store;
+ if (r->refs)
+ return r->refs;
+
+ if (!r->gitdir)
+ BUG("attempting to get main_ref_store outside of repository");
- main_ref_store = ref_store_init(get_git_dir(), REF_STORE_ALL_CAPS);
- return main_ref_store;
+ r->refs = ref_store_init(r->gitdir, REF_STORE_ALL_CAPS);
+ return r->refs;
}
/*
hashmap_init(map, ref_store_hash_cmp, NULL, 0);
if (hashmap_put(map, alloc_ref_store_hash_entry(name, refs)))
- die("BUG: %s ref_store '%s' initialized twice", type, name);
+ BUG("%s ref_store '%s' initialized twice", type, name);
}
struct ref_store *get_submodule_ref_store(const char *submodule)
const char *id;
if (wt->is_current)
- return get_main_ref_store();
+ return get_main_ref_store(the_repository);
id = wt->id ? wt->id : "/";
refs = lookup_ref_store_map(&worktree_ref_stores, id);
int peel_ref(const char *refname, struct object_id *oid)
{
- return refs_peel_ref(get_main_ref_store(), refname, oid);
+ return refs_peel_ref(get_main_ref_store(the_repository), refname, oid);
}
int refs_create_symref(struct ref_store *refs,
int create_symref(const char *ref_target, const char *refs_heads_master,
const char *logmsg)
{
- return refs_create_symref(get_main_ref_store(), ref_target,
+ return refs_create_symref(get_main_ref_store(the_repository), ref_target,
refs_heads_master, logmsg);
}
if (!cmp) {
strbuf_addf(err,
- "multiple updates for ref '%s' not allowed.",
+ _("multiple updates for ref '%s' not allowed"),
refnames->items[i].string);
return 1;
} else if (cmp > 0) {
- die("BUG: ref_update_reject_duplicates() received unsorted list");
+ BUG("ref_update_reject_duplicates() received unsorted list");
}
}
return 0;
/* Good. */
break;
case REF_TRANSACTION_PREPARED:
- die("BUG: prepare called twice on reference transaction");
+ BUG("prepare called twice on reference transaction");
break;
case REF_TRANSACTION_CLOSED:
- die("BUG: prepare called on a closed reference transaction");
+ BUG("prepare called on a closed reference transaction");
break;
default:
- die("BUG: unexpected reference transaction state");
+ BUG("unexpected reference transaction state");
break;
}
ret = refs->be->transaction_abort(refs, transaction, err);
break;
case REF_TRANSACTION_CLOSED:
- die("BUG: abort called on a closed reference transaction");
+ BUG("abort called on a closed reference transaction");
break;
default:
- die("BUG: unexpected reference transaction state");
+ BUG("unexpected reference transaction state");
break;
}
/* Fall through to finish. */
break;
case REF_TRANSACTION_CLOSED:
- die("BUG: commit called on a closed reference transaction");
+ BUG("commit called on a closed reference transaction");
break;
default:
- die("BUG: unexpected reference transaction state");
+ BUG("unexpected reference transaction state");
break;
}
continue;
if (!refs_read_raw_ref(refs, dirname.buf, &oid, &referent, &type)) {
- strbuf_addf(err, "'%s' exists; cannot create '%s'",
+ strbuf_addf(err, _("'%s' exists; cannot create '%s'"),
dirname.buf, refname);
goto cleanup;
}
if (extras && string_list_has_string(extras, dirname.buf)) {
- strbuf_addf(err, "cannot process '%s' and '%s' at the same time",
+ strbuf_addf(err, _("cannot process '%s' and '%s' at the same time"),
refname, dirname.buf);
goto cleanup;
}
string_list_has_string(skip, iter->refname))
continue;
- strbuf_addf(err, "'%s' exists; cannot create '%s'",
+ strbuf_addf(err, _("'%s' exists; cannot create '%s'"),
iter->refname, refname);
ref_iterator_abort(iter);
goto cleanup;
}
if (ok != ITER_DONE)
- die("BUG: error while iterating over references");
+ BUG("error while iterating over references");
extra_refname = find_descendant_ref(dirname.buf, extras, skip);
if (extra_refname)
- strbuf_addf(err, "cannot process '%s' and '%s' at the same time",
+ strbuf_addf(err, _("cannot process '%s' and '%s' at the same time"),
refname, extra_refname);
else
ret = 0;
int for_each_reflog(each_ref_fn fn, void *cb_data)
{
- return refs_for_each_reflog(get_main_ref_store(), fn, cb_data);
+ return refs_for_each_reflog(get_main_ref_store(the_repository), fn, cb_data);
}
int refs_for_each_reflog_ent_reverse(struct ref_store *refs,
int for_each_reflog_ent_reverse(const char *refname, each_reflog_ent_fn fn,
void *cb_data)
{
- return refs_for_each_reflog_ent_reverse(get_main_ref_store(),
+ return refs_for_each_reflog_ent_reverse(get_main_ref_store(the_repository),
refname, fn, cb_data);
}
int for_each_reflog_ent(const char *refname, each_reflog_ent_fn fn,
void *cb_data)
{
- return refs_for_each_reflog_ent(get_main_ref_store(), refname,
+ return refs_for_each_reflog_ent(get_main_ref_store(the_repository), refname,
fn, cb_data);
}
int reflog_exists(const char *refname)
{
- return refs_reflog_exists(get_main_ref_store(), refname);
+ return refs_reflog_exists(get_main_ref_store(the_repository), refname);
}
int refs_create_reflog(struct ref_store *refs, const char *refname,
int safe_create_reflog(const char *refname, int force_create,
struct strbuf *err)
{
- return refs_create_reflog(get_main_ref_store(), refname,
+ return refs_create_reflog(get_main_ref_store(the_repository), refname,
force_create, err);
}
int delete_reflog(const char *refname)
{
- return refs_delete_reflog(get_main_ref_store(), refname);
+ return refs_delete_reflog(get_main_ref_store(the_repository), refname);
}
int refs_reflog_expire(struct ref_store *refs,
reflog_expiry_cleanup_fn cleanup_fn,
void *policy_cb_data)
{
- return refs_reflog_expire(get_main_ref_store(),
+ return refs_reflog_expire(get_main_ref_store(the_repository),
refname, oid, flags,
prepare_fn, should_prune_fn,
cleanup_fn, policy_cb_data);
int delete_refs(const char *msg, struct string_list *refnames,
unsigned int flags)
{
- return refs_delete_refs(get_main_ref_store(), msg, refnames, flags);
+ return refs_delete_refs(get_main_ref_store(the_repository), msg, refnames, flags);
}
int refs_rename_ref(struct ref_store *refs, const char *oldref,
int rename_ref(const char *oldref, const char *newref, const char *logmsg)
{
- return refs_rename_ref(get_main_ref_store(), oldref, newref, logmsg);
+ return refs_rename_ref(get_main_ref_store(the_repository), oldref, newref, logmsg);
}
int refs_copy_existing_ref(struct ref_store *refs, const char *oldref,
int copy_existing_ref(const char *oldref, const char *newref, const char *logmsg)
{
- return refs_copy_existing_ref(get_main_ref_store(), oldref, newref, logmsg);
+ return refs_copy_existing_ref(get_main_ref_store(the_repository), oldref, newref, logmsg);
}