pseudorefs: create and use pseudoref update and delete functions
Pseudorefs should not be updated through the ref transaction API, because alternate ref backends still need to store pseudorefs in GIT_DIR (instead of wherever they store refs). Instead, change update_ref and delete_ref to call pseudoref-specific functions. Signed-off-by: David Turner <dturner@twopensource.com> Signed-off-by: Junio C Hamano <gitster@pobox.com>
This commit is contained in:
parent
266b18273a
commit
74ec19d4be
101
refs.c
101
refs.c
@ -2847,11 +2847,87 @@ enum ref_type ref_type(const char *refname)
|
|||||||
return REF_TYPE_NORMAL;
|
return REF_TYPE_NORMAL;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static int write_pseudoref(const char *pseudoref, const unsigned char *sha1,
|
||||||
|
const unsigned char *old_sha1, struct strbuf *err)
|
||||||
|
{
|
||||||
|
const char *filename;
|
||||||
|
int fd;
|
||||||
|
static struct lock_file lock;
|
||||||
|
struct strbuf buf = STRBUF_INIT;
|
||||||
|
int ret = -1;
|
||||||
|
|
||||||
|
strbuf_addf(&buf, "%s\n", sha1_to_hex(sha1));
|
||||||
|
|
||||||
|
filename = git_path("%s", pseudoref);
|
||||||
|
fd = hold_lock_file_for_update(&lock, filename, LOCK_DIE_ON_ERROR);
|
||||||
|
if (fd < 0) {
|
||||||
|
strbuf_addf(err, "Could not open '%s' for writing: %s",
|
||||||
|
filename, strerror(errno));
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (old_sha1) {
|
||||||
|
unsigned char actual_old_sha1[20];
|
||||||
|
read_ref(pseudoref, actual_old_sha1);
|
||||||
|
if (hashcmp(actual_old_sha1, old_sha1)) {
|
||||||
|
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) {
|
||||||
|
strbuf_addf(err, "Could not write to '%s'", filename);
|
||||||
|
rollback_lock_file(&lock);
|
||||||
|
goto done;
|
||||||
|
}
|
||||||
|
|
||||||
|
commit_lock_file(&lock);
|
||||||
|
ret = 0;
|
||||||
|
done:
|
||||||
|
strbuf_release(&buf);
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int delete_pseudoref(const char *pseudoref, const unsigned char *old_sha1)
|
||||||
|
{
|
||||||
|
static struct lock_file lock;
|
||||||
|
const char *filename;
|
||||||
|
|
||||||
|
filename = git_path("%s", pseudoref);
|
||||||
|
|
||||||
|
if (old_sha1 && !is_null_sha1(old_sha1)) {
|
||||||
|
int fd;
|
||||||
|
unsigned char actual_old_sha1[20];
|
||||||
|
|
||||||
|
fd = hold_lock_file_for_update(&lock, filename,
|
||||||
|
LOCK_DIE_ON_ERROR);
|
||||||
|
if (fd < 0)
|
||||||
|
die_errno(_("Could not open '%s' for writing"), filename);
|
||||||
|
read_ref(pseudoref, actual_old_sha1);
|
||||||
|
if (hashcmp(actual_old_sha1, old_sha1)) {
|
||||||
|
warning("Unexpected sha1 when deleting %s", pseudoref);
|
||||||
|
rollback_lock_file(&lock);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
unlink(filename);
|
||||||
|
rollback_lock_file(&lock);
|
||||||
|
} else {
|
||||||
|
unlink(filename);
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
int delete_ref(const char *refname, const unsigned char *sha1, unsigned int flags)
|
int delete_ref(const char *refname, const unsigned char *sha1, unsigned int flags)
|
||||||
{
|
{
|
||||||
struct ref_transaction *transaction;
|
struct ref_transaction *transaction;
|
||||||
struct strbuf err = STRBUF_INIT;
|
struct strbuf err = STRBUF_INIT;
|
||||||
|
|
||||||
|
if (ref_type(refname) == REF_TYPE_PSEUDOREF)
|
||||||
|
return delete_pseudoref(refname, sha1);
|
||||||
|
|
||||||
transaction = ref_transaction_begin(&err);
|
transaction = ref_transaction_begin(&err);
|
||||||
if (!transaction ||
|
if (!transaction ||
|
||||||
ref_transaction_delete(transaction, refname,
|
ref_transaction_delete(transaction, refname,
|
||||||
@ -3908,17 +3984,25 @@ int update_ref(const char *msg, const char *refname,
|
|||||||
const unsigned char *new_sha1, const unsigned char *old_sha1,
|
const unsigned char *new_sha1, const unsigned char *old_sha1,
|
||||||
unsigned int flags, enum action_on_err onerr)
|
unsigned int flags, enum action_on_err onerr)
|
||||||
{
|
{
|
||||||
struct ref_transaction *t;
|
struct ref_transaction *t = NULL;
|
||||||
struct strbuf err = STRBUF_INIT;
|
struct strbuf err = STRBUF_INIT;
|
||||||
|
int ret = 0;
|
||||||
|
|
||||||
t = ref_transaction_begin(&err);
|
if (ref_type(refname) == REF_TYPE_PSEUDOREF) {
|
||||||
if (!t ||
|
ret = write_pseudoref(refname, new_sha1, old_sha1, &err);
|
||||||
ref_transaction_update(t, refname, new_sha1, old_sha1,
|
} else {
|
||||||
flags, msg, &err) ||
|
t = ref_transaction_begin(&err);
|
||||||
ref_transaction_commit(t, &err)) {
|
if (!t ||
|
||||||
|
ref_transaction_update(t, refname, new_sha1, old_sha1,
|
||||||
|
flags, msg, &err) ||
|
||||||
|
ref_transaction_commit(t, &err)) {
|
||||||
|
ret = 1;
|
||||||
|
ref_transaction_free(t);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (ret) {
|
||||||
const char *str = "update_ref failed for ref '%s': %s";
|
const char *str = "update_ref failed for ref '%s': %s";
|
||||||
|
|
||||||
ref_transaction_free(t);
|
|
||||||
switch (onerr) {
|
switch (onerr) {
|
||||||
case UPDATE_REFS_MSG_ON_ERR:
|
case UPDATE_REFS_MSG_ON_ERR:
|
||||||
error(str, refname, err.buf);
|
error(str, refname, err.buf);
|
||||||
@ -3933,7 +4017,8 @@ int update_ref(const char *msg, const char *refname,
|
|||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
strbuf_release(&err);
|
strbuf_release(&err);
|
||||||
ref_transaction_free(t);
|
if (t)
|
||||||
|
ref_transaction_free(t);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user