aboutsummaryrefslogtreecommitdiff
path: root/refs.c
diff options
context:
space:
mode:
Diffstat (limited to 'refs.c')
-rw-r--r--refs.c777
1 files changed, 512 insertions, 265 deletions
diff --git a/refs.c b/refs.c
index df75f8e0d..20ba82b43 100644
--- a/refs.c
+++ b/refs.c
@@ -3,6 +3,7 @@
*/
#include "cache.h"
+#include "config.h"
#include "hashmap.h"
#include "lockfile.h"
#include "iterator.h"
@@ -11,6 +12,7 @@
#include "object.h"
#include "tag.h"
#include "submodule.h"
+#include "worktree.h"
/*
* List of all available backends
@@ -172,23 +174,41 @@ int refname_is_safe(const char *refname)
return 1;
}
+/*
+ * Return true if refname, which has the specified oid and flags, can
+ * be resolved to an object in the database. If the referred-to object
+ * does not exist, emit a warning and return false.
+ */
+int ref_resolves_to_object(const char *refname,
+ const struct object_id *oid,
+ unsigned int flags)
+{
+ if (flags & REF_ISBROKEN)
+ return 0;
+ if (!has_sha1_file(oid->hash)) {
+ error("%s does not point to a valid object!", refname);
+ return 0;
+ }
+ return 1;
+}
+
char *refs_resolve_refdup(struct ref_store *refs,
const char *refname, int resolve_flags,
- unsigned char *sha1, int *flags)
+ struct object_id *oid, int *flags)
{
const char *result;
result = refs_resolve_ref_unsafe(refs, refname, resolve_flags,
- sha1, flags);
+ oid, flags);
return xstrdup_or_null(result);
}
char *resolve_refdup(const char *refname, int resolve_flags,
- unsigned char *sha1, int *flags)
+ struct object_id *oid, int *flags)
{
return refs_resolve_refdup(get_main_ref_store(),
refname, resolve_flags,
- sha1, flags);
+ oid, flags);
}
/* The argument to filter_refs */
@@ -199,28 +219,71 @@ struct ref_filter {
};
int refs_read_ref_full(struct ref_store *refs, const char *refname,
- int resolve_flags, unsigned char *sha1, int *flags)
+ int resolve_flags, struct object_id *oid, int *flags)
{
- if (refs_resolve_ref_unsafe(refs, refname, resolve_flags, sha1, flags))
+ if (refs_resolve_ref_unsafe(refs, refname, resolve_flags, oid, flags))
return 0;
return -1;
}
-int read_ref_full(const char *refname, int resolve_flags, unsigned char *sha1, int *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,
- resolve_flags, sha1, flags);
+ resolve_flags, oid, flags);
}
-int read_ref(const char *refname, unsigned char *sha1)
+int read_ref(const char *refname, struct object_id *oid)
{
- return read_ref_full(refname, RESOLVE_REF_READING, sha1, NULL);
+ return read_ref_full(refname, RESOLVE_REF_READING, oid, NULL);
}
int ref_exists(const char *refname)
{
- unsigned char sha1[20];
- return !!resolve_ref_unsafe(refname, RESOLVE_REF_READING, sha1, NULL);
+ return !!resolve_ref_unsafe(refname, RESOLVE_REF_READING, NULL, NULL);
+}
+
+static int match_ref_pattern(const char *refname,
+ const struct string_list_item *item)
+{
+ int matched = 0;
+ if (item->util == NULL) {
+ if (!wildmatch(item->string, refname, 0))
+ matched = 1;
+ } else {
+ const char *rest;
+ if (skip_prefix(refname, item->string, &rest) &&
+ (!*rest || *rest == '/'))
+ matched = 1;
+ }
+ return matched;
+}
+
+int ref_filter_match(const char *refname,
+ const struct string_list *include_patterns,
+ const struct string_list *exclude_patterns)
+{
+ struct string_list_item *item;
+
+ if (exclude_patterns && exclude_patterns->nr) {
+ for_each_string_list_item(item, exclude_patterns) {
+ if (match_ref_pattern(refname, item))
+ return 0;
+ }
+ }
+
+ if (include_patterns && include_patterns->nr) {
+ int found = 0;
+ for_each_string_list_item(item, include_patterns) {
+ if (match_ref_pattern(refname, item)) {
+ found = 1;
+ break;
+ }
+ }
+
+ if (!found)
+ return 0;
+ }
+ return 1;
}
static int filter_refs(const char *refname, const struct object_id *oid,
@@ -228,17 +291,17 @@ static int filter_refs(const char *refname, const struct object_id *oid,
{
struct ref_filter *filter = (struct ref_filter *)data;
- if (wildmatch(filter->pattern, refname, 0, NULL))
+ if (wildmatch(filter->pattern, refname, 0))
return 0;
return filter->fn(refname, oid, flags, filter->cb_data);
}
-enum peel_status peel_object(const unsigned char *name, unsigned char *sha1)
+enum peel_status peel_object(const struct object_id *name, struct object_id *oid)
{
- struct object *o = lookup_unknown_object(name);
+ struct object *o = lookup_unknown_object(name->hash);
if (o->type == OBJ_NONE) {
- int type = sha1_object_info(name, NULL);
+ int type = sha1_object_info(name->hash, NULL);
if (type < 0 || !object_as_type(o, type, 0))
return PEEL_INVALID;
}
@@ -250,7 +313,7 @@ enum peel_status peel_object(const unsigned char *name, unsigned char *sha1)
if (!o)
return PEEL_INVALID;
- hashcpy(sha1, o->oid.hash);
+ oidcpy(oid, &o->oid);
return PEEL_PEELED;
}
@@ -266,12 +329,11 @@ static int warn_if_dangling_symref(const char *refname, const struct object_id *
{
struct warn_if_dangling_data *d = cb_data;
const char *resolves_to;
- struct object_id junk;
if (!(flags & REF_ISSYMREF))
return 0;
- resolves_to = resolve_ref_unsafe(refname, 0, junk.hash, NULL);
+ resolves_to = resolve_ref_unsafe(refname, 0, NULL, NULL);
if (!resolves_to
|| (d->refname
? strcmp(resolves_to, d->refname)
@@ -316,12 +378,6 @@ 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);
}
-int for_each_tag_ref_submodule(const char *submodule, each_ref_fn fn, void *cb_data)
-{
- return refs_for_each_tag_ref(get_submodule_ref_store(submodule),
- fn, cb_data);
-}
-
int refs_for_each_branch_ref(struct ref_store *refs, each_ref_fn fn, void *cb_data)
{
return refs_for_each_ref_in(refs, "refs/heads/", fn, cb_data);
@@ -332,12 +388,6 @@ 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);
}
-int for_each_branch_ref_submodule(const char *submodule, each_ref_fn fn, void *cb_data)
-{
- return refs_for_each_branch_ref(get_submodule_ref_store(submodule),
- fn, cb_data);
-}
-
int refs_for_each_remote_ref(struct ref_store *refs, each_ref_fn fn, void *cb_data)
{
return refs_for_each_ref_in(refs, "refs/remotes/", fn, cb_data);
@@ -348,12 +398,6 @@ 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);
}
-int for_each_remote_ref_submodule(const char *submodule, each_ref_fn fn, void *cb_data)
-{
- return refs_for_each_remote_ref(get_submodule_ref_store(submodule),
- fn, cb_data);
-}
-
int head_ref_namespaced(each_ref_fn fn, void *cb_data)
{
struct strbuf buf = STRBUF_INIT;
@@ -362,13 +406,34 @@ int head_ref_namespaced(each_ref_fn fn, void *cb_data)
int flag;
strbuf_addf(&buf, "%sHEAD", get_git_namespace());
- if (!read_ref_full(buf.buf, RESOLVE_REF_READING, oid.hash, &flag))
+ if (!read_ref_full(buf.buf, RESOLVE_REF_READING, &oid, &flag))
ret = fn(buf.buf, &oid, flag, cb_data);
strbuf_release(&buf);
return ret;
}
+void normalize_glob_ref(struct string_list_item *item, const char *prefix,
+ const char *pattern)
+{
+ struct strbuf normalized_pattern = STRBUF_INIT;
+
+ if (*pattern == '/')
+ BUG("pattern must not start with '/'");
+
+ if (prefix) {
+ strbuf_addstr(&normalized_pattern, prefix);
+ }
+ else if (!starts_with(pattern, "refs/"))
+ strbuf_addstr(&normalized_pattern, "refs/");
+ strbuf_addstr(&normalized_pattern, pattern);
+ strbuf_strip_suffix(&normalized_pattern, "/");
+
+ item->string = strbuf_detach(&normalized_pattern, NULL);
+ item->util = has_glob_specials(pattern) ? NULL : item->string;
+ strbuf_release(&normalized_pattern);
+}
+
int for_each_glob_ref_in(each_ref_fn fn, const char *pattern,
const char *prefix, void *cb_data)
{
@@ -456,15 +521,15 @@ static char *substitute_branch_name(const char **string, int *len)
return NULL;
}
-int dwim_ref(const char *str, int len, unsigned char *sha1, char **ref)
+int dwim_ref(const char *str, int len, struct object_id *oid, char **ref)
{
char *last_branch = substitute_branch_name(&str, &len);
- int refs_found = expand_ref(str, len, sha1, ref);
+ int refs_found = expand_ref(str, len, oid, ref);
free(last_branch);
return refs_found;
}
-int expand_ref(const char *str, int len, unsigned char *sha1, char **ref)
+int expand_ref(const char *str, int len, struct object_id *oid, char **ref)
{
const char **p, *r;
int refs_found = 0;
@@ -472,11 +537,11 @@ int expand_ref(const char *str, int len, unsigned char *sha1, char **ref)
*ref = NULL;
for (p = ref_rev_parse_rules; *p; p++) {
- unsigned char sha1_from_ref[20];
- unsigned char *this_result;
+ struct object_id oid_from_ref;
+ struct object_id *this_result;
int flag;
- this_result = refs_found ? sha1_from_ref : sha1;
+ this_result = refs_found ? &oid_from_ref : oid;
strbuf_reset(&fullref);
strbuf_addf(&fullref, *p, len, str);
r = resolve_ref_unsafe(fullref.buf, RESOLVE_REF_READING,
@@ -496,7 +561,7 @@ int expand_ref(const char *str, int len, unsigned char *sha1, char **ref)
return refs_found;
}
-int dwim_log(const char *str, int len, unsigned char *sha1, char **log)
+int dwim_log(const char *str, int len, struct object_id *oid, char **log)
{
char *last_branch = substitute_branch_name(&str, &len);
const char **p;
@@ -505,13 +570,13 @@ int dwim_log(const char *str, int len, unsigned char *sha1, char **log)
*log = NULL;
for (p = ref_rev_parse_rules; *p; p++) {
- unsigned char hash[20];
+ struct object_id hash;
const char *ref, *it;
strbuf_reset(&path);
strbuf_addf(&path, *p, len, str);
ref = resolve_ref_unsafe(path.buf, RESOLVE_REF_READING,
- hash, NULL);
+ &hash, NULL);
if (!ref)
continue;
if (reflog_exists(path.buf))
@@ -522,7 +587,7 @@ int dwim_log(const char *str, int len, unsigned char *sha1, char **log)
continue;
if (!logs_found++) {
*log = xstrdup(it);
- hashcpy(sha1, hash);
+ oidcpy(oid, &hash);
}
if (!warn_ambiguous_refs)
break;
@@ -559,8 +624,23 @@ enum ref_type ref_type(const char *refname)
return REF_TYPE_NORMAL;
}
-static int write_pseudoref(const char *pseudoref, const unsigned char *sha1,
- const unsigned char *old_sha1, struct strbuf *err)
+long get_files_ref_lock_timeout_ms(void)
+{
+ static int configured = 0;
+
+ /* The default timeout is 100 ms: */
+ static int timeout_ms = 100;
+
+ if (!configured) {
+ git_config_get_int("core.filesreflocktimeout", &timeout_ms);
+ configured = 1;
+ }
+
+ return timeout_ms;
+}
+
+static int write_pseudoref(const char *pseudoref, const struct object_id *oid,
+ const struct object_id *old_oid, struct strbuf *err)
{
const char *filename;
int fd;
@@ -568,29 +648,34 @@ static int write_pseudoref(const char *pseudoref, const unsigned char *sha1,
struct strbuf buf = STRBUF_INIT;
int ret = -1;
- strbuf_addf(&buf, "%s\n", sha1_to_hex(sha1));
+ if (!oid)
+ return 0;
+
+ strbuf_addf(&buf, "%s\n", oid_to_hex(oid));
filename = git_path("%s", pseudoref);
- fd = hold_lock_file_for_update(&lock, filename, LOCK_DIE_ON_ERROR);
+ fd = hold_lock_file_for_update_timeout(&lock, filename,
+ LOCK_DIE_ON_ERROR,
+ get_files_ref_lock_timeout_ms());
if (fd < 0) {
strbuf_addf(err, "could not open '%s' for writing: %s",
filename, strerror(errno));
- return -1;
+ goto done;
}
- if (old_sha1) {
- unsigned char actual_old_sha1[20];
+ if (old_oid) {
+ struct object_id actual_old_oid;
- if (read_ref(pseudoref, actual_old_sha1))
+ if (read_ref(pseudoref, &actual_old_oid))
die("could not read ref '%s'", pseudoref);
- if (hashcmp(actual_old_sha1, old_sha1)) {
+ if (oidcmp(&actual_old_oid, old_oid)) {
strbuf_addf(err, "unexpected sha1 when writing '%s'", pseudoref);
rollback_lock_file(&lock);
goto done;
}
}
- if (write_in_full(fd, buf.buf, buf.len) != buf.len) {
+ if (write_in_full(fd, buf.buf, buf.len) < 0) {
strbuf_addf(err, "could not write to '%s'", filename);
rollback_lock_file(&lock);
goto done;
@@ -603,24 +688,25 @@ done:
return ret;
}
-static int delete_pseudoref(const char *pseudoref, const unsigned char *old_sha1)
+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_sha1 && !is_null_sha1(old_sha1)) {
+ if (old_oid && !is_null_oid(old_oid)) {
int fd;
- unsigned char actual_old_sha1[20];
+ struct object_id actual_old_oid;
- fd = hold_lock_file_for_update(&lock, filename,
- LOCK_DIE_ON_ERROR);
+ fd = hold_lock_file_for_update_timeout(
+ &lock, filename, LOCK_DIE_ON_ERROR,
+ get_files_ref_lock_timeout_ms());
if (fd < 0)
die_errno(_("Could not open '%s' for writing"), filename);
- if (read_ref(pseudoref, actual_old_sha1))
+ if (read_ref(pseudoref, &actual_old_oid))
die("could not read ref '%s'", pseudoref);
- if (hashcmp(actual_old_sha1, old_sha1)) {
+ if (oidcmp(&actual_old_oid, old_oid)) {
warning("Unexpected sha1 when deleting %s", pseudoref);
rollback_lock_file(&lock);
return -1;
@@ -637,7 +723,7 @@ static int delete_pseudoref(const char *pseudoref, const unsigned char *old_sha1
int refs_delete_ref(struct ref_store *refs, const char *msg,
const char *refname,
- const unsigned char *old_sha1,
+ const struct object_id *old_oid,
unsigned int flags)
{
struct ref_transaction *transaction;
@@ -645,12 +731,12 @@ int refs_delete_ref(struct ref_store *refs, const char *msg,
if (ref_type(refname) == REF_TYPE_PSEUDOREF) {
assert(refs == get_main_ref_store());
- return delete_pseudoref(refname, old_sha1);
+ return delete_pseudoref(refname, old_oid);
}
transaction = ref_store_transaction_begin(refs, &err);
if (!transaction ||
- ref_transaction_delete(transaction, refname, old_sha1,
+ ref_transaction_delete(transaction, refname, old_oid,
flags, msg, &err) ||
ref_transaction_commit(transaction, &err)) {
error("%s", err.buf);
@@ -664,10 +750,10 @@ int refs_delete_ref(struct ref_store *refs, const char *msg,
}
int delete_ref(const char *msg, const char *refname,
- const unsigned char *old_sha1, unsigned int flags)
+ const struct object_id *old_oid, unsigned int flags)
{
return refs_delete_ref(get_main_ref_store(), msg, refname,
- old_sha1, flags);
+ old_oid, flags);
}
int copy_reflog_msg(char *buf, const char *msg)
@@ -713,24 +799,24 @@ int is_branch(const char *refname)
struct read_ref_at_cb {
const char *refname;
- unsigned long at_time;
+ timestamp_t at_time;
int cnt;
int reccnt;
- unsigned char *sha1;
+ struct object_id *oid;
int found_it;
- unsigned char osha1[20];
- unsigned char nsha1[20];
+ struct object_id ooid;
+ struct object_id noid;
int tz;
- unsigned long date;
+ timestamp_t date;
char **msg;
- unsigned long *cutoff_time;
+ timestamp_t *cutoff_time;
int *cutoff_tz;
int *cutoff_cnt;
};
static int read_ref_at_ent(struct object_id *ooid, struct object_id *noid,
- const char *email, unsigned long timestamp, int tz,
+ const char *email, timestamp_t timestamp, int tz,
const char *message, void *cb_data)
{
struct read_ref_at_cb *cb = cb_data;
@@ -749,35 +835,35 @@ static int read_ref_at_ent(struct object_id *ooid, struct object_id *noid,
if (cb->cutoff_cnt)
*cb->cutoff_cnt = cb->reccnt - 1;
/*
- * we have not yet updated cb->[n|o]sha1 so they still
+ * we have not yet updated cb->[n|o]oid so they still
* hold the values for the previous record.
*/
- if (!is_null_sha1(cb->osha1)) {
- hashcpy(cb->sha1, noid->hash);
- if (hashcmp(cb->osha1, noid->hash))
+ if (!is_null_oid(&cb->ooid)) {
+ oidcpy(cb->oid, noid);
+ if (oidcmp(&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)
- hashcpy(cb->sha1, noid->hash);
- else if (hashcmp(noid->hash, cb->sha1))
+ oidcpy(cb->oid, noid);
+ else if (oidcmp(noid, cb->oid))
warning("Log for ref %s unexpectedly ended on %s.",
cb->refname, show_date(cb->date, cb->tz,
DATE_MODE(RFC2822)));
- hashcpy(cb->osha1, ooid->hash);
- hashcpy(cb->nsha1, noid->hash);
+ oidcpy(&cb->ooid, ooid);
+ oidcpy(&cb->noid, noid);
cb->found_it = 1;
return 1;
}
- hashcpy(cb->osha1, ooid->hash);
- hashcpy(cb->nsha1, noid->hash);
+ oidcpy(&cb->ooid, ooid);
+ oidcpy(&cb->noid, noid);
if (cb->cnt > 0)
cb->cnt--;
return 0;
}
static int read_ref_at_ent_oldest(struct object_id *ooid, struct object_id *noid,
- const char *email, unsigned long timestamp,
+ const char *email, timestamp_t timestamp,
int tz, const char *message, void *cb_data)
{
struct read_ref_at_cb *cb = cb_data;
@@ -790,16 +876,16 @@ static int read_ref_at_ent_oldest(struct object_id *ooid, struct object_id *noid
*cb->cutoff_tz = tz;
if (cb->cutoff_cnt)
*cb->cutoff_cnt = cb->reccnt;
- hashcpy(cb->sha1, ooid->hash);
- if (is_null_sha1(cb->sha1))
- hashcpy(cb->sha1, noid->hash);
+ oidcpy(cb->oid, ooid);
+ if (is_null_oid(cb->oid))
+ oidcpy(cb->oid, noid);
/* We just want the first entry */
return 1;
}
-int read_ref_at(const char *refname, unsigned int flags, unsigned long at_time, int cnt,
- unsigned char *sha1, char **msg,
- unsigned long *cutoff_time, int *cutoff_tz, int *cutoff_cnt)
+int read_ref_at(const char *refname, unsigned int flags, timestamp_t at_time, int cnt,
+ struct object_id *oid, char **msg,
+ timestamp_t *cutoff_time, int *cutoff_tz, int *cutoff_cnt)
{
struct read_ref_at_cb cb;
@@ -811,12 +897,12 @@ int read_ref_at(const char *refname, unsigned int flags, unsigned long at_time,
cb.cutoff_time = cutoff_time;
cb.cutoff_tz = cutoff_tz;
cb.cutoff_cnt = cutoff_cnt;
- cb.sha1 = sha1;
+ cb.oid = oid;
for_each_reflog_ent_reverse(refname, read_ref_at_ent, &cb);
if (!cb.reccnt) {
- if (flags & GET_SHA1_QUIETLY)
+ if (flags & GET_OID_QUIETLY)
exit(128);
else
die("Log for %s is empty.", refname);
@@ -847,11 +933,24 @@ struct ref_transaction *ref_transaction_begin(struct strbuf *err)
void ref_transaction_free(struct ref_transaction *transaction)
{
- int i;
+ size_t i;
if (!transaction)
return;
+ switch (transaction->state) {
+ case REF_TRANSACTION_OPEN:
+ case REF_TRANSACTION_CLOSED:
+ /* OK */
+ break;
+ case REF_TRANSACTION_PREPARED:
+ die("BUG: free called on a prepared reference transaction");
+ break;
+ default:
+ die("BUG: unexpected reference transaction state");
+ break;
+ }
+
for (i = 0; i < transaction->nr; i++) {
free(transaction->updates[i]->msg);
free(transaction->updates[i]);
@@ -863,8 +962,8 @@ void ref_transaction_free(struct ref_transaction *transaction)
struct ref_update *ref_transaction_add_update(
struct ref_transaction *transaction,
const char *refname, unsigned int flags,
- const unsigned char *new_sha1,
- const unsigned char *old_sha1,
+ const struct object_id *new_oid,
+ const struct object_id *old_oid,
const char *msg)
{
struct ref_update *update;
@@ -872,9 +971,6 @@ struct ref_update *ref_transaction_add_update(
if (transaction->state != REF_TRANSACTION_OPEN)
die("BUG: update called for transaction that is not open");
- if ((flags & REF_ISPRUNING) && !(flags & REF_NODEREF))
- die("BUG: REF_ISPRUNING set without REF_NODEREF");
-
FLEX_ALLOC_STR(update, refname, refname);
ALLOC_GROW(transaction->updates, transaction->nr + 1, transaction->alloc);
transaction->updates[transaction->nr++] = update;
@@ -882,23 +978,23 @@ struct ref_update *ref_transaction_add_update(
update->flags = flags;
if (flags & REF_HAVE_NEW)
- hashcpy(update->new_sha1, new_sha1);
+ oidcpy(&update->new_oid, new_oid);
if (flags & REF_HAVE_OLD)
- hashcpy(update->old_sha1, old_sha1);
+ oidcpy(&update->old_oid, old_oid);
update->msg = xstrdup_or_null(msg);
return update;
}
int ref_transaction_update(struct ref_transaction *transaction,
const char *refname,
- const unsigned char *new_sha1,
- const unsigned char *old_sha1,
+ const struct object_id *new_oid,
+ const struct object_id *old_oid,
unsigned int flags, const char *msg,
struct strbuf *err)
{
assert(err);
- if ((new_sha1 && !is_null_sha1(new_sha1)) ?
+ 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'",
@@ -906,62 +1002,57 @@ int ref_transaction_update(struct ref_transaction *transaction,
return -1;
}
- flags |= (new_sha1 ? REF_HAVE_NEW : 0) | (old_sha1 ? REF_HAVE_OLD : 0);
+ if (flags & ~REF_TRANSACTION_UPDATE_ALLOWED_FLAGS)
+ BUG("illegal flags 0x%x passed to ref_transaction_update()", flags);
+
+ flags |= (new_oid ? REF_HAVE_NEW : 0) | (old_oid ? REF_HAVE_OLD : 0);
ref_transaction_add_update(transaction, refname, flags,
- new_sha1, old_sha1, msg);
+ new_oid, old_oid, msg);
return 0;
}
int ref_transaction_create(struct ref_transaction *transaction,
const char *refname,
- const unsigned char *new_sha1,
+ const struct object_id *new_oid,
unsigned int flags, const char *msg,
struct strbuf *err)
{
- if (!new_sha1 || is_null_sha1(new_sha1))
- die("BUG: create called without valid new_sha1");
- return ref_transaction_update(transaction, refname, new_sha1,
- null_sha1, flags, msg, err);
+ if (!new_oid || is_null_oid(new_oid))
+ die("BUG: create called without valid new_oid");
+ return ref_transaction_update(transaction, refname, new_oid,
+ &null_oid, flags, msg, err);
}
int ref_transaction_delete(struct ref_transaction *transaction,
const char *refname,
- const unsigned char *old_sha1,
+ const struct object_id *old_oid,
unsigned int flags, const char *msg,
struct strbuf *err)
{
- if (old_sha1 && is_null_sha1(old_sha1))
- die("BUG: delete called with old_sha1 set to zeros");
+ if (old_oid && is_null_oid(old_oid))
+ die("BUG: delete called with old_oid set to zeros");
return ref_transaction_update(transaction, refname,
- null_sha1, old_sha1,
+ &null_oid, old_oid,
flags, msg, err);
}
int ref_transaction_verify(struct ref_transaction *transaction,
const char *refname,
- const unsigned char *old_sha1,
+ const struct object_id *old_oid,
unsigned int flags,
struct strbuf *err)
{
- if (!old_sha1)
- die("BUG: verify called with old_sha1 set to NULL");
+ if (!old_oid)
+ die("BUG: verify called with old_oid set to NULL");
return ref_transaction_update(transaction, refname,
- NULL, old_sha1,
+ NULL, old_oid,
flags, NULL, err);
}
-int update_ref_oid(const char *msg, const char *refname,
- const struct object_id *new_oid, const struct object_id *old_oid,
- unsigned int flags, enum action_on_err onerr)
-{
- return update_ref(msg, refname, new_oid ? new_oid->hash : NULL,
- old_oid ? old_oid->hash : NULL, flags, onerr);
-}
-
int refs_update_ref(struct ref_store *refs, const char *msg,
- const char *refname, const unsigned char *new_sha1,
- const unsigned char *old_sha1, unsigned int flags,
+ const char *refname, const struct object_id *new_oid,
+ const struct object_id *old_oid, unsigned int flags,
enum action_on_err onerr)
{
struct ref_transaction *t = NULL;
@@ -970,11 +1061,11 @@ int refs_update_ref(struct ref_store *refs, const char *msg,
if (ref_type(refname) == REF_TYPE_PSEUDOREF) {
assert(refs == get_main_ref_store());
- ret = write_pseudoref(refname, new_sha1, old_sha1, &err);
+ ret = write_pseudoref(refname, new_oid, old_oid, &err);
} else {
t = ref_store_transaction_begin(refs, &err);
if (!t ||
- ref_transaction_update(t, refname, new_sha1, old_sha1,
+ ref_transaction_update(t, refname, new_oid, old_oid,
flags, msg, &err) ||
ref_transaction_commit(t, &err)) {
ret = 1;
@@ -1004,12 +1095,12 @@ int refs_update_ref(struct ref_store *refs, const char *msg,
}
int update_ref(const char *msg, const char *refname,
- const unsigned char *new_sha1,
- const unsigned char *old_sha1,
+ const struct object_id *new_oid,
+ 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_sha1,
- old_sha1, flags, onerr);
+ return refs_update_ref(get_main_ref_store(), msg, refname, new_oid,
+ old_oid, flags, onerr);
}
char *shorten_unambiguous_ref(const char *refname, int strict)
@@ -1145,7 +1236,7 @@ int ref_is_hidden(const char *refname, const char *refname_full)
const char *match = hide_refs->items[i].string;
const char *subject;
int neg = 0;
- int len;
+ const char *p;
if (*match == '!') {
neg = 1;
@@ -1160,10 +1251,9 @@ int ref_is_hidden(const char *refname, const char *refname_full)
}
/* refname can be NULL when namespaces are used. */
- if (!subject || !starts_with(subject, match))
- continue;
- len = strlen(match);
- if (!subject[len] || subject[len] == '/')
+ if (subject &&
+ skip_prefix(subject, match, &p) &&
+ (!*p || *p == '/'))
return !neg;
}
return 0;
@@ -1216,19 +1306,13 @@ int refs_rename_ref_available(struct ref_store *refs,
return ok;
}
-int head_ref_submodule(const char *submodule, each_ref_fn fn, void *cb_data)
+int refs_head_ref(struct ref_store *refs, each_ref_fn fn, void *cb_data)
{
struct object_id oid;
int flag;
- if (submodule) {
- if (resolve_gitlink_ref(submodule, "HEAD", oid.hash) == 0)
- return fn("HEAD", &oid, 0, cb_data);
-
- return 0;
- }
-
- if (!read_ref_full("HEAD", RESOLVE_REF_READING, oid.hash, &flag))
+ if (!refs_read_ref_full(refs, "HEAD", RESOLVE_REF_READING,
+ &oid, &flag))
return fn("HEAD", &oid, flag, cb_data);
return 0;
@@ -1236,7 +1320,7 @@ int head_ref_submodule(const char *submodule, each_ref_fn fn, void *cb_data)
int head_ref(each_ref_fn fn, void *cb_data)
{
- return head_ref_submodule(NULL, fn, cb_data);
+ return refs_head_ref(get_main_ref_store(), fn, cb_data);
}
struct ref_iterator *refs_ref_iterator_begin(
@@ -1245,8 +1329,23 @@ struct ref_iterator *refs_ref_iterator_begin(
{
struct ref_iterator *iter;
+ if (ref_paranoia < 0)
+ ref_paranoia = git_env_bool("GIT_REF_PARANOIA", 0);
+ if (ref_paranoia)
+ flags |= DO_FOR_EACH_INCLUDE_BROKEN;
+
iter = refs->be->iterator_begin(refs, prefix, flags);
- iter = prefix_ref_iterator_begin(iter, prefix, trim);
+
+ /*
+ * `iterator_begin()` already takes care of prefix, but we
+ * might need to do some trimming:
+ */
+ if (trim)
+ iter = prefix_ref_iterator_begin(iter, "", trim);
+
+ /* Sanity check for subclasses: */
+ if (!iter->ordered)
+ BUG("reference iterator is not ordered");
return iter;
}
@@ -1283,11 +1382,6 @@ int for_each_ref(each_ref_fn fn, void *cb_data)
return refs_for_each_ref(get_main_ref_store(), fn, cb_data);
}
-int for_each_ref_submodule(const char *submodule, each_ref_fn fn, void *cb_data)
-{
- return refs_for_each_ref(get_submodule_ref_store(submodule), fn, cb_data);
-}
-
int refs_for_each_ref_in(struct ref_store *refs, const char *prefix,
each_ref_fn fn, void *cb_data)
{
@@ -1309,11 +1403,15 @@ int for_each_fullref_in(const char *prefix, each_ref_fn fn, void *cb_data, unsig
prefix, fn, 0, flag, cb_data);
}
-int for_each_ref_in_submodule(const char *submodule, const char *prefix,
- each_ref_fn fn, void *cb_data)
+int refs_for_each_fullref_in(struct ref_store *refs, const char *prefix,
+ each_ref_fn fn, void *cb_data,
+ unsigned int broken)
{
- return refs_for_each_ref_in(get_submodule_ref_store(submodule),
- prefix, fn, cb_data);
+ unsigned int flag = 0;
+
+ if (broken)
+ flag = DO_FOR_EACH_INCLUDE_BROKEN;
+ return do_for_each_ref(refs, prefix, fn, 0, flag, cb_data);
}
int for_each_replace_ref(each_ref_fn fn, void *cb_data)
@@ -1321,7 +1419,7 @@ int for_each_replace_ref(each_ref_fn fn, void *cb_data)
return do_for_each_ref(get_main_ref_store(),
git_replace_ref_base, fn,
strlen(git_replace_ref_base),
- 0, cb_data);
+ DO_FOR_EACH_INCLUDE_BROKEN, cb_data);
}
int for_each_namespaced_ref(each_ref_fn fn, void *cb_data)
@@ -1347,22 +1445,25 @@ int for_each_rawref(each_ref_fn fn, void *cb_data)
}
int refs_read_raw_ref(struct ref_store *ref_store,
- const char *refname, unsigned char *sha1,
+ const char *refname, struct object_id *oid,
struct strbuf *referent, unsigned int *type)
{
- return ref_store->be->read_raw_ref(ref_store, refname, sha1, referent, type);
+ return ref_store->be->read_raw_ref(ref_store, refname, oid, referent, type);
}
/* This function needs to return a meaningful errno on failure */
const char *refs_resolve_ref_unsafe(struct ref_store *refs,
const char *refname,
int resolve_flags,
- unsigned char *sha1, int *flags)
+ struct object_id *oid, int *flags)
{
static struct strbuf sb_refname = STRBUF_INIT;
+ struct object_id unused_oid;
int unused_flags;
int symref_count;
+ if (!oid)
+ oid = &unused_oid;
if (!flags)
flags = &unused_flags;
@@ -1390,11 +1491,24 @@ const char *refs_resolve_ref_unsafe(struct ref_store *refs,
unsigned int read_flags = 0;
if (refs_read_raw_ref(refs, refname,
- sha1, &sb_refname, &read_flags)) {
+ oid, &sb_refname, &read_flags)) {
*flags |= read_flags;
- if (errno != ENOENT || (resolve_flags & RESOLVE_REF_READING))
+
+ /* In reading mode, refs must eventually resolve */
+ if (resolve_flags & RESOLVE_REF_READING)
+ return NULL;
+
+ /*
+ * Otherwise a missing ref is OK. But the files backend
+ * may show errors besides ENOENT if there are
+ * similarly-named refs.
+ */
+ if (errno != ENOENT &&
+ errno != EISDIR &&
+ errno != ENOTDIR)
return NULL;
- hashclr(sha1);
+
+ oidclr(oid);
if (*flags & REF_BAD_NAME)
*flags |= REF_ISBROKEN;
return refname;
@@ -1404,7 +1518,7 @@ const char *refs_resolve_ref_unsafe(struct ref_store *refs,
if (!(read_flags & REF_ISSYMREF)) {
if (*flags & REF_BAD_NAME) {
- hashclr(sha1);
+ oidclr(oid);
*flags |= REF_ISBROKEN;
}
return refname;
@@ -1412,7 +1526,7 @@ const char *refs_resolve_ref_unsafe(struct ref_store *refs,
refname = sb_refname.buf;
if (resolve_flags & RESOLVE_REF_NO_RECURSE) {
- hashclr(sha1);
+ oidclr(oid);
return refname;
}
if (check_refname_format(refname, REFNAME_ALLOW_ONELEVEL)) {
@@ -1439,70 +1553,56 @@ int refs_init_db(struct strbuf *err)
}
const char *resolve_ref_unsafe(const char *refname, int resolve_flags,
- unsigned char *sha1, int *flags)
+ struct object_id *oid, int *flags)
{
return refs_resolve_ref_unsafe(get_main_ref_store(), refname,
- resolve_flags, sha1, flags);
+ resolve_flags, oid, flags);
}
int resolve_gitlink_ref(const char *submodule, const char *refname,
- unsigned char *sha1)
+ struct object_id *oid)
{
- size_t len = strlen(submodule);
struct ref_store *refs;
int flags;
- while (len && submodule[len - 1] == '/')
- len--;
-
- if (!len)
- return -1;
-
- if (submodule[len]) {
- /* We need to strip off one or more trailing slashes */
- char *stripped = xmemdupz(submodule, len);
-
- refs = get_submodule_ref_store(stripped);
- free(stripped);
- } else {
- refs = get_submodule_ref_store(submodule);
- }
+ refs = get_submodule_ref_store(submodule);
if (!refs)
return -1;
- if (!refs_resolve_ref_unsafe(refs, refname, 0, sha1, &flags) ||
- is_null_sha1(sha1))
+ if (!refs_resolve_ref_unsafe(refs, refname, 0, oid, &flags) ||
+ is_null_oid(oid))
return -1;
return 0;
}
-struct submodule_hash_entry
+struct ref_store_hash_entry
{
struct hashmap_entry ent; /* must be the first member! */
struct ref_store *refs;
- /* NUL-terminated name of submodule: */
- char submodule[FLEX_ARRAY];
+ /* NUL-terminated identifier of the ref store: */
+ char name[FLEX_ARRAY];
};
-static int submodule_hash_cmp(const void *entry, const void *entry_or_key,
+static int ref_store_hash_cmp(const void *unused_cmp_data,
+ const void *entry, const void *entry_or_key,
const void *keydata)
{
- const struct submodule_hash_entry *e1 = entry, *e2 = entry_or_key;
- const char *submodule = keydata ? keydata : e2->submodule;
+ const struct ref_store_hash_entry *e1 = entry, *e2 = entry_or_key;
+ const char *name = keydata ? keydata : e2->name;
- return strcmp(e1->submodule, submodule);
+ return strcmp(e1->name, name);
}
-static struct submodule_hash_entry *alloc_submodule_hash_entry(
- const char *submodule, struct ref_store *refs)
+static struct ref_store_hash_entry *alloc_ref_store_hash_entry(
+ const char *name, struct ref_store *refs)
{
- struct submodule_hash_entry *entry;
+ struct ref_store_hash_entry *entry;
- FLEX_ALLOC_STR(entry, submodule, submodule);
- hashmap_entry_init(entry, strhash(submodule));
+ FLEX_ALLOC_STR(entry, name, name);
+ hashmap_entry_init(entry, strhash(name));
entry->refs = refs;
return entry;
}
@@ -1513,20 +1613,23 @@ static struct ref_store *main_ref_store;
/* A hashmap of ref_stores, stored by submodule name: */
static struct hashmap submodule_ref_stores;
+/* A hashmap of ref_stores, stored by worktree id: */
+static struct hashmap worktree_ref_stores;
+
/*
- * Return the ref_store instance for the specified submodule. If that
- * ref_store hasn't been initialized yet, return NULL.
+ * Look up a ref store by name. If that ref_store hasn't been
+ * registered yet, return NULL.
*/
-static struct ref_store *lookup_submodule_ref_store(const char *submodule)
+static struct ref_store *lookup_ref_store_map(struct hashmap *map,
+ const char *name)
{
- struct submodule_hash_entry *entry;
+ struct ref_store_hash_entry *entry;
- if (!submodule_ref_stores.tablesize)
+ if (!map->tablesize)
/* It's initialized on demand in register_ref_store(). */
return NULL;
- entry = hashmap_get_from_hash(&submodule_ref_stores,
- strhash(submodule), submodule);
+ entry = hashmap_get_from_hash(map, strhash(name), name);
return entry ? entry->refs : NULL;
}
@@ -1553,67 +1656,93 @@ struct ref_store *get_main_ref_store(void)
if (main_ref_store)
return main_ref_store;
- main_ref_store = ref_store_init(get_git_dir(),
- (REF_STORE_READ |
- REF_STORE_WRITE |
- REF_STORE_ODB |
- REF_STORE_MAIN));
+ main_ref_store = ref_store_init(get_git_dir(), REF_STORE_ALL_CAPS);
return main_ref_store;
}
/*
- * Register the specified ref_store to be the one that should be used
- * for submodule. It is a fatal error to call this function twice for
- * the same submodule.
+ * Associate a ref store with a name. It is a fatal error to call this
+ * function twice for the same name.
*/
-static void register_submodule_ref_store(struct ref_store *refs,
- const char *submodule)
+static void register_ref_store_map(struct hashmap *map,
+ const char *type,
+ struct ref_store *refs,
+ const char *name)
{
- if (!submodule_ref_stores.tablesize)
- hashmap_init(&submodule_ref_stores, submodule_hash_cmp, 0);
+ if (!map->tablesize)
+ hashmap_init(map, ref_store_hash_cmp, NULL, 0);
- if (hashmap_put(&submodule_ref_stores,
- alloc_submodule_hash_entry(submodule, refs)))
- die("BUG: ref_store for submodule '%s' initialized twice",
- submodule);
+ if (hashmap_put(map, alloc_ref_store_hash_entry(name, refs)))
+ die("BUG: %s ref_store '%s' initialized twice", type, name);
}
struct ref_store *get_submodule_ref_store(const char *submodule)
{
struct strbuf submodule_sb = STRBUF_INIT;
struct ref_store *refs;
- int ret;
+ char *to_free = NULL;
+ size_t len;
- if (!submodule || !*submodule) {
- /*
- * FIXME: This case is ideally not allowed. But that
- * can't happen until we clean up all the callers.
- */
- return get_main_ref_store();
- }
+ if (!submodule)
+ return NULL;
+
+ len = strlen(submodule);
+ while (len && is_dir_sep(submodule[len - 1]))
+ len--;
+ if (!len)
+ return NULL;
- refs = lookup_submodule_ref_store(submodule);
+ if (submodule[len])
+ /* We need to strip off one or more trailing slashes */
+ submodule = to_free = xmemdupz(submodule, len);
+
+ refs = lookup_ref_store_map(&submodule_ref_stores, submodule);
if (refs)
- return refs;
+ goto done;
strbuf_addstr(&submodule_sb, submodule);
- ret = is_nonbare_repository_dir(&submodule_sb);
- strbuf_release(&submodule_sb);
- if (!ret)
- return NULL;
+ if (!is_nonbare_repository_dir(&submodule_sb))
+ goto done;
- ret = submodule_to_gitdir(&submodule_sb, submodule);
- if (ret) {
- strbuf_release(&submodule_sb);
- return NULL;
- }
+ if (submodule_to_gitdir(&submodule_sb, submodule))
+ goto done;
/* assume that add_submodule_odb() has been called */
refs = ref_store_init(submodule_sb.buf,
REF_STORE_READ | REF_STORE_ODB);
- register_submodule_ref_store(refs, submodule);
+ register_ref_store_map(&submodule_ref_stores, "submodule",
+ refs, submodule);
+done:
strbuf_release(&submodule_sb);
+ free(to_free);
+
+ return refs;
+}
+
+struct ref_store *get_worktree_ref_store(const struct worktree *wt)
+{
+ struct ref_store *refs;
+ const char *id;
+
+ if (wt->is_current)
+ return get_main_ref_store();
+
+ id = wt->id ? wt->id : "/";
+ refs = lookup_ref_store_map(&worktree_ref_stores, id);
+ if (refs)
+ return refs;
+
+ if (wt->id)
+ refs = ref_store_init(git_common_path("worktrees/%s", wt->id),
+ REF_STORE_ALL_CAPS);
+ else
+ refs = ref_store_init(get_git_common_dir(),
+ REF_STORE_ALL_CAPS);
+
+ if (refs)
+ register_ref_store_map(&worktree_ref_stores, "worktree",
+ refs, id);
return refs;
}
@@ -1630,14 +1759,30 @@ int refs_pack_refs(struct ref_store *refs, unsigned int flags)
}
int refs_peel_ref(struct ref_store *refs, const char *refname,
- unsigned char *sha1)
+ struct object_id *oid)
{
- return refs->be->peel_ref(refs, refname, sha1);
+ int flag;
+ struct object_id base;
+
+ if (current_ref_iter && current_ref_iter->refname == refname) {
+ struct object_id peeled;
+
+ if (ref_iterator_peel(current_ref_iter, &peeled))
+ return -1;
+ oidcpy(oid, &peeled);
+ return 0;
+ }
+
+ if (refs_read_ref_full(refs, refname,
+ RESOLVE_REF_READING, &base, &flag))
+ return -1;
+
+ return peel_object(&base, oid);
}
-int peel_ref(const char *refname, unsigned char *sha1)
+int peel_ref(const char *refname, struct object_id *oid)
{
- return refs_peel_ref(get_main_ref_store(), refname, sha1);
+ return refs_peel_ref(get_main_ref_store(), refname, oid);
}
int refs_create_symref(struct ref_store *refs,
@@ -1657,18 +1802,108 @@ int create_symref(const char *ref_target, const char *refs_heads_master,
refs_heads_master, logmsg);
}
-int ref_transaction_commit(struct ref_transaction *transaction,
- struct strbuf *err)
+int ref_update_reject_duplicates(struct string_list *refnames,
+ struct strbuf *err)
+{
+ size_t i, n = refnames->nr;
+
+ assert(err);
+
+ for (i = 1; i < n; i++) {
+ int cmp = strcmp(refnames->items[i - 1].string,
+ refnames->items[i].string);
+
+ if (!cmp) {
+ strbuf_addf(err,
+ "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");
+ }
+ }
+ return 0;
+}
+
+int ref_transaction_prepare(struct ref_transaction *transaction,
+ struct strbuf *err)
{
struct ref_store *refs = transaction->ref_store;
+ switch (transaction->state) {
+ case REF_TRANSACTION_OPEN:
+ /* Good. */
+ break;
+ case REF_TRANSACTION_PREPARED:
+ die("BUG: prepare called twice on reference transaction");
+ break;
+ case REF_TRANSACTION_CLOSED:
+ die("BUG: prepare called on a closed reference transaction");
+ break;
+ default:
+ die("BUG: unexpected reference transaction state");
+ break;
+ }
+
if (getenv(GIT_QUARANTINE_ENVIRONMENT)) {
strbuf_addstr(err,
_("ref updates forbidden inside quarantine environment"));
return -1;
}
- return refs->be->transaction_commit(refs, transaction, err);
+ return refs->be->transaction_prepare(refs, transaction, err);
+}
+
+int ref_transaction_abort(struct ref_transaction *transaction,
+ struct strbuf *err)
+{
+ struct ref_store *refs = transaction->ref_store;
+ int ret = 0;
+
+ switch (transaction->state) {
+ case REF_TRANSACTION_OPEN:
+ /* No need to abort explicitly. */
+ break;
+ case REF_TRANSACTION_PREPARED:
+ ret = refs->be->transaction_abort(refs, transaction, err);
+ break;
+ case REF_TRANSACTION_CLOSED:
+ die("BUG: abort called on a closed reference transaction");
+ break;
+ default:
+ die("BUG: unexpected reference transaction state");
+ break;
+ }
+
+ ref_transaction_free(transaction);
+ return ret;
+}
+
+int ref_transaction_commit(struct ref_transaction *transaction,
+ struct strbuf *err)
+{
+ struct ref_store *refs = transaction->ref_store;
+ int ret;
+
+ switch (transaction->state) {
+ case REF_TRANSACTION_OPEN:
+ /* Need to prepare first. */
+ ret = ref_transaction_prepare(transaction, err);
+ if (ret)
+ return ret;
+ break;
+ case REF_TRANSACTION_PREPARED:
+ /* Fall through to finish. */
+ break;
+ case REF_TRANSACTION_CLOSED:
+ die("BUG: commit called on a closed reference transaction");
+ break;
+ default:
+ die("BUG: unexpected reference transaction state");
+ break;
+ }
+
+ return refs->be->transaction_finish(refs, transaction, err);
}
int refs_verify_refname_available(struct ref_store *refs,
@@ -1707,7 +1942,7 @@ 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.hash, &referent, &type)) {
+ if (!refs_read_raw_ref(refs, dirname.buf, &oid, &referent, &type)) {
strbuf_addf(err, "'%s' exists; cannot create '%s'",
dirname.buf, refname);
goto cleanup;
@@ -1837,19 +2072,19 @@ int delete_reflog(const char *refname)
}
int refs_reflog_expire(struct ref_store *refs,
- const char *refname, const unsigned char *sha1,
+ const char *refname, const struct object_id *oid,
unsigned int flags,
reflog_expiry_prepare_fn prepare_fn,
reflog_expiry_should_prune_fn should_prune_fn,
reflog_expiry_cleanup_fn cleanup_fn,
void *policy_cb_data)
{
- return refs->be->reflog_expire(refs, refname, sha1, flags,
+ return refs->be->reflog_expire(refs, refname, oid, flags,
prepare_fn, should_prune_fn,
cleanup_fn, policy_cb_data);
}
-int reflog_expire(const char *refname, const unsigned char *sha1,
+int reflog_expire(const char *refname, const struct object_id *oid,
unsigned int flags,
reflog_expiry_prepare_fn prepare_fn,
reflog_expiry_should_prune_fn should_prune_fn,
@@ -1857,7 +2092,7 @@ int reflog_expire(const char *refname, const unsigned char *sha1,
void *policy_cb_data)
{
return refs_reflog_expire(get_main_ref_store(),
- refname, sha1, flags,
+ refname, oid, flags,
prepare_fn, should_prune_fn,
cleanup_fn, policy_cb_data);
}
@@ -1870,15 +2105,16 @@ int initial_ref_transaction_commit(struct ref_transaction *transaction,
return refs->be->initial_transaction_commit(refs, transaction, err);
}
-int refs_delete_refs(struct ref_store *refs, struct string_list *refnames,
- unsigned int flags)
+int refs_delete_refs(struct ref_store *refs, const char *msg,
+ struct string_list *refnames, unsigned int flags)
{
- return refs->be->delete_refs(refs, refnames, flags);
+ return refs->be->delete_refs(refs, msg, refnames, flags);
}
-int delete_refs(struct string_list *refnames, unsigned int flags)
+int delete_refs(const char *msg, struct string_list *refnames,
+ unsigned int flags)
{
- return refs_delete_refs(get_main_ref_store(), refnames, flags);
+ return refs_delete_refs(get_main_ref_store(), msg, refnames, flags);
}
int refs_rename_ref(struct ref_store *refs, const char *oldref,
@@ -1891,3 +2127,14 @@ int rename_ref(const char *oldref, const char *newref, const char *logmsg)
{
return refs_rename_ref(get_main_ref_store(), oldref, newref, logmsg);
}
+
+int refs_copy_existing_ref(struct ref_store *refs, const char *oldref,
+ const char *newref, const char *logmsg)
+{
+ return refs->be->copy_ref(refs, oldref, newref, logmsg);
+}
+
+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);
+}