Show changes to builtin/update-ref.c +98 −39
diff --git a/builtin/update-ref.c b/builtin/update-ref.c
index 5259cc7226..6355c3dd3e 100644
--- a/builtin/update-ref.c
+++ b/builtin/update-ref.c
@@ -25,6 +25,15 @@ static unsigned int default_flags;
static unsigned create_reflog_flag;
static const char *msg;
+struct command_options {
+ /*
+ * Individual updates are allowed to fail without causing
+ * update-ref to exit. This is set when using the
+ * '--batch-updates' flag.
+ */
+ bool allow_update_failures;
+};
+
/*
* Parse one whitespace- or NUL-terminated, possibly C-quoted argument
* and append the result to arg. Return a pointer to the terminator.
@@ -257,6 +266,31 @@ static void print_rejected_refs(const char *refname,
strbuf_release(&sb);
}
+/*
+ * Handle transaction errors. If we're using batches updates, we want to only
+ * die for generic errors and print the remaining to the user.
+ */
+static void handle_ref_transaction_error(const char *refname,
+ struct object_id *new_oid,
+ struct object_id *old_oid,
+ const char *new_target,
+ const char *old_target,
+ enum ref_transaction_error tx_err,
+ struct strbuf *err,
+ struct command_options *opts)
+{
+ if (!tx_err)
+ return;
+
+ if (tx_err != REF_TRANSACTION_ERROR_GENERIC && opts->allow_update_failures) {
+ print_rejected_refs(refname, old_oid, new_oid, old_target,
+ new_target, tx_err, err->buf, NULL);
+ return;
+ }
+
+ die("%s", err->buf);
+}
+
/*
* The following five parse_cmd_*() functions parse the corresponding
* command. In each case, next points at the character following the
@@ -268,11 +302,13 @@ static void print_rejected_refs(const char *refname,
*/
static void parse_cmd_update(struct ref_transaction *transaction,
- const char *next, const char *end)
+ const char *next, const char *end,
+ struct command_options *opts)
{
struct strbuf err = STRBUF_INIT;
char *refname;
struct object_id new_oid, old_oid;
+ enum ref_transaction_error tx_err;
int have_old;
refname = parse_refname(&next);
@@ -289,12 +325,14 @@ static void parse_cmd_update(struct ref_transaction *transaction,
if (*next != line_termination)
die("update %s: extra input: %s", refname, next);
- if (ref_transaction_update(transaction, refname,
- &new_oid, have_old ? &old_oid : NULL,
- NULL, NULL,
- update_flags | create_reflog_flag,
- msg, &err))
- die("%s", err.buf);
+ tx_err = ref_transaction_update(transaction, refname,
+ &new_oid, have_old ? &old_oid : NULL,
+ NULL, NULL,
+ update_flags | create_reflog_flag,
+ msg, &err);
+ handle_ref_transaction_error(refname, &new_oid, have_old ? &old_oid : NULL,
+ NULL, NULL, tx_err, &err, opts);
+
update_flags = default_flags;
free(refname);
@@ -302,9 +340,11 @@ static void parse_cmd_update(struct ref_transaction *transaction,
}
static void parse_cmd_symref_update(struct ref_transaction *transaction,
- const char *next, const char *end UNUSED)
+ const char *next, const char *end UNUSED,
+ struct command_options *opts)
{
char *refname, *new_target, *old_arg;
+ enum ref_transaction_error tx_err;
char *old_target = NULL;
struct strbuf err = STRBUF_INIT;
struct object_id old_oid;
@@ -341,13 +381,15 @@ static void parse_cmd_symref_update(struct ref_transaction *transaction,
if (*next != line_termination)
die("symref-update %s: extra input: %s", refname, next);
- if (ref_transaction_update(transaction, refname, NULL,
- have_old_oid ? &old_oid : NULL,
- new_target,
- have_old_oid ? NULL : old_target,
- update_flags | create_reflog_flag,
- msg, &err))
- die("%s", err.buf);
+ tx_err = ref_transaction_update(transaction, refname, NULL,
+ have_old_oid ? &old_oid : NULL,
+ new_target,
+ have_old_oid ? NULL : old_target,
+ update_flags | create_reflog_flag,
+ msg, &err);
+ handle_ref_transaction_error(refname, NULL, have_old_oid ? &old_oid : NULL,
+ new_target, have_old_oid ? NULL : old_target,
+ tx_err, &err, opts);
update_flags = default_flags;
free(refname);
@@ -358,11 +400,13 @@ static void parse_cmd_symref_update(struct ref_transaction *transaction,
}
static void parse_cmd_create(struct ref_transaction *transaction,
- const char *next, const char *end)
+ const char *next, const char *end,
+ struct command_options *opts)
{
struct strbuf err = STRBUF_INIT;
char *refname;
struct object_id new_oid;
+ enum ref_transaction_error tx_err;
refname = parse_refname(&next);
if (!refname)
@@ -377,22 +421,24 @@ static void parse_cmd_create(struct ref_transaction *transaction,
if (*next != line_termination)
die("create %s: extra input: %s", refname, next);
- if (ref_transaction_create(transaction, refname, &new_oid, NULL,
- update_flags | create_reflog_flag,
- msg, &err))
- die("%s", err.buf);
+ tx_err = ref_transaction_create(transaction, refname, &new_oid, NULL,
+ update_flags | create_reflog_flag,
+ msg, &err);
+ handle_ref_transaction_error(refname, &new_oid, NULL, NULL, NULL, tx_err,
+ &err, opts);
update_flags = default_flags;
free(refname);
strbuf_release(&err);
}
-
static void parse_cmd_symref_create(struct ref_transaction *transaction,
- const char *next, const char *end UNUSED)
+ const char *next, const char *end UNUSED,
+ struct command_options *opts)
{
struct strbuf err = STRBUF_INIT;
char *refname, *new_target;
+ enum ref_transaction_error tx_err;
refname = parse_refname(&next);
if (!refname)
@@ -405,10 +451,11 @@ static void parse_cmd_symref_create(struct ref_transaction *transaction,
if (*next != line_termination)
die("symref-create %s: extra input: %s", refname, next);
- if (ref_transaction_create(transaction, refname, NULL, new_target,
- update_flags | create_reflog_flag,
- msg, &err))
- die("%s", err.buf);
+ tx_err = ref_transaction_create(transaction, refname, NULL, new_target,
+ update_flags | create_reflog_flag,
+ msg, &err);
+ handle_ref_transaction_error(refname, NULL, NULL, new_target, NULL,
+ tx_err, &err, opts);
update_flags = default_flags;
free(refname);
@@ -417,7 +464,8 @@ static void parse_cmd_symref_create(struct ref_transaction *transaction,
}
static void parse_cmd_delete(struct ref_transaction *transaction,
- const char *next, const char *end)
+ const char *next, const char *end,
+ struct command_options *opts UNUSED)
{
struct strbuf err = STRBUF_INIT;
char *refname;
@@ -450,9 +498,9 @@ static void parse_cmd_delete(struct ref_transaction *transaction,
strbuf_release(&err);
}
-
static void parse_cmd_symref_delete(struct ref_transaction *transaction,
- const char *next, const char *end UNUSED)
+ const char *next, const char *end UNUSED,
+ struct command_options *opts UNUSED)
{
struct strbuf err = STRBUF_INIT;
char *refname, *old_target;
@@ -479,9 +527,9 @@ static void parse_cmd_symref_delete(struct ref_transaction *transaction,
strbuf_release(&err);
}
-
static void parse_cmd_verify(struct ref_transaction *transaction,
- const char *next, const char *end)
+ const char *next, const char *end,
+ struct command_options *opts UNUSED)
{
struct strbuf err = STRBUF_INIT;
char *refname;
@@ -508,7 +556,8 @@ static void parse_cmd_verify(struct ref_transaction *transaction,
}
static void parse_cmd_symref_verify(struct ref_transaction *transaction,
- const char *next, const char *end UNUSED)
+ const char *next, const char *end UNUSED,
+ struct command_options *opts UNUSED)
{
struct strbuf err = STRBUF_INIT;
struct object_id old_oid;
@@ -550,7 +599,8 @@ static void report_ok(const char *command)
}
static void parse_cmd_option(struct ref_transaction *transaction UNUSED,
- const char *next, const char *end UNUSED)
+ const char *next, const char *end UNUSED,
+ struct command_options *opts UNUSED)
{
const char *rest;
if (skip_prefix(next, "no-deref", &rest) && *rest == line_termination)
@@ -560,7 +610,8 @@ static void parse_cmd_option(struct ref_transaction *transaction UNUSED,
}
static void parse_cmd_start(struct ref_transaction *transaction UNUSED,
- const char *next, const char *end UNUSED)
+ const char *next, const char *end UNUSED,
+ struct command_options *opts UNUSED)
{
if (*next != line_termination)
die("start: extra input: %s", next);
@@ -568,7 +619,8 @@ static void parse_cmd_start(struct ref_transaction *transaction UNUSED,
}
static void parse_cmd_prepare(struct ref_transaction *transaction,
- const char *next, const char *end UNUSED)
+ const char *next, const char *end UNUSED,
+ struct command_options *opts UNUSED)
{
struct strbuf error = STRBUF_INIT;
if (*next != line_termination)
@@ -579,7 +631,8 @@ static void parse_cmd_prepare(struct ref_transaction *transaction,
}
static void parse_cmd_abort(struct ref_transaction *transaction,
- const char *next, const char *end UNUSED)
+ const char *next, const char *end UNUSED,
+ struct command_options *opts UNUSED)
{
struct strbuf error = STRBUF_INIT;
if (*next != line_termination)
@@ -590,7 +643,8 @@ static void parse_cmd_abort(struct ref_transaction *transaction,
}
static void parse_cmd_commit(struct ref_transaction *transaction,
- const char *next, const char *end UNUSED)
+ const char *next, const char *end UNUSED,
+ struct command_options *opts UNUSED)
{
struct strbuf error = STRBUF_INIT;
if (*next != line_termination)
@@ -618,7 +672,8 @@ enum update_refs_state {
static const struct parse_cmd {
const char *prefix;
- void (*fn)(struct ref_transaction *, const char *, const char *);
+ void (*fn)(struct ref_transaction *, const char *, const char *,
+ struct command_options *);
unsigned args;
enum update_refs_state state;
} command[] = {
@@ -644,6 +699,10 @@ static void update_refs_stdin(unsigned int flags)
struct ref_transaction *transaction;
int i, j;
+ struct command_options opts = {
+ .allow_update_failures = flags & REF_TRANSACTION_ALLOW_FAILURE,
+ };
+
transaction = ref_store_transaction_begin(get_main_ref_store(the_repository),
flags, &err);
if (!transaction)
@@ -721,7 +780,7 @@ static void update_refs_stdin(unsigned int flags)
}
cmd->fn(transaction, input.buf + strlen(cmd->prefix) + !!cmd->args,
- input.buf + input.len);
+ input.buf + input.len, &opts);
}
switch (state) {