return timeout_ms;
}
-static int write_pseudoref(const char *pseudoref, const unsigned char *sha1,
- const unsigned char *old_sha1, struct strbuf *err)
+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;
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_timeout(&lock, filename,
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.hash))
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;
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_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.hash))
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;
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;
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 ? old_oid->hash : NULL,
flags, msg, &err) ||
ref_transaction_commit(transaction, &err)) {
error("%s", err.buf);
}
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)
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;
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 ? new_oid->hash : NULL,
+ old_oid ? old_oid->hash : NULL,
flags, msg, &err) ||
ref_transaction_commit(t, &err)) {
ret = 1;
}
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)
if (refs_read_raw_ref(refs, refname,
sha1, &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);
if (*flags & REF_BAD_NAME)
*flags |= REF_ISBROKEN;