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;
|
||||
}
|
||||
|
||||
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)
|
||||
{
|
||||
struct ref_transaction *transaction;
|
||||
struct strbuf err = STRBUF_INIT;
|
||||
|
||||
if (ref_type(refname) == REF_TYPE_PSEUDOREF)
|
||||
return delete_pseudoref(refname, sha1);
|
||||
|
||||
transaction = ref_transaction_begin(&err);
|
||||
if (!transaction ||
|
||||
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,
|
||||
unsigned int flags, enum action_on_err onerr)
|
||||
{
|
||||
struct ref_transaction *t;
|
||||
struct ref_transaction *t = NULL;
|
||||
struct strbuf err = STRBUF_INIT;
|
||||
int ret = 0;
|
||||
|
||||
t = ref_transaction_begin(&err);
|
||||
if (!t ||
|
||||
ref_transaction_update(t, refname, new_sha1, old_sha1,
|
||||
flags, msg, &err) ||
|
||||
ref_transaction_commit(t, &err)) {
|
||||
if (ref_type(refname) == REF_TYPE_PSEUDOREF) {
|
||||
ret = write_pseudoref(refname, new_sha1, old_sha1, &err);
|
||||
} else {
|
||||
t = ref_transaction_begin(&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";
|
||||
|
||||
ref_transaction_free(t);
|
||||
switch (onerr) {
|
||||
case UPDATE_REFS_MSG_ON_ERR:
|
||||
error(str, refname, err.buf);
|
||||
@ -3933,7 +4017,8 @@ int update_ref(const char *msg, const char *refname,
|
||||
return 1;
|
||||
}
|
||||
strbuf_release(&err);
|
||||
ref_transaction_free(t);
|
||||
if (t)
|
||||
ref_transaction_free(t);
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user