* [PATCH v12 06/41] refs.c: add an err argument to repack_without_refs
2014-05-29 16:07 [PATCH v12 00/44] Use ref transactions for all ref updates Ronnie Sahlberg
@ 2014-05-29 16:07 ` Ronnie Sahlberg
2014-05-29 18:17 ` Jonathan Nieder
2014-05-29 16:07 ` [PATCH v12 08/41] refs.c: add an err argument to delete_ref_loose Ronnie Sahlberg
` (13 subsequent siblings)
14 siblings, 1 reply; 18+ messages in thread
From: Ronnie Sahlberg @ 2014-05-29 16:07 UTC (permalink / raw)
To: git; +Cc: jrnieder, Ronnie Sahlberg
Update repack_without_refs to take an err argument and update it if there
is a failure. Pass the err variable from ref_transaction_commit to this
function so that callers can print a meaningful error message if _commit
fails due to a problem in repack_without_refs.
Add a new function unable_to_lock_message that takes a strbuf argument and
fills in the reason for the failure.
In commit_packed_refs, make sure that we propagate any errno that
commit_lock_file might have set back to our caller.
Signed-off-by: Ronnie Sahlberg <sahlberg@google.com>
---
cache.h | 2 ++
lockfile.c | 21 ++++++++++++---------
refs.c | 25 +++++++++++++++++++------
3 files changed, 33 insertions(+), 15 deletions(-)
diff --git a/cache.h b/cache.h
index 8c6cdc2..5858da8 100644
--- a/cache.h
+++ b/cache.h
@@ -559,6 +559,8 @@ struct lock_file {
#define LOCK_DIE_ON_ERROR 1
#define LOCK_NODEREF 2
extern int unable_to_lock_error(const char *path, int err);
+extern void unable_to_lock_message(const char *path, int err,
+ struct strbuf *buf);
extern NORETURN void unable_to_lock_index_die(const char *path, int err);
extern int hold_lock_file_for_update(struct lock_file *, const char *path, int);
extern int hold_lock_file_for_append(struct lock_file *, const char *path, int);
diff --git a/lockfile.c b/lockfile.c
index 8fbcb6a..92e0397 100644
--- a/lockfile.c
+++ b/lockfile.c
@@ -157,33 +157,36 @@ static int lock_file(struct lock_file *lk, const char *path, int flags)
return lk->fd;
}
-static char *unable_to_lock_message(const char *path, int err)
+void unable_to_lock_message(const char *path, int err, struct strbuf *buf)
{
- struct strbuf buf = STRBUF_INIT;
if (err == EEXIST) {
- strbuf_addf(&buf, "Unable to create '%s.lock': %s.\n\n"
+ strbuf_addf(buf, "Unable to create '%s.lock': %s.\n\n"
"If no other git process is currently running, this probably means a\n"
"git process crashed in this repository earlier. Make sure no other git\n"
"process is running and remove the file manually to continue.",
absolute_path(path), strerror(err));
} else
- strbuf_addf(&buf, "Unable to create '%s.lock': %s",
+ strbuf_addf(buf, "Unable to create '%s.lock': %s",
absolute_path(path), strerror(err));
- return strbuf_detach(&buf, NULL);
}
int unable_to_lock_error(const char *path, int err)
{
- char *msg = unable_to_lock_message(path, err);
- error("%s", msg);
- free(msg);
+ struct strbuf buf = STRBUF_INIT;
+
+ unable_to_lock_message(path, err, &buf);
+ error("%s", buf.buf);
+ strbuf_release(&buf);
return -1;
}
NORETURN void unable_to_lock_index_die(const char *path, int err)
{
- die("%s", unable_to_lock_message(path, err));
+ struct strbuf buf = STRBUF_INIT;
+
+ unable_to_lock_message(path, err, &buf);
+ die("%s", buf.buf);
}
int hold_lock_file_for_update(struct lock_file *lk, const char *path, int flags)
diff --git a/refs.c b/refs.c
index 25c3a93..6e28841 100644
--- a/refs.c
+++ b/refs.c
@@ -2208,6 +2208,7 @@ int commit_packed_refs(void)
struct packed_ref_cache *packed_ref_cache =
get_packed_ref_cache(&ref_cache);
int error = 0;
+ int save_errno = 0;
if (!packed_ref_cache->lock)
die("internal error: packed-refs not locked");
@@ -2217,10 +2218,13 @@ int commit_packed_refs(void)
do_for_each_entry_in_dir(get_packed_ref_dir(packed_ref_cache),
0, write_packed_entry_fn,
&packed_ref_cache->lock->fd);
- if (commit_lock_file(packed_ref_cache->lock))
+ if (commit_lock_file(packed_ref_cache->lock)) {
+ save_errno = errno;
error = -1;
+ }
packed_ref_cache->lock = NULL;
release_packed_ref_cache(packed_ref_cache);
+ errno = save_errno;
return error;
}
@@ -2427,12 +2431,12 @@ static int curate_packed_ref_fn(struct ref_entry *entry, void *cb_data)
return 0;
}
-static int repack_without_refs(const char **refnames, int n)
+static int repack_without_refs(const char **refnames, int n, struct strbuf *err)
{
struct ref_dir *packed;
struct string_list refs_to_delete = STRING_LIST_INIT_DUP;
struct string_list_item *ref_to_delete;
- int i, removed = 0;
+ int i, ret, removed = 0;
/* Look for a packed ref */
for (i = 0; i < n; i++)
@@ -2444,6 +2448,11 @@ static int repack_without_refs(const char **refnames, int n)
return 0; /* no refname exists in packed refs */
if (lock_packed_refs(0)) {
+ if (err) {
+ unable_to_lock_message(git_path("packed-refs"), errno,
+ err);
+ return -1;
+ }
unable_to_lock_error(git_path("packed-refs"), errno);
return error("cannot delete '%s' from packed refs", refnames[i]);
}
@@ -2470,12 +2479,16 @@ static int repack_without_refs(const char **refnames, int n)
}
/* Write what remains */
- return commit_packed_refs();
+ ret = commit_packed_refs();
+ if (ret && err)
+ strbuf_addf(err, "unable to overwrite old ref-pack file: %s",
+ strerror(errno));
+ return ret;
}
static int repack_without_ref(const char *refname)
{
- return repack_without_refs(&refname, 1);
+ return repack_without_refs(&refname, 1, NULL);
}
static int delete_ref_loose(struct ref_lock *lock, int flag)
@@ -3481,7 +3494,7 @@ int ref_transaction_commit(struct ref_transaction *transaction,
}
}
- ret |= repack_without_refs(delnames, delnum);
+ ret |= repack_without_refs(delnames, delnum, err);
for (i = 0; i < delnum; i++)
unlink_or_warn(git_path("logs/%s", delnames[i]));
clear_loose_ref_cache(&ref_cache);
--
2.0.0.rc3.474.g3833130
^ permalink raw reply related [flat|nested] 18+ messages in thread
* Re: [PATCH v12 06/41] refs.c: add an err argument to repack_without_refs
2014-05-29 16:07 ` [PATCH v12 06/41] refs.c: add an err argument to repack_without_refs Ronnie Sahlberg
@ 2014-05-29 18:17 ` Jonathan Nieder
2014-06-03 20:55 ` Ronnie Sahlberg
0 siblings, 1 reply; 18+ messages in thread
From: Jonathan Nieder @ 2014-05-29 18:17 UTC (permalink / raw)
To: Ronnie Sahlberg; +Cc: git, Michael Haggerty
Hi,
Ronnie Sahlberg wrote:
> Update repack_without_refs to take an err argument and update it if there
> is a failure. Pass the err variable from ref_transaction_commit to this
> function so that callers can print a meaningful error message if _commit
> fails due to a problem in repack_without_refs.
>
> Add a new function unable_to_lock_message that takes a strbuf argument and
> fills in the reason for the failure.
>
> In commit_packed_refs, make sure that we propagate any errno that
> commit_lock_file might have set back to our caller.
>
> Signed-off-by: Ronnie Sahlberg <sahlberg@google.com>
> ---
> cache.h | 2 ++
> lockfile.c | 21 ++++++++++++---------
> refs.c | 25 +++++++++++++++++++------
> 3 files changed, 33 insertions(+), 15 deletions(-)
I don't want to sound like a broken record, but this still has the
same issues I described before at
http://thread.gmane.org/gmane.comp.version-control.git/250197/focus=250309.
The commit message or documentation or notes after the three dashes
above could explain what I missed when making my suggestions.
Otherwise I get no reality check as a reviewer, other reviewers get
less insight into what's happening in the patch, people in the future
looking into the patch don't understand its design as well, etc.
As a general rule, that is a good practice anyway --- even when a
reviewer was confused, what they got confused about can be an
indication of where to make the code or design documentation (commit
message) more clear, and when reposting a patch it can be a good
opportunity to explain how the patch evolved.
What would be wrong with the line of API documentation and the TODO
comment for a known bug I suggested? If they are a bad idea, can you
explain that so I can learn from it? Or if they were confusing, would
you like a patch that explains what I mean?
Jonathan
^ permalink raw reply [flat|nested] 18+ messages in thread
* Re: [PATCH v12 06/41] refs.c: add an err argument to repack_without_refs
2014-05-29 18:17 ` Jonathan Nieder
@ 2014-06-03 20:55 ` Ronnie Sahlberg
0 siblings, 0 replies; 18+ messages in thread
From: Ronnie Sahlberg @ 2014-06-03 20:55 UTC (permalink / raw)
To: Jonathan Nieder; +Cc: git@vger.kernel.org, Michael Haggerty
Thanks.
I have done all the additions of save_errno you suggested.
On Thu, May 29, 2014 at 11:17 AM, Jonathan Nieder <jrnieder@gmail.com> wrote:
> Hi,
>
> Ronnie Sahlberg wrote:
>
>> Update repack_without_refs to take an err argument and update it if there
>> is a failure. Pass the err variable from ref_transaction_commit to this
>> function so that callers can print a meaningful error message if _commit
>> fails due to a problem in repack_without_refs.
>>
>> Add a new function unable_to_lock_message that takes a strbuf argument and
>> fills in the reason for the failure.
>>
>> In commit_packed_refs, make sure that we propagate any errno that
>> commit_lock_file might have set back to our caller.
>>
>> Signed-off-by: Ronnie Sahlberg <sahlberg@google.com>
>> ---
>> cache.h | 2 ++
>> lockfile.c | 21 ++++++++++++---------
>> refs.c | 25 +++++++++++++++++++------
>> 3 files changed, 33 insertions(+), 15 deletions(-)
>
> I don't want to sound like a broken record, but this still has the
> same issues I described before at
> http://thread.gmane.org/gmane.comp.version-control.git/250197/focus=250309.
>
> The commit message or documentation or notes after the three dashes
> above could explain what I missed when making my suggestions.
> Otherwise I get no reality check as a reviewer, other reviewers get
> less insight into what's happening in the patch, people in the future
> looking into the patch don't understand its design as well, etc.
>
> As a general rule, that is a good practice anyway --- even when a
> reviewer was confused, what they got confused about can be an
> indication of where to make the code or design documentation (commit
> message) more clear, and when reposting a patch it can be a good
> opportunity to explain how the patch evolved.
>
> What would be wrong with the line of API documentation and the TODO
> comment for a known bug I suggested? If they are a bad idea, can you
> explain that so I can learn from it? Or if they were confusing, would
> you like a patch that explains what I mean?
>
> Jonathan
^ permalink raw reply [flat|nested] 18+ messages in thread
* [PATCH v12 08/41] refs.c: add an err argument to delete_ref_loose
2014-05-29 16:07 [PATCH v12 00/44] Use ref transactions for all ref updates Ronnie Sahlberg
2014-05-29 16:07 ` [PATCH v12 06/41] refs.c: add an err argument to repack_without_refs Ronnie Sahlberg
@ 2014-05-29 16:07 ` Ronnie Sahlberg
2014-05-29 16:07 ` [PATCH v12 16/41] refs.c: add transaction.status and track OPEN/CLOSED/ERROR Ronnie Sahlberg
` (12 subsequent siblings)
14 siblings, 0 replies; 18+ messages in thread
From: Ronnie Sahlberg @ 2014-05-29 16:07 UTC (permalink / raw)
To: git; +Cc: jrnieder, Ronnie Sahlberg
Add an err argument to delete_loose_ref so that we can pass a descriptive
error string back to the caller. Pass the err argument from transaction
commit to this function so that transaction users will have a nice error
string if the transaction failed due to delete_loose_ref.
Add a new function unlink_or_err that we can call from delete_ref_loose. This
function is similar to unlink_or_warn except that we can pass it an err
argument. If err is non-NULL the function will populate err instead of
printing a warning().
Signed-off-by: Ronnie Sahlberg <sahlberg@google.com>
---
refs.c | 35 +++++++++++++++++++++++++++++------
1 file changed, 29 insertions(+), 6 deletions(-)
diff --git a/refs.c b/refs.c
index 9d079ec..d768a5e 100644
--- a/refs.c
+++ b/refs.c
@@ -2491,16 +2491,38 @@ static int repack_without_ref(const char *refname)
return repack_without_refs(&refname, 1, NULL);
}
-static int delete_ref_loose(struct ref_lock *lock, int flag)
+static int add_err_if_unremovable(const char *op, const char *file,
+ struct strbuf *e, int rc)
+{
+ int err = errno;
+ if (rc < 0 && errno != ENOENT) {
+ strbuf_addf(e, "unable to %s %s: %s",
+ op, file, strerror(errno));
+ errno = err;
+ return -1;
+ }
+ return 0;
+}
+
+static int unlink_or_err(const char *file, struct strbuf *err)
+{
+ if (err)
+ return add_err_if_unremovable("unlink", file, err,
+ unlink(file));
+ else
+ return unlink_or_warn(file);
+}
+
+static int delete_ref_loose(struct ref_lock *lock, int flag, struct strbuf *err)
{
if (!(flag & REF_ISPACKED) || flag & REF_ISSYMREF) {
/* loose */
- int err, i = strlen(lock->lk->filename) - 5; /* .lock */
+ int res, i = strlen(lock->lk->filename) - 5; /* .lock */
lock->lk->filename[i] = 0;
- err = unlink_or_warn(lock->lk->filename);
+ res = unlink_or_err(lock->lk->filename, err);
lock->lk->filename[i] = '.';
- if (err && errno != ENOENT)
+ if (res && errno != ENOENT)
return 1;
}
return 0;
@@ -2514,7 +2536,7 @@ int delete_ref(const char *refname, const unsigned char *sha1, int delopt)
lock = lock_ref_sha1_basic(refname, sha1, delopt, &flag);
if (!lock)
return 1;
- ret |= delete_ref_loose(lock, flag);
+ ret |= delete_ref_loose(lock, flag, NULL);
/* removing the loose one could have resurrected an earlier
* packed one. Also, if it was not loose we need to repack
@@ -3494,7 +3516,8 @@ int ref_transaction_commit(struct ref_transaction *transaction,
if (update->lock) {
delnames[delnum++] = update->lock->ref_name;
- ret |= delete_ref_loose(update->lock, update->type);
+ ret |= delete_ref_loose(update->lock, update->type,
+ err);
}
}
--
2.0.0.rc3.474.g3833130
^ permalink raw reply related [flat|nested] 18+ messages in thread
* [PATCH v12 16/41] refs.c: add transaction.status and track OPEN/CLOSED/ERROR
2014-05-29 16:07 [PATCH v12 00/44] Use ref transactions for all ref updates Ronnie Sahlberg
2014-05-29 16:07 ` [PATCH v12 06/41] refs.c: add an err argument to repack_without_refs Ronnie Sahlberg
2014-05-29 16:07 ` [PATCH v12 08/41] refs.c: add an err argument to delete_ref_loose Ronnie Sahlberg
@ 2014-05-29 16:07 ` Ronnie Sahlberg
2014-05-29 16:07 ` [PATCH v12 24/41] receive-pack.c: use a reference transaction for updating the refs Ronnie Sahlberg
` (11 subsequent siblings)
14 siblings, 0 replies; 18+ messages in thread
From: Ronnie Sahlberg @ 2014-05-29 16:07 UTC (permalink / raw)
To: git; +Cc: jrnieder, Ronnie Sahlberg
Track the status of a transaction in a new status field. Check the field for
sanity, i.e. that status must be OPEN when _commit/_create/_delete or
_update is called or else die(BUG:...)
Signed-off-by: Ronnie Sahlberg <sahlberg@google.com>
---
refs.c | 36 +++++++++++++++++++++++++++++++++++-
1 file changed, 35 insertions(+), 1 deletion(-)
diff --git a/refs.c b/refs.c
index b5186cd..00d8fc9 100644
--- a/refs.c
+++ b/refs.c
@@ -3331,6 +3331,30 @@ struct ref_update {
};
/*
+ * Transaction states.
+ * OPEN: The transaction is in a valid state and can accept new updates.
+ * An OPEN transaction can be committed.
+ * CLOSED: If an open transaction is successfully committed the state will
+ * change to CLOSED. No further changes can be made to a CLOSED
+ * transaction.
+ * CLOSED means that all updates have been successfully committed and
+ * the only thing that remains is to free the completed transaction.
+ * ERROR: The transaction has failed and is no longer committable.
+ * Eventhough the transaction can no longer be committed it is still
+ * possible to add additional updates to the transaction. The reason
+ * for this is to allow a caller to continue trying more updates
+ * so that a caller can report a list of ALL updates that would fail
+ * instead of just the first update that fails.
+ * An ERRORed transaction can not be committed and must be rolled
+ * back using transaction_free.
+ */
+enum ref_transaction_state {
+ REF_TRANSACTION_OPEN = 0,
+ REF_TRANSACTION_CLOSED = 1,
+ REF_TRANSACTION_ERROR = 2,
+};
+
+/*
* Data structure for holding a reference transaction, which can
* consist of checks and updates to multiple references, carried out
* as atomically as possible. This structure is opaque to callers.
@@ -3339,6 +3363,8 @@ struct ref_transaction {
struct ref_update **updates;
size_t alloc;
size_t nr;
+ enum ref_transaction_state state;
+ int status;
};
struct ref_transaction *ref_transaction_begin(struct strbuf *err)
@@ -3476,8 +3502,13 @@ int ref_transaction_commit(struct ref_transaction *transaction,
int n = transaction->nr;
struct ref_update **updates = transaction->updates;
- if (!n)
+ if (transaction->state != REF_TRANSACTION_OPEN)
+ return transaction->status;
+
+ if (!n) {
+ transaction->state = REF_TRANSACTION_CLOSED;
return 0;
+ }
/* Allocate work space */
delnames = xmalloc(sizeof(*delnames) * n);
@@ -3540,6 +3571,9 @@ int ref_transaction_commit(struct ref_transaction *transaction,
clear_loose_ref_cache(&ref_cache);
cleanup:
+ transaction->state = ret ? REF_TRANSACTION_ERROR
+ : REF_TRANSACTION_CLOSED;
+
for (i = 0; i < n; i++)
if (updates[i]->lock)
unlock_ref(updates[i]->lock);
--
2.0.0.rc3.474.g3833130
^ permalink raw reply related [flat|nested] 18+ messages in thread
* [PATCH v12 24/41] receive-pack.c: use a reference transaction for updating the refs
2014-05-29 16:07 [PATCH v12 00/44] Use ref transactions for all ref updates Ronnie Sahlberg
` (2 preceding siblings ...)
2014-05-29 16:07 ` [PATCH v12 16/41] refs.c: add transaction.status and track OPEN/CLOSED/ERROR Ronnie Sahlberg
@ 2014-05-29 16:07 ` Ronnie Sahlberg
2014-05-29 16:07 ` [PATCH v12 25/41] fast-import.c: use a ref transaction when dumping tags Ronnie Sahlberg
` (10 subsequent siblings)
14 siblings, 0 replies; 18+ messages in thread
From: Ronnie Sahlberg @ 2014-05-29 16:07 UTC (permalink / raw)
To: git; +Cc: jrnieder, Ronnie Sahlberg
Wrap all the ref updates inside a transaction.
Signed-off-by: Ronnie Sahlberg <sahlberg@google.com>
---
builtin/receive-pack.c | 31 ++++++++++++++++++++++---------
1 file changed, 22 insertions(+), 9 deletions(-)
diff --git a/builtin/receive-pack.c b/builtin/receive-pack.c
index c323081..13f4a63 100644
--- a/builtin/receive-pack.c
+++ b/builtin/receive-pack.c
@@ -46,6 +46,7 @@ static void *head_name_to_free;
static int sent_capabilities;
static int shallow_update;
static const char *alt_shallow_file;
+static struct string_list error_strings = STRING_LIST_INIT_DUP;
static enum deny_action parse_deny_action(const char *var, const char *value)
{
@@ -475,7 +476,6 @@ static const char *update(struct command *cmd, struct shallow_info *si)
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)) {
@@ -576,19 +576,31 @@ static const char *update(struct command *cmd, struct shallow_info *si)
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";
- lock = lock_any_ref_for_update(namespaced_name, old_sha1,
- 0, NULL);
- if (!lock) {
- rp_error("failed to lock %s", name);
- return "failed to lock";
- }
- if (write_ref_sha1(lock, new_sha1, "push")) {
- return "failed to write"; /* error() already called */
+ transaction = ref_transaction_begin(&err);
+ if (!transaction ||
+ ref_transaction_update(transaction, namespaced_name,
+ new_sha1, old_sha1, 0, 1, &err) ||
+ ref_transaction_commit(transaction, "push", &err)) {
+
+ const char *str;
+ string_list_append(&error_strings, err.buf);
+ str = error_strings.items[error_strings.nr - 1].string;
+ strbuf_release(&err);
+
+ ref_transaction_free(transaction);
+ rp_error("%s", str);
+ return str;
}
+
+ ref_transaction_free(transaction);
+ strbuf_release(&err);
return NULL; /* good */
}
}
@@ -1215,5 +1227,6 @@ int cmd_receive_pack(int argc, const char **argv, const char *prefix)
packet_flush(1);
sha1_array_clear(&shallow);
sha1_array_clear(&ref);
+ string_list_clear(&error_strings, 0);
return 0;
}
--
2.0.0.rc3.474.g3833130
^ permalink raw reply related [flat|nested] 18+ messages in thread
* [PATCH v12 25/41] fast-import.c: use a ref transaction when dumping tags
2014-05-29 16:07 [PATCH v12 00/44] Use ref transactions for all ref updates Ronnie Sahlberg
` (3 preceding siblings ...)
2014-05-29 16:07 ` [PATCH v12 24/41] receive-pack.c: use a reference transaction for updating the refs Ronnie Sahlberg
@ 2014-05-29 16:07 ` Ronnie Sahlberg
2014-05-29 16:07 ` [PATCH v12 26/41] walker.c: use ref transaction for ref updates Ronnie Sahlberg
` (9 subsequent siblings)
14 siblings, 0 replies; 18+ messages in thread
From: Ronnie Sahlberg @ 2014-05-29 16:07 UTC (permalink / raw)
To: git; +Cc: jrnieder, Ronnie Sahlberg
Signed-off-by: Ronnie Sahlberg <sahlberg@google.com>
---
fast-import.c | 29 +++++++++++++++++++++++------
1 file changed, 23 insertions(+), 6 deletions(-)
diff --git a/fast-import.c b/fast-import.c
index 4a7b196..587ef4a 100644
--- a/fast-import.c
+++ b/fast-import.c
@@ -1735,15 +1735,32 @@ static void dump_tags(void)
{
static const char *msg = "fast-import";
struct tag *t;
- struct ref_lock *lock;
- char ref_name[PATH_MAX];
+ struct strbuf ref_name = STRBUF_INIT;
+ struct strbuf err = STRBUF_INIT;
+ struct ref_transaction *transaction;
+ transaction = ref_transaction_begin(&err);
+ if (!transaction) {
+ failure |= error("%s", err.buf);
+ goto cleanup;
+ }
for (t = first_tag; t; t = t->next_tag) {
- sprintf(ref_name, "tags/%s", t->name);
- lock = lock_ref_sha1(ref_name, NULL);
- if (!lock || write_ref_sha1(lock, t->sha1, msg) < 0)
- failure |= error("Unable to update %s", ref_name);
+ strbuf_reset(&ref_name);
+ strbuf_addf(&ref_name, "refs/tags/%s", t->name);
+
+ if (ref_transaction_update(transaction, ref_name.buf, t->sha1,
+ NULL, 0, 0, &err)) {
+ failure |= error("%s", err.buf);
+ goto cleanup;
+ }
}
+ if (ref_transaction_commit(transaction, msg, &err))
+ failure |= error("%s", err.buf);
+
+ cleanup:
+ ref_transaction_free(transaction);
+ strbuf_release(&ref_name);
+ strbuf_release(&err);
}
static void dump_marks_helper(FILE *f,
--
2.0.0.rc3.474.g3833130
^ permalink raw reply related [flat|nested] 18+ messages in thread
* [PATCH v12 26/41] walker.c: use ref transaction for ref updates
2014-05-29 16:07 [PATCH v12 00/44] Use ref transactions for all ref updates Ronnie Sahlberg
` (4 preceding siblings ...)
2014-05-29 16:07 ` [PATCH v12 25/41] fast-import.c: use a ref transaction when dumping tags Ronnie Sahlberg
@ 2014-05-29 16:07 ` Ronnie Sahlberg
2014-05-29 16:07 ` [PATCH v12 31/41] refs.c: make prune_ref use a transaction to delete the ref Ronnie Sahlberg
` (8 subsequent siblings)
14 siblings, 0 replies; 18+ messages in thread
From: Ronnie Sahlberg @ 2014-05-29 16:07 UTC (permalink / raw)
To: git; +Cc: jrnieder, Ronnie Sahlberg
Switch to using ref transactions in walker_fetch(). As part of the refactoring
to use ref transactions we also fix a potential memory leak where in the
original code if write_ref_sha1() would fail we would end up returning from
the function without free()ing the msg string.
Note that this function is only called when fetching from a remote HTTP
repository onto the local (most of the time single-user) repository which
likely means that the type of collissions that the previous locking would
protect against and cause the fetch to fail for to be even more rare.
Signed-off-by: Ronnie Sahlberg <sahlberg@google.com>
---
walker.c | 59 +++++++++++++++++++++++++++++++++++------------------------
1 file changed, 35 insertions(+), 24 deletions(-)
diff --git a/walker.c b/walker.c
index 1dd86b8..60d9f9e 100644
--- a/walker.c
+++ b/walker.c
@@ -251,39 +251,36 @@ void walker_targets_free(int targets, char **target, const char **write_ref)
int walker_fetch(struct walker *walker, int targets, char **target,
const char **write_ref, const char *write_ref_log_details)
{
- struct ref_lock **lock = xcalloc(targets, sizeof(struct ref_lock *));
+ struct strbuf ref_name = STRBUF_INIT;
+ struct strbuf err = STRBUF_INIT;
+ struct ref_transaction *transaction = NULL;
unsigned char *sha1 = xmalloc(targets * 20);
- char *msg;
- int ret;
+ char *msg = NULL;
int i;
save_commit_buffer = 0;
- for (i = 0; i < targets; i++) {
- if (!write_ref || !write_ref[i])
- continue;
-
- lock[i] = lock_ref_sha1(write_ref[i], NULL);
- if (!lock[i]) {
- error("Can't lock ref %s", write_ref[i]);
- goto unlock_and_fail;
+ if (write_ref) {
+ transaction = ref_transaction_begin(&err);
+ if (!transaction) {
+ error("%s", err.buf);
+ goto rollback_and_fail;
}
}
-
if (!walker->get_recover)
for_each_ref(mark_complete, NULL);
for (i = 0; i < targets; i++) {
if (interpret_target(walker, target[i], &sha1[20 * i])) {
error("Could not interpret response from server '%s' as something to pull", target[i]);
- goto unlock_and_fail;
+ goto rollback_and_fail;
}
if (process(walker, lookup_unknown_object(&sha1[20 * i])))
- goto unlock_and_fail;
+ goto rollback_and_fail;
}
if (loop(walker))
- goto unlock_and_fail;
+ goto rollback_and_fail;
if (write_ref_log_details) {
msg = xmalloc(strlen(write_ref_log_details) + 12);
@@ -294,19 +291,33 @@ int walker_fetch(struct walker *walker, int targets, char **target,
for (i = 0; i < targets; i++) {
if (!write_ref || !write_ref[i])
continue;
- ret = write_ref_sha1(lock[i], &sha1[20 * i], msg ? msg : "fetch (unknown)");
- lock[i] = NULL;
- if (ret)
- goto unlock_and_fail;
+ strbuf_reset(&ref_name);
+ strbuf_addf(&ref_name, "refs/%s", write_ref[i]);
+ if (ref_transaction_update(transaction, ref_name.buf,
+ &sha1[20 * i], NULL, 0, 0,
+ &err)) {
+ error("%s", err.buf);
+ goto rollback_and_fail;
+ }
+ }
+ if (write_ref) {
+ if (ref_transaction_commit(transaction,
+ msg ? msg : "fetch (unknown)",
+ &err)) {
+ error("%s", err.buf);
+ goto rollback_and_fail;
+ }
+ ref_transaction_free(transaction);
}
- free(msg);
+ free(msg);
return 0;
-unlock_and_fail:
- for (i = 0; i < targets; i++)
- if (lock[i])
- unlock_ref(lock[i]);
+rollback_and_fail:
+ ref_transaction_free(transaction);
+ free(msg);
+ strbuf_release(&err);
+ strbuf_release(&ref_name);
return -1;
}
--
2.0.0.rc3.474.g3833130
^ permalink raw reply related [flat|nested] 18+ messages in thread
* [PATCH v12 31/41] refs.c: make prune_ref use a transaction to delete the ref
2014-05-29 16:07 [PATCH v12 00/44] Use ref transactions for all ref updates Ronnie Sahlberg
` (5 preceding siblings ...)
2014-05-29 16:07 ` [PATCH v12 26/41] walker.c: use ref transaction for ref updates Ronnie Sahlberg
@ 2014-05-29 16:07 ` Ronnie Sahlberg
2014-05-29 16:07 ` [PATCH v12 32/41] refs.c: make delete_ref use a transaction Ronnie Sahlberg
` (7 subsequent siblings)
14 siblings, 0 replies; 18+ messages in thread
From: Ronnie Sahlberg @ 2014-05-29 16:07 UTC (permalink / raw)
To: git; +Cc: jrnieder, Ronnie Sahlberg
Change prune_ref to delete the ref using a ref transaction. To do this we also
need to add a new flag REF_ISPRUNING that will tell the transaction that we
do not want to delete this ref from the packed refs. This flag is private to
refs.c and not exposed to external callers.
Signed-off-by: Ronnie Sahlberg <sahlberg@google.com>
---
refs.c | 28 +++++++++++++++++++++-------
refs.h | 11 ++++++++++-
2 files changed, 31 insertions(+), 8 deletions(-)
diff --git a/refs.c b/refs.c
index 7cea694..60593d7 100644
--- a/refs.c
+++ b/refs.c
@@ -30,6 +30,12 @@ static inline int bad_ref_char(int ch)
}
/*
+ * Used as a flag to ref_transaction_delete when a loose ref is being
+ * pruned.
+ */
+#define REF_ISPRUNING 0x0100
+
+/*
* Try to read one refname component from the front of refname. Return
* the length of the component found, or -1 if the component is not
* legal.
@@ -2328,17 +2334,24 @@ static void try_remove_empty_parents(char *name)
/* make sure nobody touched the ref, and unlink */
static void prune_ref(struct ref_to_prune *r)
{
- struct ref_lock *lock;
+ struct ref_transaction *transaction;
+ struct strbuf err = STRBUF_INIT;
if (check_refname_format(r->name + 5, 0))
return;
- lock = lock_ref_sha1_basic(r->name, r->sha1, 0, NULL);
- if (lock) {
- unlink_or_warn(git_path("%s", r->name));
- unlock_ref(lock);
- try_remove_empty_parents(r->name);
+ transaction = ref_transaction_begin(&err);
+ if (!transaction ||
+ ref_transaction_delete(transaction, r->name, r->sha1,
+ REF_ISPRUNING, 1, &err) ||
+ ref_transaction_commit(transaction, NULL, &err)) {
+ ref_transaction_free(transaction);
+ error("%s", err.buf);
+ strbuf_release(&err);
+ return;
}
+ ref_transaction_free(transaction);
+ try_remove_empty_parents(r->name);
}
static void prune_refs(struct ref_to_prune *r)
@@ -3536,9 +3549,10 @@ int ref_transaction_commit(struct ref_transaction *transaction,
struct ref_update *update = updates[i];
if (update->lock) {
- delnames[delnum++] = update->lock->ref_name;
ret |= delete_ref_loose(update->lock, update->type,
err);
+ if (!(update->flags & REF_ISPRUNING))
+ delnames[delnum++] = update->lock->ref_name;
}
}
diff --git a/refs.h b/refs.h
index c38ee09..dee7c8f 100644
--- a/refs.h
+++ b/refs.h
@@ -171,8 +171,17 @@ extern int ref_exists(const char *);
*/
extern int peel_ref(const char *refname, unsigned char *sha1);
-/** Locks any ref (for 'HEAD' type refs). */
+/*
+ * Flags controlling lock_any_ref_for_update(), ref_transaction_update(),
+ * ref_transaction_create(), etc.
+ * REF_NODEREF: act on the ref directly, instead of dereferencing
+ * symbolic references.
+ *
+ * Flags >= 0x100 are reserved for internal use.
+ */
#define REF_NODEREF 0x01
+
+/** Locks any ref (for 'HEAD' type refs). */
extern struct ref_lock *lock_any_ref_for_update(const char *refname,
const unsigned char *old_sha1,
int flags, int *type_p);
--
2.0.0.rc3.474.g3833130
^ permalink raw reply related [flat|nested] 18+ messages in thread
* [PATCH v12 32/41] refs.c: make delete_ref use a transaction
2014-05-29 16:07 [PATCH v12 00/44] Use ref transactions for all ref updates Ronnie Sahlberg
` (6 preceding siblings ...)
2014-05-29 16:07 ` [PATCH v12 31/41] refs.c: make prune_ref use a transaction to delete the ref Ronnie Sahlberg
@ 2014-05-29 16:07 ` Ronnie Sahlberg
2014-05-29 16:07 ` [PATCH v12 33/41] refs.c: pass the ref log message to _create/delete/update instead of _commit Ronnie Sahlberg
` (6 subsequent siblings)
14 siblings, 0 replies; 18+ messages in thread
From: Ronnie Sahlberg @ 2014-05-29 16:07 UTC (permalink / raw)
To: git; +Cc: jrnieder, Ronnie Sahlberg
Change delete_ref to use a ref transaction for the deletion. At the same time
since we no longer have any callers of repack_without_ref we can now delete
this function.
Change delete_ref to return 0 on success and -1 on failure instead of the
previous 0 on success either 1 or -1 on failure.
Signed-off-by: Ronnie Sahlberg <sahlberg@google.com>
---
refs.c | 36 ++++++++++++++----------------------
1 file changed, 14 insertions(+), 22 deletions(-)
diff --git a/refs.c b/refs.c
index 60593d7..e2c2249 100644
--- a/refs.c
+++ b/refs.c
@@ -2494,11 +2494,6 @@ static int repack_without_refs(const char **refnames, int n, struct strbuf *err)
return ret;
}
-static int repack_without_ref(const char *refname)
-{
- return repack_without_refs(&refname, 1, NULL);
-}
-
static int add_err_if_unremovable(const char *op, const char *file,
struct strbuf *e, int rc)
{
@@ -2538,24 +2533,21 @@ static int delete_ref_loose(struct ref_lock *lock, int flag, struct strbuf *err)
int delete_ref(const char *refname, const unsigned char *sha1, int delopt)
{
- struct ref_lock *lock;
- int ret = 0, flag = 0;
-
- lock = lock_ref_sha1_basic(refname, sha1, delopt, &flag);
- if (!lock)
- return 1;
- ret |= delete_ref_loose(lock, flag, NULL);
-
- /* removing the loose one could have resurrected an earlier
- * packed one. Also, if it was not loose we need to repack
- * without it.
- */
- ret |= repack_without_ref(lock->ref_name);
+ struct ref_transaction *transaction;
+ struct strbuf err = STRBUF_INIT;
- unlink_or_warn(git_path("logs/%s", lock->ref_name));
- clear_loose_ref_cache(&ref_cache);
- unlock_ref(lock);
- return ret;
+ transaction = ref_transaction_begin(&err);
+ if (!transaction ||
+ ref_transaction_delete(transaction, refname, sha1, delopt,
+ sha1 && !is_null_sha1(sha1), &err) ||
+ ref_transaction_commit(transaction, NULL, &err)) {
+ error("%s", err.buf);
+ ref_transaction_free(transaction);
+ strbuf_release(&err);
+ return -1;
+ }
+ ref_transaction_free(transaction);
+ return 0;
}
/*
--
2.0.0.rc3.474.g3833130
^ permalink raw reply related [flat|nested] 18+ messages in thread
* [PATCH v12 33/41] refs.c: pass the ref log message to _create/delete/update instead of _commit
2014-05-29 16:07 [PATCH v12 00/44] Use ref transactions for all ref updates Ronnie Sahlberg
` (7 preceding siblings ...)
2014-05-29 16:07 ` [PATCH v12 32/41] refs.c: make delete_ref use a transaction Ronnie Sahlberg
@ 2014-05-29 16:07 ` Ronnie Sahlberg
2014-05-29 16:07 ` [PATCH v12 36/41] refs.c: move the check for valid refname to lock_ref_sha1_basic Ronnie Sahlberg
` (5 subsequent siblings)
14 siblings, 0 replies; 18+ messages in thread
From: Ronnie Sahlberg @ 2014-05-29 16:07 UTC (permalink / raw)
To: git; +Cc: jrnieder, Ronnie Sahlberg
Change the reference transactions so that we pass the reflog message
through to the create/delete/update function instead of the commit message.
This allows for individual messages for each change in a multi ref
transaction.
Signed-off-by: Ronnie Sahlberg <sahlberg@google.com>
---
branch.c | 4 ++--
builtin/commit.c | 4 ++--
builtin/fetch.c | 3 +--
builtin/receive-pack.c | 7 ++++---
builtin/replace.c | 4 ++--
builtin/tag.c | 4 ++--
builtin/update-ref.c | 13 +++++++------
fast-import.c | 8 ++++----
refs.c | 34 +++++++++++++++++++++-------------
refs.h | 8 ++++----
sequencer.c | 4 ++--
walker.c | 5 ++---
12 files changed, 53 insertions(+), 45 deletions(-)
diff --git a/branch.c b/branch.c
index c1eae00..e0439af 100644
--- a/branch.c
+++ b/branch.c
@@ -301,8 +301,8 @@ void create_branch(const char *head,
transaction = ref_transaction_begin(&err);
if (!transaction ||
ref_transaction_update(transaction, ref.buf, sha1,
- null_sha1, 0, !forcing, &err) ||
- ref_transaction_commit(transaction, msg, &err))
+ null_sha1, 0, !forcing, msg, &err) ||
+ ref_transaction_commit(transaction, &err))
die("%s", err.buf);
ref_transaction_free(transaction);
}
diff --git a/builtin/commit.c b/builtin/commit.c
index 7db194f..608296c 100644
--- a/builtin/commit.c
+++ b/builtin/commit.c
@@ -1721,8 +1721,8 @@ int cmd_commit(int argc, const char **argv, const char *prefix)
ref_transaction_update(transaction, "HEAD", sha1,
current_head ?
current_head->object.sha1 : NULL,
- 0, !!current_head, &err) ||
- ref_transaction_commit(transaction, sb.buf, &err)) {
+ 0, !!current_head, sb.buf, &err) ||
+ ref_transaction_commit(transaction, &err)) {
rollback_index_files();
die("%s", err.buf);
}
diff --git a/builtin/fetch.c b/builtin/fetch.c
index 55f457c..faa1233 100644
--- a/builtin/fetch.c
+++ b/builtin/fetch.c
@@ -673,10 +673,9 @@ static int store_updated_refs(const char *raw_url, const char *remote_name,
}
}
}
-
if (rc & STORE_REF_ERROR_DF_CONFLICT)
error(_("some local refs could not be updated; try running\n"
- " 'git remote prune %s' to remove any old, conflicting "
+ "'git remote prune %s' to remove any old, conflicting "
"branches"), remote_name);
abort:
diff --git a/builtin/receive-pack.c b/builtin/receive-pack.c
index 13f4a63..5653fa2 100644
--- a/builtin/receive-pack.c
+++ b/builtin/receive-pack.c
@@ -586,10 +586,11 @@ static const char *update(struct command *cmd, struct shallow_info *si)
transaction = ref_transaction_begin(&err);
if (!transaction ||
ref_transaction_update(transaction, namespaced_name,
- new_sha1, old_sha1, 0, 1, &err) ||
- ref_transaction_commit(transaction, "push", &err)) {
-
+ new_sha1, old_sha1, 0, 1, "push",
+ &err) ||
+ ref_transaction_commit(transaction, &err)) {
const char *str;
+
string_list_append(&error_strings, err.buf);
str = error_strings.items[error_strings.nr - 1].string;
strbuf_release(&err);
diff --git a/builtin/replace.c b/builtin/replace.c
index f24d814..09bfd40 100644
--- a/builtin/replace.c
+++ b/builtin/replace.c
@@ -160,8 +160,8 @@ static int replace_object_sha1(const char *object_ref,
transaction = ref_transaction_begin(&err);
if (!transaction ||
ref_transaction_update(transaction, ref, repl, prev,
- 0, !is_null_sha1(prev), &err) ||
- ref_transaction_commit(transaction, NULL, &err))
+ 0, !is_null_sha1(prev), NULL, &err) ||
+ ref_transaction_commit(transaction, &err))
die("%s", err.buf);
ref_transaction_free(transaction);
diff --git a/builtin/tag.c b/builtin/tag.c
index c9bfc9a..74af63e 100644
--- a/builtin/tag.c
+++ b/builtin/tag.c
@@ -705,8 +705,8 @@ int cmd_tag(int argc, const char **argv, const char *prefix)
transaction = ref_transaction_begin(&err);
if (!transaction ||
ref_transaction_update(transaction, ref.buf, object, prev,
- 0, !is_null_sha1(prev), &err) ||
- ref_transaction_commit(transaction, NULL, &err))
+ 0, !is_null_sha1(prev), NULL, &err) ||
+ ref_transaction_commit(transaction, &err))
die("%s", err.buf);
ref_transaction_free(transaction);
if (force && !is_null_sha1(prev) && hashcmp(prev, object))
diff --git a/builtin/update-ref.c b/builtin/update-ref.c
index c6ad0be..28b478a 100644
--- a/builtin/update-ref.c
+++ b/builtin/update-ref.c
@@ -16,6 +16,7 @@ static struct ref_transaction *transaction;
static char line_termination = '\n';
static int update_flags;
+static const char *msg;
static struct strbuf err = STRBUF_INIT;
/*
@@ -199,7 +200,7 @@ static const char *parse_cmd_update(struct strbuf *input, const char *next)
die("update %s: extra input: %s", refname, next);
if (ref_transaction_update(transaction, refname, new_sha1, old_sha1,
- update_flags, have_old, &err))
+ update_flags, have_old, msg, &err))
die("%s", err.buf);
update_flags = 0;
@@ -227,7 +228,7 @@ static const char *parse_cmd_create(struct strbuf *input, const char *next)
die("create %s: extra input: %s", refname, next);
if (ref_transaction_create(transaction, refname, new_sha1,
- update_flags, &err))
+ update_flags, msg, &err))
die("%s", err.buf);
update_flags = 0;
@@ -259,7 +260,7 @@ static const char *parse_cmd_delete(struct strbuf *input, const char *next)
die("delete %s: extra input: %s", refname, next);
if (ref_transaction_delete(transaction, refname, old_sha1,
- update_flags, have_old, &err))
+ update_flags, have_old, msg, &err))
die("%s", err.buf);
update_flags = 0;
@@ -292,7 +293,7 @@ static const char *parse_cmd_verify(struct strbuf *input, const char *next)
die("verify %s: extra input: %s", refname, next);
if (ref_transaction_update(transaction, refname, new_sha1, old_sha1,
- update_flags, have_old, &err))
+ update_flags, have_old, msg, &err))
die("%s", err.buf);
update_flags = 0;
@@ -345,7 +346,7 @@ static void update_refs_stdin(void)
int cmd_update_ref(int argc, const char **argv, const char *prefix)
{
- const char *refname, *oldval, *msg = NULL;
+ const char *refname, *oldval;
unsigned char sha1[20], oldsha1[20];
int delete = 0, no_deref = 0, read_stdin = 0, end_null = 0, flags = 0;
struct option options[] = {
@@ -371,7 +372,7 @@ int cmd_update_ref(int argc, const char **argv, const char *prefix)
if (end_null)
line_termination = '\0';
update_refs_stdin();
- if (ref_transaction_commit(transaction, msg, &err))
+ if (ref_transaction_commit(transaction, &err))
die("%s", err.buf);
ref_transaction_free(transaction);
return 0;
diff --git a/fast-import.c b/fast-import.c
index 587ef4a..7ca8b5a 100644
--- a/fast-import.c
+++ b/fast-import.c
@@ -1709,8 +1709,8 @@ static int update_branch(struct branch *b)
transaction = ref_transaction_begin(&err);
if (!transaction ||
ref_transaction_update(transaction, b->name, b->sha1, old_sha1,
- 0, 1, &err) ||
- ref_transaction_commit(transaction, msg, &err)) {
+ 0, 1, msg, &err) ||
+ ref_transaction_commit(transaction, &err)) {
ref_transaction_free(transaction);
error("%s", err.buf);
strbuf_release(&err);
@@ -1749,12 +1749,12 @@ static void dump_tags(void)
strbuf_addf(&ref_name, "refs/tags/%s", t->name);
if (ref_transaction_update(transaction, ref_name.buf, t->sha1,
- NULL, 0, 0, &err)) {
+ NULL, 0, 0, msg, &err)) {
failure |= error("%s", err.buf);
goto cleanup;
}
}
- if (ref_transaction_commit(transaction, msg, &err))
+ if (ref_transaction_commit(transaction, &err))
failure |= error("%s", err.buf);
cleanup:
diff --git a/refs.c b/refs.c
index 696bc4f..9c19267 100644
--- a/refs.c
+++ b/refs.c
@@ -2343,8 +2343,8 @@ static void prune_ref(struct ref_to_prune *r)
transaction = ref_transaction_begin(&err);
if (!transaction ||
ref_transaction_delete(transaction, r->name, r->sha1,
- REF_ISPRUNING, 1, &err) ||
- ref_transaction_commit(transaction, NULL, &err)) {
+ REF_ISPRUNING, 1, NULL, &err) ||
+ ref_transaction_commit(transaction, &err)) {
ref_transaction_free(transaction);
error("%s", err.buf);
strbuf_release(&err);
@@ -2539,8 +2539,8 @@ int delete_ref(const char *refname, const unsigned char *sha1, int delopt)
transaction = ref_transaction_begin(&err);
if (!transaction ||
ref_transaction_delete(transaction, refname, sha1, delopt,
- sha1 && !is_null_sha1(sha1), &err) ||
- ref_transaction_commit(transaction, NULL, &err)) {
+ sha1 && !is_null_sha1(sha1), NULL, &err) ||
+ ref_transaction_commit(transaction, &err)) {
error("%s", err.buf);
ref_transaction_free(transaction);
strbuf_release(&err);
@@ -3290,6 +3290,7 @@ struct ref_update {
int have_old; /* 1 if old_sha1 is valid, 0 otherwise */
struct ref_lock *lock;
int type;
+ char *msg;
const char refname[FLEX_ARRAY];
};
@@ -3342,9 +3343,10 @@ void ref_transaction_free(struct ref_transaction *transaction)
if (!transaction)
return;
- for (i = 0; i < transaction->nr; i++)
+ for (i = 0; i < transaction->nr; i++) {
+ free(transaction->updates[i]->msg);
free(transaction->updates[i]);
-
+ }
free(transaction->updates);
free(transaction);
}
@@ -3365,7 +3367,7 @@ int ref_transaction_update(struct ref_transaction *transaction,
const char *refname,
const unsigned char *new_sha1,
const unsigned char *old_sha1,
- int flags, int have_old,
+ int flags, int have_old, const char *msg,
struct strbuf *err)
{
struct ref_update *update;
@@ -3379,13 +3381,15 @@ int ref_transaction_update(struct ref_transaction *transaction,
update->have_old = have_old;
if (have_old)
hashcpy(update->old_sha1, old_sha1);
+ if (msg)
+ update->msg = xstrdup(msg);
return 0;
}
int ref_transaction_create(struct ref_transaction *transaction,
const char *refname,
const unsigned char *new_sha1,
- int flags,
+ int flags, const char *msg,
struct strbuf *err)
{
struct ref_update *update;
@@ -3399,13 +3403,15 @@ int ref_transaction_create(struct ref_transaction *transaction,
hashclr(update->old_sha1);
update->flags = flags;
update->have_old = 1;
+ if (msg)
+ update->msg = xstrdup(msg);
return 0;
}
int ref_transaction_delete(struct ref_transaction *transaction,
const char *refname,
const unsigned char *old_sha1,
- int flags, int have_old,
+ int flags, int have_old, const char *msg,
struct strbuf *err)
{
struct ref_update *update;
@@ -3420,6 +3426,8 @@ int ref_transaction_delete(struct ref_transaction *transaction,
assert(!is_null_sha1(old_sha1));
hashcpy(update->old_sha1, old_sha1);
}
+ if (msg)
+ update->msg = xstrdup(msg);
return 0;
}
@@ -3433,8 +3441,8 @@ int update_ref(const char *action, const char *refname,
t = ref_transaction_begin(&err);
if (!t ||
ref_transaction_update(t, refname, sha1, oldval, flags,
- !!oldval, &err) ||
- ref_transaction_commit(t, action, &err)) {
+ !!oldval, action, &err) ||
+ ref_transaction_commit(t, &err)) {
const char *str = "update_ref failed for ref '%s': %s";
ref_transaction_free(t);
@@ -3475,7 +3483,7 @@ static int ref_update_reject_duplicates(struct ref_update **updates, int n,
}
int ref_transaction_commit(struct ref_transaction *transaction,
- const char *msg, struct strbuf *err)
+ struct strbuf *err)
{
int ret = 0, delnum = 0, i;
const char **delnames;
@@ -3524,7 +3532,7 @@ int ref_transaction_commit(struct ref_transaction *transaction,
if (!is_null_sha1(update->new_sha1)) {
ret = write_ref_sha1(update->lock, update->new_sha1,
- msg);
+ update->msg);
update->lock = NULL; /* freed by write_ref_sha1 */
if (ret) {
const char *str = "Cannot update the ref '%s'.";
diff --git a/refs.h b/refs.h
index dee7c8f..5c6c20f 100644
--- a/refs.h
+++ b/refs.h
@@ -287,7 +287,7 @@ int ref_transaction_update(struct ref_transaction *transaction,
const char *refname,
const unsigned char *new_sha1,
const unsigned char *old_sha1,
- int flags, int have_old,
+ int flags, int have_old, const char *msg,
struct strbuf *err);
/*
@@ -302,7 +302,7 @@ int ref_transaction_update(struct ref_transaction *transaction,
int ref_transaction_create(struct ref_transaction *transaction,
const char *refname,
const unsigned char *new_sha1,
- int flags,
+ int flags, const char *msg,
struct strbuf *err);
/*
@@ -316,7 +316,7 @@ int ref_transaction_create(struct ref_transaction *transaction,
int ref_transaction_delete(struct ref_transaction *transaction,
const char *refname,
const unsigned char *old_sha1,
- int flags, int have_old,
+ int flags, int have_old, const char *msg,
struct strbuf *err);
/*
@@ -325,7 +325,7 @@ int ref_transaction_delete(struct ref_transaction *transaction,
* problem.
*/
int ref_transaction_commit(struct ref_transaction *transaction,
- const char *msg, struct strbuf *err);
+ struct strbuf *err);
/*
* Free an existing transaction and all associated data.
diff --git a/sequencer.c b/sequencer.c
index fd8acaf..f9906ef 100644
--- a/sequencer.c
+++ b/sequencer.c
@@ -285,8 +285,8 @@ static int fast_forward_to(const unsigned char *to, const unsigned char *from,
transaction = ref_transaction_begin(&err);
if (!transaction ||
ref_transaction_update(transaction, "HEAD", to, from,
- 0, !unborn, &err) ||
- ref_transaction_commit(transaction, sb.buf, &err)) {
+ 0, !unborn, sb.buf, &err) ||
+ ref_transaction_commit(transaction, &err)) {
ref_transaction_free(transaction);
error("%s", err.buf);
strbuf_release(&sb);
diff --git a/walker.c b/walker.c
index 60d9f9e..fd9ef87 100644
--- a/walker.c
+++ b/walker.c
@@ -295,15 +295,14 @@ int walker_fetch(struct walker *walker, int targets, char **target,
strbuf_addf(&ref_name, "refs/%s", write_ref[i]);
if (ref_transaction_update(transaction, ref_name.buf,
&sha1[20 * i], NULL, 0, 0,
+ msg ? msg : "fetch (unknown)",
&err)) {
error("%s", err.buf);
goto rollback_and_fail;
}
}
if (write_ref) {
- if (ref_transaction_commit(transaction,
- msg ? msg : "fetch (unknown)",
- &err)) {
+ if (ref_transaction_commit(transaction, &err)) {
error("%s", err.buf);
goto rollback_and_fail;
}
--
2.0.0.rc3.474.g3833130
^ permalink raw reply related [flat|nested] 18+ messages in thread
* [PATCH v12 36/41] refs.c: move the check for valid refname to lock_ref_sha1_basic
2014-05-29 16:07 [PATCH v12 00/44] Use ref transactions for all ref updates Ronnie Sahlberg
` (8 preceding siblings ...)
2014-05-29 16:07 ` [PATCH v12 33/41] refs.c: pass the ref log message to _create/delete/update instead of _commit Ronnie Sahlberg
@ 2014-05-29 16:07 ` Ronnie Sahlberg
2014-05-29 16:07 ` [PATCH v12 38/41] refs.c: pass a skip list to name_conflict_fn Ronnie Sahlberg
` (4 subsequent siblings)
14 siblings, 0 replies; 18+ messages in thread
From: Ronnie Sahlberg @ 2014-05-29 16:07 UTC (permalink / raw)
To: git; +Cc: jrnieder, Ronnie Sahlberg
Move the check for check_refname_format from lock_any_ref_for_update
to lock_ref_sha1_basic. At some later stage we will get rid of
lock_any_ref_for_update completely.
This leaves lock_any_ref_for_updates as a no-op wrapper which could be removed.
But this wrapper is also called from an external caller and we will soon
make changes to the signature to lock_ref_sha1_basic that we do not want to
expose to that caller.
Signed-off-by: Ronnie Sahlberg <sahlberg@google.com>
---
refs.c | 5 +++--
1 file changed, 3 insertions(+), 2 deletions(-)
diff --git a/refs.c b/refs.c
index 5680028..df00993 100644
--- a/refs.c
+++ b/refs.c
@@ -2043,6 +2043,9 @@ static struct ref_lock *lock_ref_sha1_basic(const char *refname,
int missing = 0;
int attempts_remaining = 3;
+ if (check_refname_format(refname, REFNAME_ALLOW_ONELEVEL))
+ return NULL;
+
lock = xcalloc(1, sizeof(struct ref_lock));
lock->lock_fd = -1;
@@ -2134,8 +2137,6 @@ struct ref_lock *lock_any_ref_for_update(const char *refname,
const unsigned char *old_sha1,
int flags, int *type_p)
{
- if (check_refname_format(refname, REFNAME_ALLOW_ONELEVEL))
- return NULL;
return lock_ref_sha1_basic(refname, old_sha1, flags, type_p);
}
--
2.0.0.rc3.474.g3833130
^ permalink raw reply related [flat|nested] 18+ messages in thread
* [PATCH v12 38/41] refs.c: pass a skip list to name_conflict_fn
2014-05-29 16:07 [PATCH v12 00/44] Use ref transactions for all ref updates Ronnie Sahlberg
` (9 preceding siblings ...)
2014-05-29 16:07 ` [PATCH v12 36/41] refs.c: move the check for valid refname to lock_ref_sha1_basic Ronnie Sahlberg
@ 2014-05-29 16:07 ` Ronnie Sahlberg
2014-05-29 16:07 ` [PATCH v12 39/41] refs.c: propagate any errno==ENOTDIR from _commit back to the callers Ronnie Sahlberg
` (3 subsequent siblings)
14 siblings, 0 replies; 18+ messages in thread
From: Ronnie Sahlberg @ 2014-05-29 16:07 UTC (permalink / raw)
To: git; +Cc: jrnieder, Ronnie Sahlberg
Allow passing a list of refs to skip checking to name_conflict_fn.
There are some conditions where we want to allow a temporary conflict and skip
checking those refs. For example if we have a transaction that
1, guarantees that m is a packed refs and there is no loose ref for m
2, the transaction will delete m from the packed ref
3, the transaction will create conflicting m/m
For this case we want to be able to lock and create m/m since we know that the
conflict is only transient. I.e. the conflict will be automatically resolved
by the transaction when it deletes m.
Signed-off-by: Ronnie Sahlberg <sahlberg@google.com>
---
refs.c | 36 ++++++++++++++++++++++++++----------
1 file changed, 26 insertions(+), 10 deletions(-)
diff --git a/refs.c b/refs.c
index edf73b7..ec8d642 100644
--- a/refs.c
+++ b/refs.c
@@ -793,11 +793,17 @@ struct name_conflict_cb {
const char *refname;
const char *oldrefname;
const char *conflicting_refname;
+ const char **skip;
+ int skipnum;
};
static int name_conflict_fn(struct ref_entry *entry, void *cb_data)
{
struct name_conflict_cb *data = (struct name_conflict_cb *)cb_data;
+ int i;
+ for (i = 0; i < data->skipnum; i++)
+ if (!strcmp(entry->name, data->skip[i]))
+ return 0;
if (data->oldrefname && !strcmp(data->oldrefname, entry->name))
return 0;
if (names_conflict(data->refname, entry->name)) {
@@ -812,15 +818,19 @@ static int name_conflict_fn(struct ref_entry *entry, void *cb_data)
* conflicting with the name of an existing reference in dir. If
* oldrefname is non-NULL, ignore potential conflicts with oldrefname
* (e.g., because oldrefname is scheduled for deletion in the same
- * operation).
+ * operation). skip contains a list of refs we want to skip checking for
+ * conflicts with.
*/
static int is_refname_available(const char *refname, const char *oldrefname,
- struct ref_dir *dir)
+ struct ref_dir *dir,
+ const char **skip, int skipnum)
{
struct name_conflict_cb data;
data.refname = refname;
data.oldrefname = oldrefname;
data.conflicting_refname = NULL;
+ data.skip = skip;
+ data.skipnum = skipnum;
sort_ref_dir(dir);
if (do_for_each_entry_in_dir(dir, 0, name_conflict_fn, &data)) {
@@ -2032,7 +2042,8 @@ int dwim_log(const char *str, int len, unsigned char *sha1, char **log)
static struct ref_lock *lock_ref_sha1_basic(const char *refname,
const unsigned char *old_sha1,
- int flags, int *type_p)
+ int flags, int *type_p,
+ const char **skip, int skipnum)
{
char *ref_file;
const char *orig_refname = refname;
@@ -2079,7 +2090,9 @@ static struct ref_lock *lock_ref_sha1_basic(const char *refname,
* name is a proper prefix of our refname.
*/
if (missing &&
- !is_refname_available(refname, NULL, get_packed_refs(&ref_cache))) {
+ !is_refname_available(refname, NULL,
+ get_packed_refs(&ref_cache),
+ skip, skipnum)) {
last_errno = ENOTDIR;
goto error_return;
}
@@ -2137,7 +2150,7 @@ struct ref_lock *lock_any_ref_for_update(const char *refname,
const unsigned char *old_sha1,
int flags, int *type_p)
{
- return lock_ref_sha1_basic(refname, old_sha1, flags, type_p);
+ return lock_ref_sha1_basic(refname, old_sha1, flags, type_p, NULL, 0);
}
/*
@@ -2624,10 +2637,12 @@ int rename_ref(const char *oldrefname, const char *newrefname, const char *logms
if (!symref)
return error("refname %s not found", oldrefname);
- if (!is_refname_available(newrefname, oldrefname, get_packed_refs(&ref_cache)))
+ if (!is_refname_available(newrefname, oldrefname,
+ get_packed_refs(&ref_cache), NULL, 0))
return 1;
- if (!is_refname_available(newrefname, oldrefname, get_loose_refs(&ref_cache)))
+ if (!is_refname_available(newrefname, oldrefname,
+ get_loose_refs(&ref_cache), NULL, 0))
return 1;
if (log && rename(git_path("logs/%s", oldrefname), git_path(TMP_RENAMED_LOG)))
@@ -2660,7 +2675,7 @@ int rename_ref(const char *oldrefname, const char *newrefname, const char *logms
logmoved = log;
- lock = lock_ref_sha1_basic(newrefname, NULL, 0, NULL);
+ lock = lock_ref_sha1_basic(newrefname, NULL, 0, NULL, NULL, 0);
if (!lock) {
error("unable to lock %s for update", newrefname);
goto rollback;
@@ -2675,7 +2690,7 @@ int rename_ref(const char *oldrefname, const char *newrefname, const char *logms
return 0;
rollback:
- lock = lock_ref_sha1_basic(oldrefname, NULL, 0, NULL);
+ lock = lock_ref_sha1_basic(oldrefname, NULL, 0, NULL, NULL, 0);
if (!lock) {
error("unable to lock %s for rollback", oldrefname);
goto rollbacklog;
@@ -3520,7 +3535,8 @@ int ref_transaction_commit(struct ref_transaction *transaction,
update->old_sha1 :
NULL),
update->flags,
- &update->type);
+ &update->type,
+ delnames, delnum);
if (!update->lock) {
if (err)
strbuf_addf(err, "Cannot lock the ref '%s'.",
--
2.0.0.rc3.474.g3833130
^ permalink raw reply related [flat|nested] 18+ messages in thread
* [PATCH v12 39/41] refs.c: propagate any errno==ENOTDIR from _commit back to the callers
2014-05-29 16:07 [PATCH v12 00/44] Use ref transactions for all ref updates Ronnie Sahlberg
` (10 preceding siblings ...)
2014-05-29 16:07 ` [PATCH v12 38/41] refs.c: pass a skip list to name_conflict_fn Ronnie Sahlberg
@ 2014-05-29 16:07 ` Ronnie Sahlberg
2014-05-29 16:07 ` [PATCH v12 40/41] fetch.c: change s_update_ref to use a ref transaction Ronnie Sahlberg
` (2 subsequent siblings)
14 siblings, 0 replies; 18+ messages in thread
From: Ronnie Sahlberg @ 2014-05-29 16:07 UTC (permalink / raw)
To: git; +Cc: jrnieder, Ronnie Sahlberg
In _commit, ENOTDIR can happen in the call to lock_ref_sha1_basic, either when
we lstat the new refname and it returns ENOTDIR or if the name checking
function reports that the same type of conflict happened. In both cases it
means that we can not create the new ref due to a name conflict.
For these cases, save the errno value and abort and make sure that the caller
can see errno==ENOTDIR.
Also start defining specific return codes for _commit, assign -1 as a generic
error and -2 as the error that refers to a name conflict. Callers can (and
should) use that return value inspecting errno directly.
Signed-off-by: Ronnie Sahlberg <sahlberg@google.com>
---
refs.c | 23 ++++++++++++++++-------
refs.h | 4 ++++
2 files changed, 20 insertions(+), 7 deletions(-)
diff --git a/refs.c b/refs.c
index ec8d642..6414afc 100644
--- a/refs.c
+++ b/refs.c
@@ -3504,7 +3504,7 @@ static int ref_update_reject_duplicates(struct ref_update **updates, int n,
int ref_transaction_commit(struct ref_transaction *transaction,
struct strbuf *err)
{
- int ret = 0, delnum = 0, i;
+ int ret = 0, delnum = 0, i, save_errno = 0;
const char **delnames;
int n = transaction->nr;
struct ref_update **updates = transaction->updates;
@@ -3522,9 +3522,10 @@ int ref_transaction_commit(struct ref_transaction *transaction,
/* Copy, sort, and reject duplicate refs */
qsort(updates, n, sizeof(*updates), ref_update_compare);
- ret = ref_update_reject_duplicates(updates, n, err);
- if (ret)
+ if (ref_update_reject_duplicates(updates, n, err)) {
+ ret = -1;
goto cleanup;
+ }
/* Acquire all locks while verifying old values */
for (i = 0; i < n; i++) {
@@ -3538,10 +3539,12 @@ int ref_transaction_commit(struct ref_transaction *transaction,
&update->type,
delnames, delnum);
if (!update->lock) {
+ if (errno == ENOTDIR)
+ save_errno = errno;
if (err)
strbuf_addf(err, "Cannot lock the ref '%s'.",
update->refname);
- ret = 1;
+ ret = -1;
goto cleanup;
}
}
@@ -3559,6 +3562,7 @@ int ref_transaction_commit(struct ref_transaction *transaction,
if (err)
strbuf_addf(err, str, update->refname);
+ ret = -1;
goto cleanup;
}
}
@@ -3569,14 +3573,16 @@ int ref_transaction_commit(struct ref_transaction *transaction,
struct ref_update *update = updates[i];
if (update->lock) {
- ret |= delete_ref_loose(update->lock, update->type,
- err);
+ if (delete_ref_loose(update->lock, update->type, err))
+ ret = -1;
+
if (!(update->flags & REF_ISPRUNING))
delnames[delnum++] = update->lock->ref_name;
}
}
- ret |= repack_without_refs(delnames, delnum, err);
+ if (repack_without_refs(delnames, delnum, err))
+ ret = -1;
for (i = 0; i < delnum; i++)
unlink_or_warn(git_path("logs/%s", delnames[i]));
clear_loose_ref_cache(&ref_cache);
@@ -3589,6 +3595,9 @@ cleanup:
if (updates[i]->lock)
unlock_ref(updates[i]->lock);
free(delnames);
+ errno = save_errno;
+ if (save_errno == ENOTDIR)
+ ret = -2;
return ret;
}
diff --git a/refs.h b/refs.h
index 5c6c20f..88732a1 100644
--- a/refs.h
+++ b/refs.h
@@ -323,6 +323,10 @@ int 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.
+ * If the transaction is already in failed state this function will return
+ * an error.
+ * Function returns 0 on success, -1 for generic failures and -2 if the
+ * failure was due to a name collision (ENOTDIR).
*/
int ref_transaction_commit(struct ref_transaction *transaction,
struct strbuf *err);
--
2.0.0.rc3.474.g3833130
^ permalink raw reply related [flat|nested] 18+ messages in thread
* [PATCH v12 40/41] fetch.c: change s_update_ref to use a ref transaction
2014-05-29 16:07 [PATCH v12 00/44] Use ref transactions for all ref updates Ronnie Sahlberg
` (11 preceding siblings ...)
2014-05-29 16:07 ` [PATCH v12 39/41] refs.c: propagate any errno==ENOTDIR from _commit back to the callers Ronnie Sahlberg
@ 2014-05-29 16:07 ` Ronnie Sahlberg
2014-05-29 16:07 ` [PATCH v12 41/41] refs.c: make write_ref_sha1 static Ronnie Sahlberg
2014-05-29 16:13 ` [PATCH v12 00/44] Use ref transactions for all ref updates Ronnie Sahlberg
14 siblings, 0 replies; 18+ messages in thread
From: Ronnie Sahlberg @ 2014-05-29 16:07 UTC (permalink / raw)
To: git; +Cc: jrnieder, Ronnie Sahlberg
Change s_update_ref to use a ref transaction for the ref update.
Signed-off-by: Ronnie Sahlberg <sahlberg@google.com>
---
builtin/fetch.c | 21 +++++++++++++--------
1 file changed, 13 insertions(+), 8 deletions(-)
diff --git a/builtin/fetch.c b/builtin/fetch.c
index faa1233..b13e8f9 100644
--- a/builtin/fetch.c
+++ b/builtin/fetch.c
@@ -375,22 +375,27 @@ static int s_update_ref(const char *action,
{
char msg[1024];
char *rla = getenv("GIT_REFLOG_ACTION");
- static struct ref_lock *lock;
+ struct ref_transaction *transaction;
+ struct strbuf err = STRBUF_INIT;
if (dry_run)
return 0;
if (!rla)
rla = default_rla.buf;
snprintf(msg, sizeof(msg), "%s: %s", rla, action);
- lock = lock_any_ref_for_update(ref->name,
- check_old ? ref->old_sha1 : NULL,
- 0, NULL);
- if (!lock)
- return errno == ENOTDIR ? STORE_REF_ERROR_DF_CONFLICT :
- STORE_REF_ERROR_OTHER;
- if (write_ref_sha1(lock, ref->new_sha1, msg) < 0)
+
+ transaction = ref_transaction_begin(&err);
+ if (!transaction ||
+ ref_transaction_update(transaction, ref->name, ref->new_sha1,
+ ref->old_sha1, 0, check_old, msg, &err) ||
+ ref_transaction_commit(transaction, &err)) {
+ ref_transaction_free(transaction);
+ error("%s", err.buf);
+ strbuf_release(&err);
return errno == ENOTDIR ? STORE_REF_ERROR_DF_CONFLICT :
STORE_REF_ERROR_OTHER;
+ }
+ ref_transaction_free(transaction);
return 0;
}
--
2.0.0.rc3.474.g3833130
^ permalink raw reply related [flat|nested] 18+ messages in thread
* [PATCH v12 41/41] refs.c: make write_ref_sha1 static
2014-05-29 16:07 [PATCH v12 00/44] Use ref transactions for all ref updates Ronnie Sahlberg
` (12 preceding siblings ...)
2014-05-29 16:07 ` [PATCH v12 40/41] fetch.c: change s_update_ref to use a ref transaction Ronnie Sahlberg
@ 2014-05-29 16:07 ` Ronnie Sahlberg
2014-05-29 16:13 ` [PATCH v12 00/44] Use ref transactions for all ref updates Ronnie Sahlberg
14 siblings, 0 replies; 18+ messages in thread
From: Ronnie Sahlberg @ 2014-05-29 16:07 UTC (permalink / raw)
To: git; +Cc: jrnieder, Ronnie Sahlberg
No external users call write_ref_sha1 any more so lets declare it static.
Signed-off-by: Ronnie Sahlberg <sahlberg@google.com>
---
refs.c | 6 +++++-
refs.h | 3 ---
2 files changed, 5 insertions(+), 4 deletions(-)
diff --git a/refs.c b/refs.c
index 6414afc..aefa5bc 100644
--- a/refs.c
+++ b/refs.c
@@ -2618,6 +2618,9 @@ static int rename_tmp_log(const char *newrefname)
return 0;
}
+static int write_ref_sha1(struct ref_lock *lock, const unsigned char *sha1,
+ const char *logmsg);
+
int rename_ref(const char *oldrefname, const char *newrefname, const char *logmsg)
{
unsigned char sha1[20], orig_sha1[20];
@@ -2848,7 +2851,8 @@ static int is_branch(const char *refname)
return !strcmp(refname, "HEAD") || starts_with(refname, "refs/heads/");
}
-int write_ref_sha1(struct ref_lock *lock,
+/** Writes sha1 into the ref specified by the lock. **/
+static int write_ref_sha1(struct ref_lock *lock,
const unsigned char *sha1, const char *logmsg)
{
static char term = '\n';
diff --git a/refs.h b/refs.h
index 88732a1..88020c5 100644
--- a/refs.h
+++ b/refs.h
@@ -195,9 +195,6 @@ extern int commit_ref(struct ref_lock *lock);
/** Release any lock taken but not written. **/
extern void unlock_ref(struct ref_lock *lock);
-/** Writes sha1 into the ref specified by the lock. **/
-extern int write_ref_sha1(struct ref_lock *lock, const unsigned char *sha1, const char *msg);
-
/** Setup reflog before using. **/
int log_ref_setup(const char *refname, char *logfile, int bufsize);
--
2.0.0.rc3.474.g3833130
^ permalink raw reply related [flat|nested] 18+ messages in thread
* Re: [PATCH v12 00/44] Use ref transactions for all ref updates
2014-05-29 16:07 [PATCH v12 00/44] Use ref transactions for all ref updates Ronnie Sahlberg
` (13 preceding siblings ...)
2014-05-29 16:07 ` [PATCH v12 41/41] refs.c: make write_ref_sha1 static Ronnie Sahlberg
@ 2014-05-29 16:13 ` Ronnie Sahlberg
14 siblings, 0 replies; 18+ messages in thread
From: Ronnie Sahlberg @ 2014-05-29 16:13 UTC (permalink / raw)
To: git@vger.kernel.org; +Cc: Jonathan Nieder, Ronnie Sahlberg
These patches are the remaining patches that need review in this series.
Please review them.
On Thu, May 29, 2014 at 9:07 AM, Ronnie Sahlberg <sahlberg@google.com> wrote:
> This patch series can also be found at
> https://github.com/rsahlberg/git/tree/ref-transactions
>
>
> Ronnie please review these remaining patches in this series.
>
>
> Sahlberg (44):
> refs.c: constify the sha arguments for
> ref_transaction_create|delete|update
> refs.c: allow passing NULL to ref_transaction_free
> refs.c: add a strbuf argument to ref_transaction_commit for error
> logging
> refs.c: add an err argument to repack_without_refs
> refs.c: make ref_update_reject_duplicates take a strbuf argument for
> errors
> refs.c: add an err argument to delete_ref_loose
> refs.c: make update_ref_write update a strbuf on failure
> update-ref.c: log transaction error from the update_ref
> refs.c: remove the onerr argument to ref_transaction_commit
> refs.c: change ref_transaction_update() to do error checking and
> return status
> refs.c: change ref_transaction_create to do error checking and return
> status
> refs.c: ref_transaction_delete to check for error and return status
> tag.c: use ref transactions when doing updates
> replace.c: use the ref transaction functions for updates
> commit.c: use ref transactions for updates
> sequencer.c: use ref transactions for all ref updates
> fast-import.c: change update_branch to use ref transactions
> branch.c: use ref transaction for all ref updates
> refs.c: change update_ref to use a transaction
> refs.c: free the transaction before returning when number of updates
> is 0
> refs.c: ref_transaction_commit should not free the transaction
> fetch.c: clear errno before calling functions that might set it
> fetch.c: change s_update_ref to use a ref transaction
> fetch.c: use a single ref transaction for all ref updates
> receive-pack.c: use a reference transaction for updating the refs
> fast-import.c: use a ref transaction when dumping tags
> walker.c: use ref transaction for ref updates
> refs.c: make write_ref_sha1 static
> refs.c: make lock_ref_sha1 static
> refs.c: add transaction.status and track OPEN/CLOSED/ERROR
> refs.c: remove the update_ref_lock function
> refs.c: remove the update_ref_write function
> refs.c: remove lock_ref_sha1
> refs.c: make prune_ref use a transaction to delete the ref
> refs.c: make delete_ref use a transaction
> refs.c: pass the ref log message to _create/delete/update instead of
> _commit
> refs.c: pass NULL as *flags to read_ref_full
> refs.c: pack all refs before we start to rename a ref
> refs.c: move the check for valid refname to lock_ref_sha1_basic
> refs.c: call lock_ref_sha1_basic directly from commit
> refs.c: add a new flag for transaction delete for refs we know are
> packed only
> refs.c: pass a skip list to name_conflict_fn
> refs.c: make rename_ref use a transaction
> refs.c: remove forward declaration of write_ref_sha1
>
> branch.c | 30 ++--
> builtin/commit.c | 24 ++-
> builtin/fetch.c | 29 +--
> builtin/receive-pack.c | 21 +--
> builtin/replace.c | 15 +-
> builtin/tag.c | 15 +-
> builtin/update-ref.c | 32 ++--
> cache.h | 2 +
> fast-import.c | 42 +++--
> lockfile.c | 21 ++-
> refs.c | 468 +++++++++++++++++++++++++++++--------------------
> refs.h | 54 +++---
> sequencer.c | 24 ++-
> t/t3200-branch.sh | 2 +-
> walker.c | 51 +++---
> 15 files changed, 491 insertions(+), 339 deletions(-)
>
> --
> 2.0.0.rc3.510.g20c254b
>
^ permalink raw reply [flat|nested] 18+ messages in thread