Re: [PATCH v3 03/19] refs.c: make ref_transaction_commit return an error string

2014-04-28 Thread Ronnie Sahlberg
Good points.



On Fri, Apr 25, 2014 at 3:10 PM, Jonathan Nieder jrnie...@gmail.com wrote:
 Ronnie Sahlberg wrote:

 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.

 s/returns/prints/?

Done, and then was deleted when I reworded the message.


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

 Interesting.  Can you give an example?  What kind of behavior are we
 expecting in callers other than die()-ing or cleaning up and then
 die()-ing?

I was thinking a bit too far ahead. You could in theory keep logging multiple
lock failures during the _commit() and then when the transaction fails
and returns
it will have appended a list of all refs that failed and not just the
first ref that failed.



 I like this more than having the caller pass in a flag/callback/etc to
 decide how noisy to be and whether to gracefully accept errors or exit.
 So it seems like an improvement, but may always returning error()
 would be better --- more context would help in clarifying this.

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

 Is the idea that if I pass in a pointer err then
 ref_transaction_commit will take the action described by onerr *and*
 write its error message to err?

Temporarily, yes.
Shortly after this patch I remove the onerr argument completely.
But I want to keep the pass error back to caller and get rid of
onerr as two separate patches.
I think it is easier to follow the flow of changes if they are done in
two separate steps.


 Probably squashing with patch 07 would make this easier to read (and
 wouldn't require changing any messages at that point).

See above.


 [...]
 --- a/refs.c
 +++ b/refs.c
 [...]
 @@ -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);
 + }

 Might be clearer to use a helper similar to path.c::mkpathdup

 char *aprintf(const char *fmt, ...)
 {
 char *result;
 struct strbuf sb = STRBUF_INIT;
 va_list args;

 va_start(args, fmt);
 strbuf_vaddf(sb, fmt, args);
 va_end(args);

 return strbuf_detach(sb);
 }

 or to have the caller pass in a pointer to strbuf instead of char *.

strbuf as argument is probably the right thing to do. I am doing that change.


 The rest looks good to me.

 Thanks,
 Jonathan
--
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 03/19] refs.c: make ref_transaction_commit return an error string

2014-04-25 Thread Ronnie Sahlberg
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


Re: [PATCH v3 03/19] refs.c: make ref_transaction_commit return an error string

2014-04-25 Thread Jonathan Nieder
Ronnie Sahlberg wrote:

 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.

s/returns/prints/?

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

Interesting.  Can you give an example?  What kind of behavior are we
expecting in callers other than die()-ing or cleaning up and then
die()-ing?

I like this more than having the caller pass in a flag/callback/etc to
decide how noisy to be and whether to gracefully accept errors or exit.
So it seems like an improvement, but may always returning error()
would be better --- more context would help in clarifying this.

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

Is the idea that if I pass in a pointer err then
ref_transaction_commit will take the action described by onerr *and*
write its error message to err?

Probably squashing with patch 07 would make this easier to read (and
wouldn't require changing any messages at that point).

[...]
 --- a/refs.c
 +++ b/refs.c
[...]
 @@ -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);
 + }

Might be clearer to use a helper similar to path.c::mkpathdup

char *aprintf(const char *fmt, ...)
{
char *result;
struct strbuf sb = STRBUF_INIT;
va_list args;

va_start(args, fmt);
strbuf_vaddf(sb, fmt, args);
va_end(args);

return strbuf_detach(sb);
}

or to have the caller pass in a pointer to strbuf instead of char *.

The rest looks good to me.

Thanks,
Jonathan
--
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