Re: [PATCH v3 4/6] pseudorefs: create and use pseudoref update and delete functions

2015-07-29 Thread Eric Sunshine
On Tue, Jul 28, 2015 at 2:12 PM, David Turner dtur...@twopensource.com wrote:
 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 dtur...@twopensource.com
 ---
 diff --git a/refs.c b/refs.c
 index 553ae8b..2bd6aa6 100644
 --- a/refs.c
 +++ b/refs.c
 @@ -2877,12 +2877,87 @@ enum ref_type ref_type(const char *refname)
 +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);
 +   return -1;

Does this need to release the lock file before returning?

 +   }
 +
 +   unlink(filename);
 +   rollback_lock_file(lock);
 +   } else {
 +   unlink(filename);
 +   }
 +
 +   return 0;
 +}
--
To unsubscribe from this list: send the line unsubscribe git in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


[PATCH v3 4/6] pseudorefs: create and use pseudoref update and delete functions

2015-07-28 Thread David Turner
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 dtur...@twopensource.com
---
 refs.c | 100 +++--
 1 file changed, 92 insertions(+), 8 deletions(-)

diff --git a/refs.c b/refs.c
index 553ae8b..2bd6aa6 100644
--- a/refs.c
+++ b/refs.c
@@ -2877,12 +2877,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);
+   return -1;
+   }
+
+   unlink(filename);
+   rollback_lock_file(lock);
+   } else {
+   unlink(filename);
+   }
+
+   return 0;
+}
+
 int delete_ref(const char *refname, const unsigned char *old_sha1,
   unsigned int flags)
 {
struct ref_transaction *transaction;
struct strbuf err = STRBUF_INIT;
 
+   if (ref_type(refname) == REF_TYPE_PSEUDOREF)
+   return delete_pseudoref(refname, old_sha1);
+
transaction = ref_transaction_begin(err);
if (!transaction ||
ref_transaction_delete(transaction, refname, old_sha1,
@@ -3976,17 +4051,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);
@@ -4001,7 +4084,8 @@ int update_ref(const char *msg, const char *refname,
return 1;
}
strbuf_release(err);
-   ref_transaction_free(t);
+   if