Wrap all the ref updates inside a transaction.
Signed-off-by: Ronnie Sahlberg sahlb...@google.com
---
builtin/receive-pack.c | 96 +-
1 file changed, 63 insertions(+), 33 deletions(-)
diff --git a/builtin/receive-pack.c b/builtin/receive-pack.c
index c323081..91099ad 100644
--- a/builtin/receive-pack.c
+++ b/builtin/receive-pack.c
@@ -194,7 +194,7 @@ static void write_head_info(void)
struct command {
struct command *next;
- const char *error_string;
+ char *error_string;
unsigned int skip_update:1,
did_not_exist:1;
int index;
@@ -468,19 +468,18 @@ static int update_shallow_ref(struct command *cmd, struct
shallow_info *si)
return 0;
}
-static const char *update(struct command *cmd, struct shallow_info *si)
+static char *update(struct command *cmd, struct shallow_info *si)
{
const char *name = cmd-ref_name;
struct strbuf namespaced_name_buf = STRBUF_INIT;
const char *namespaced_name;
unsigned char *old_sha1 = cmd-old_sha1;
unsigned char *new_sha1 = cmd-new_sha1;
- struct ref_lock *lock;
/* only refs/... are allowed */
if (!starts_with(name, refs/) || check_refname_format(name + 5, 0)) {
rp_error(refusing to create funny ref '%s' remotely, name);
- return funny refname;
+ return xstrdup(funny refname);
}
strbuf_addf(namespaced_name_buf, %s%s, get_git_namespace(), name);
@@ -498,20 +497,20 @@ static const char *update(struct command *cmd, struct
shallow_info *si)
rp_error(refusing to update checked out branch: %s,
name);
if (deny_current_branch == DENY_UNCONFIGURED)
refuse_unconfigured_deny();
- return branch is currently checked out;
+ return xstrdup(branch is currently checked out);
}
}
if (!is_null_sha1(new_sha1) !has_sha1_file(new_sha1)) {
error(unpack should have generated %s,
but I can't find it!, sha1_to_hex(new_sha1));
- return bad pack;
+ return xstrdup(bad pack);
}
if (!is_null_sha1(old_sha1) is_null_sha1(new_sha1)) {
if (deny_deletes starts_with(name, refs/heads/)) {
rp_error(denying ref deletion for %s, name);
- return deletion prohibited;
+ return xstrdup(deletion prohibited);
}
if (!strcmp(namespaced_name, head_name)) {
@@ -526,7 +525,7 @@ static const char *update(struct command *cmd, struct
shallow_info *si)
if (deny_delete_current == DENY_UNCONFIGURED)
refuse_unconfigured_deny_delete_current();
rp_error(refusing to delete the current
branch: %s, name);
- return deletion of the current branch
prohibited;
+ return xstrdup(deletion of the current branch
prohibited);
}
}
}
@@ -544,19 +543,19 @@ static const char *update(struct command *cmd, struct
shallow_info *si)
old_object-type != OBJ_COMMIT ||
new_object-type != OBJ_COMMIT) {
error(bad sha1 objects for %s, name);
- return bad ref;
+ return xstrdup(bad ref);
}
old_commit = (struct commit *)old_object;
new_commit = (struct commit *)new_object;
if (!in_merge_bases(old_commit, new_commit)) {
rp_error(denying non-fast-forward %s
(you should pull first), name);
- return non-fast-forward;
+ return xstrdup(non-fast-forward);
}
}
if (run_update_hook(cmd)) {
rp_error(hook declined to update %s, name);
- return hook declined;
+ return xstrdup(hook declined);
}
if (is_null_sha1(new_sha1)) {
@@ -571,24 +570,32 @@ static const char *update(struct command *cmd, struct
shallow_info *si)
}
if (delete_ref(namespaced_name, old_sha1, 0)) {
rp_error(failed to delete %s, name);
- return failed to delete;
+ return xstrdup(failed to delete);
}
return NULL; /* good */
}
else {
+ struct strbuf err = STRBUF_INIT;
+ struct ref_transaction *transaction;
+
if (shallow_update si-shallow_ref[cmd-index]
update_shallow_ref(cmd, si))
- return shallow error;
-
-