Skip to content

Commit 74ec19d

Browse files
dturner-twgitster
authored andcommitted
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 <[email protected]> Signed-off-by: Junio C Hamano <[email protected]>
1 parent 266b182 commit 74ec19d

File tree

1 file changed

+93
-8
lines changed

1 file changed

+93
-8
lines changed

refs.c

Lines changed: 93 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -2847,11 +2847,87 @@ enum ref_type ref_type(const char *refname)
28472847
return REF_TYPE_NORMAL;
28482848
}
28492849

2850+
static int write_pseudoref(const char *pseudoref, const unsigned char *sha1,
2851+
const unsigned char *old_sha1, struct strbuf *err)
2852+
{
2853+
const char *filename;
2854+
int fd;
2855+
static struct lock_file lock;
2856+
struct strbuf buf = STRBUF_INIT;
2857+
int ret = -1;
2858+
2859+
strbuf_addf(&buf, "%s\n", sha1_to_hex(sha1));
2860+
2861+
filename = git_path("%s", pseudoref);
2862+
fd = hold_lock_file_for_update(&lock, filename, LOCK_DIE_ON_ERROR);
2863+
if (fd < 0) {
2864+
strbuf_addf(err, "Could not open '%s' for writing: %s",
2865+
filename, strerror(errno));
2866+
return -1;
2867+
}
2868+
2869+
if (old_sha1) {
2870+
unsigned char actual_old_sha1[20];
2871+
read_ref(pseudoref, actual_old_sha1);
2872+
if (hashcmp(actual_old_sha1, old_sha1)) {
2873+
strbuf_addf(err, "Unexpected sha1 when writing %s", pseudoref);
2874+
rollback_lock_file(&lock);
2875+
goto done;
2876+
}
2877+
}
2878+
2879+
if (write_in_full(fd, buf.buf, buf.len) != buf.len) {
2880+
strbuf_addf(err, "Could not write to '%s'", filename);
2881+
rollback_lock_file(&lock);
2882+
goto done;
2883+
}
2884+
2885+
commit_lock_file(&lock);
2886+
ret = 0;
2887+
done:
2888+
strbuf_release(&buf);
2889+
return ret;
2890+
}
2891+
2892+
static int delete_pseudoref(const char *pseudoref, const unsigned char *old_sha1)
2893+
{
2894+
static struct lock_file lock;
2895+
const char *filename;
2896+
2897+
filename = git_path("%s", pseudoref);
2898+
2899+
if (old_sha1 && !is_null_sha1(old_sha1)) {
2900+
int fd;
2901+
unsigned char actual_old_sha1[20];
2902+
2903+
fd = hold_lock_file_for_update(&lock, filename,
2904+
LOCK_DIE_ON_ERROR);
2905+
if (fd < 0)
2906+
die_errno(_("Could not open '%s' for writing"), filename);
2907+
read_ref(pseudoref, actual_old_sha1);
2908+
if (hashcmp(actual_old_sha1, old_sha1)) {
2909+
warning("Unexpected sha1 when deleting %s", pseudoref);
2910+
rollback_lock_file(&lock);
2911+
return -1;
2912+
}
2913+
2914+
unlink(filename);
2915+
rollback_lock_file(&lock);
2916+
} else {
2917+
unlink(filename);
2918+
}
2919+
2920+
return 0;
2921+
}
2922+
28502923
int delete_ref(const char *refname, const unsigned char *sha1, unsigned int flags)
28512924
{
28522925
struct ref_transaction *transaction;
28532926
struct strbuf err = STRBUF_INIT;
28542927

2928+
if (ref_type(refname) == REF_TYPE_PSEUDOREF)
2929+
return delete_pseudoref(refname, sha1);
2930+
28552931
transaction = ref_transaction_begin(&err);
28562932
if (!transaction ||
28572933
ref_transaction_delete(transaction, refname,
@@ -3908,17 +3984,25 @@ int update_ref(const char *msg, const char *refname,
39083984
const unsigned char *new_sha1, const unsigned char *old_sha1,
39093985
unsigned int flags, enum action_on_err onerr)
39103986
{
3911-
struct ref_transaction *t;
3987+
struct ref_transaction *t = NULL;
39123988
struct strbuf err = STRBUF_INIT;
3989+
int ret = 0;
39133990

3914-
t = ref_transaction_begin(&err);
3915-
if (!t ||
3916-
ref_transaction_update(t, refname, new_sha1, old_sha1,
3917-
flags, msg, &err) ||
3918-
ref_transaction_commit(t, &err)) {
3991+
if (ref_type(refname) == REF_TYPE_PSEUDOREF) {
3992+
ret = write_pseudoref(refname, new_sha1, old_sha1, &err);
3993+
} else {
3994+
t = ref_transaction_begin(&err);
3995+
if (!t ||
3996+
ref_transaction_update(t, refname, new_sha1, old_sha1,
3997+
flags, msg, &err) ||
3998+
ref_transaction_commit(t, &err)) {
3999+
ret = 1;
4000+
ref_transaction_free(t);
4001+
}
4002+
}
4003+
if (ret) {
39194004
const char *str = "update_ref failed for ref '%s': %s";
39204005

3921-
ref_transaction_free(t);
39224006
switch (onerr) {
39234007
case UPDATE_REFS_MSG_ON_ERR:
39244008
error(str, refname, err.buf);
@@ -3933,7 +4017,8 @@ int update_ref(const char *msg, const char *refname,
39334017
return 1;
39344018
}
39354019
strbuf_release(&err);
3936-
ref_transaction_free(t);
4020+
if (t)
4021+
ref_transaction_free(t);
39374022
return 0;
39384023
}
39394024

0 commit comments

Comments
 (0)