Skip to content

Commit

Permalink
pseudorefs: create and use pseudoref update and delete functions
Browse files Browse the repository at this point in the history
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>
  • Loading branch information
David Turner authored and Junio C Hamano committed Jul 31, 2015
1 parent 266b182 commit 74ec19d
Showing 1 changed file with 93 additions and 8 deletions.
101 changes: 93 additions & 8 deletions refs.c
Original file line number Diff line number Diff line change
Expand Up @@ -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,
Expand Down Expand Up @@ -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);
Expand All @@ -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;
}

Expand Down

0 comments on commit 74ec19d

Please sign in to comment.