Let ref_transaction_commit return an optional error string that describes
the transaction failure. Start by returning the same error as update_ref_lock
returns, modulo the initial error:/fatal: preamble.

This will make it easier for callers to craft better error messages when
a transaction call fails.

Signed-off-by: Ronnie Sahlberg <sahlb...@google.com>
---
 builtin/update-ref.c |  2 +-
 refs.c               | 12 +++++++++++-
 refs.h               |  5 ++++-
 3 files changed, 16 insertions(+), 3 deletions(-)

diff --git a/builtin/update-ref.c b/builtin/update-ref.c
index 405267f..aaa06aa 100644
--- a/builtin/update-ref.c
+++ b/builtin/update-ref.c
@@ -367,7 +367,7 @@ int cmd_update_ref(int argc, const char **argv, const char 
*prefix)
                if (end_null)
                        line_termination = '\0';
                update_refs_stdin();
-               ret = ref_transaction_commit(transaction, msg,
+               ret = ref_transaction_commit(transaction, msg, NULL,
                                             UPDATE_REFS_DIE_ON_ERR);
                return ret;
        }
diff --git a/refs.c b/refs.c
index 2d83ef6..0712912 100644
--- a/refs.c
+++ b/refs.c
@@ -3414,7 +3414,8 @@ static int ref_update_reject_duplicates(struct ref_update 
**updates, int n,
 }
 
 int ref_transaction_commit(struct ref_transaction *transaction,
-                          const char *msg, enum action_on_err onerr)
+                          const char *msg, char **err,
+                          enum action_on_err onerr)
 {
        int ret = 0, delnum = 0, i;
        const char **delnames;
@@ -3424,6 +3425,9 @@ int ref_transaction_commit(struct ref_transaction 
*transaction,
        if (!n)
                return 0;
 
+       if (err)
+               *err = NULL;
+
        /* Allocate work space */
        delnames = xmalloc(sizeof(*delnames) * n);
 
@@ -3443,6 +3447,12 @@ int ref_transaction_commit(struct ref_transaction 
*transaction,
                                               update->flags,
                                               &update->type, onerr);
                if (!update->lock) {
+                       if (err) {
+                               const char *str = "Cannot lock the ref '%s'.";
+                               *err = xmalloc(PATH_MAX + 24);
+                               snprintf(*err, PATH_MAX + 24, str,
+                                        update->refname);
+                       }
                        ret = 1;
                        goto cleanup;
                }
diff --git a/refs.h b/refs.h
index 892c5b6..615c73d 100644
--- a/refs.h
+++ b/refs.h
@@ -268,9 +268,12 @@ void ref_transaction_delete(struct ref_transaction 
*transaction,
  * Commit all of the changes that have been queued in transaction, as
  * atomically as possible.  Return a nonzero value if there is a
  * problem.  The ref_transaction is freed by this function.
+ * If error is non-NULL it will return an error string that describes
+ * why a commit failed. This string must be free()ed by the caller.
  */
 int ref_transaction_commit(struct ref_transaction *transaction,
-                          const char *msg, enum action_on_err onerr);
+                          const char *msg, char **err,
+                          enum action_on_err onerr);
 
 /** Lock a ref and then write its file */
 int update_ref(const char *action, const char *refname,
-- 
1.9.1.521.g5dc89fa

--
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

Reply via email to