Re: [PATCH v4 1/3] refs.c: split writing and commiting a ref into two separate functions

2014-04-15 Thread Michael Haggerty
See my comment to your cover letter where I suggest using ref
transactions instead of making callers deal with even more of the
details of updating references.  But I will comment on these patches
anyway, in case you'd rather leave them closer to the current form.

On 04/14/2014 08:29 PM, Ronnie Sahlberg wrote:
> Change the function write_ref_sha1() to just write the ref but not
> commit the ref or the lockfile.
> Add a new function commit_ref_lock() that will commit the change done by
> a previous write_ref_sha1().
> Update all callers of write_ref_sha1() to call commit_ref_lock().
> 
> The new pattern for updating a ref is now :
> 
> lock = lock_ref_sha1_basic() (or varient of)

s/varient/variant/

> write_ref_sha1(lock)
> unlock_ref(lock) | commit_ref_lock(lock)
> 
> Once write_ref_sha1() returns, the new ref has been written and the lock
> file has been closed.
> At that stage we can then either call unlock_ref() which will abort the
> update and delete the lock file withouth applying it, or call

You need a comma after "unlock_ref()".

s/withouth/without/

> commit_ref_lock() which will rename the lock file onto the ref file.


The commit message would be easier to read with better formatting; maybe

---8<---8<---8<---8<---8<---8<---8<---8<---8<---8<---8<---8<---8<---8<---
refs.c: split writing and commiting a ref into two separate functions

* Change the function write_ref_sha1() to just write the ref but not
  commit the ref or the lockfile.

* Add a new function commit_ref_lock() that will commit the change done by
  a previous write_ref_sha1().

* Update all callers of write_ref_sha1() to call commit_ref_lock().

The new pattern for updating a ref is now :

lock = lock_ref_sha1_basic() (or variant of)
write_ref_sha1(lock)
unlock_ref(lock) | commit_ref_lock(lock)

Once write_ref_sha1() returns, the new ref has been written and the lock
file has been closed. At that stage we can then either call unlock_ref(),
which will abort the update and delete the lock file without applying it,
or call commit_ref_lock() which will rename the lock file onto the ref
file.

Signed-off-by: Ronnie Sahlberg 
---8<---8<---8<---8<---8<---8<---8<---8<---8<---8<---8<---8<---8<---8<---


> Signed-off-by: Ronnie Sahlberg 
> ---
>  branch.c   | 10 --
>  builtin/commit.c   |  5 +
>  builtin/fetch.c|  7 ++-
>  builtin/receive-pack.c |  4 
>  builtin/replace.c  |  6 +-
>  builtin/tag.c  |  6 +-
>  fast-import.c  | 18 --
>  refs.c | 41 +++--
>  refs.h |  4 
>  sequencer.c|  4 
>  walker.c   |  4 
>  11 files changed, 92 insertions(+), 17 deletions(-)
> 
> diff --git a/branch.c b/branch.c
> index 660097b..903ea75 100644
> --- a/branch.c
> +++ b/branch.c
> @@ -304,9 +304,15 @@ void create_branch(const char *head,
>   if (real_ref && track)
>   setup_tracking(ref.buf + 11, real_ref, track, quiet);
>  
> - if (!dont_change_ref)
> - if (write_ref_sha1(lock, sha1, msg) < 0)
> + if (!dont_change_ref) {
> + if (write_ref_sha1(lock, sha1, msg) < 0) {
> + unlock_ref(lock);
>   die_errno(_("Failed to write ref"));
> + }
> + if (commit_ref_lock(lock) < 0) {
> + die_errno(_("Failed to commit ref"));
> + }
> + }
>  
>   strbuf_release(&ref);
>   free(real_ref);

There are a lot of changes like this with similar duplicated error
handling.  Why not define a helper function like
write_ref_sha1_and_commit() that does what the old write_ref_sha1() used
to do (for the callers who don't care about updating multiple references
at once)?

In fact, I would recommend renaming the function in a preparatory
commit, to reduce the amount of code churn in the second commit where
you extract the two new separate functions.

> diff --git a/builtin/commit.c b/builtin/commit.c
> index d9550c5..3d8a3a8 100644
> --- a/builtin/commit.c
> +++ b/builtin/commit.c
> @@ -1686,9 +1686,14 @@ int cmd_commit(int argc, const char **argv, const char 
> *prefix)
>   die(_("cannot lock HEAD ref"));
>   }
>   if (write_ref_sha1(ref_lock, sha1, sb.buf) < 0) {
> + unlock_ref(ref_lock);
>   rollback_index_files();
>   die(_("cannot update HEAD ref"));
>   }
> + if (commit_ref_lock(ref_lock) < 0) {
> + rollback_index_files();
> + die(_("cannot commit HEAD ref"));
> + }
>  
>   unlink(git_path("CHERRY_PICK_HEAD"));
>   unlink(git_path("REVERT_HEAD"));
> diff --git a/builtin/fetch.c b/builtin/fetch.c
> index 55f457c..ebfb854 100644
> --- a/builtin/fetch.c
> +++ b/builtin/fetch.c
> @@ -388,7 +388,12 @@ static int s_update_ref(const char *action,
>   if (!lock)
>   return errno == ENOTDIR ? STORE_REF_ERROR_DF_CONFLICT :

[PATCH v4 1/3] refs.c: split writing and commiting a ref into two separate functions

2014-04-14 Thread Ronnie Sahlberg
Change the function write_ref_sha1() to just write the ref but not
commit the ref or the lockfile.
Add a new function commit_ref_lock() that will commit the change done by
a previous write_ref_sha1().
Update all callers of write_ref_sha1() to call commit_ref_lock().

The new pattern for updating a ref is now :

lock = lock_ref_sha1_basic() (or varient of)
write_ref_sha1(lock)
unlock_ref(lock) | commit_ref_lock(lock)

Once write_ref_sha1() returns, the new ref has been written and the lock
file has been closed.
At that stage we can then either call unlock_ref() which will abort the
update and delete the lock file withouth applying it, or call
commit_ref_lock() which will rename the lock file onto the ref file.

Signed-off-by: Ronnie Sahlberg 
---
 branch.c   | 10 --
 builtin/commit.c   |  5 +
 builtin/fetch.c|  7 ++-
 builtin/receive-pack.c |  4 
 builtin/replace.c  |  6 +-
 builtin/tag.c  |  6 +-
 fast-import.c  | 18 --
 refs.c | 41 +++--
 refs.h |  4 
 sequencer.c|  4 
 walker.c   |  4 
 11 files changed, 92 insertions(+), 17 deletions(-)

diff --git a/branch.c b/branch.c
index 660097b..903ea75 100644
--- a/branch.c
+++ b/branch.c
@@ -304,9 +304,15 @@ void create_branch(const char *head,
if (real_ref && track)
setup_tracking(ref.buf + 11, real_ref, track, quiet);
 
-   if (!dont_change_ref)
-   if (write_ref_sha1(lock, sha1, msg) < 0)
+   if (!dont_change_ref) {
+   if (write_ref_sha1(lock, sha1, msg) < 0) {
+   unlock_ref(lock);
die_errno(_("Failed to write ref"));
+   }
+   if (commit_ref_lock(lock) < 0) {
+   die_errno(_("Failed to commit ref"));
+   }
+   }
 
strbuf_release(&ref);
free(real_ref);
diff --git a/builtin/commit.c b/builtin/commit.c
index d9550c5..3d8a3a8 100644
--- a/builtin/commit.c
+++ b/builtin/commit.c
@@ -1686,9 +1686,14 @@ int cmd_commit(int argc, const char **argv, const char 
*prefix)
die(_("cannot lock HEAD ref"));
}
if (write_ref_sha1(ref_lock, sha1, sb.buf) < 0) {
+   unlock_ref(ref_lock);
rollback_index_files();
die(_("cannot update HEAD ref"));
}
+   if (commit_ref_lock(ref_lock) < 0) {
+   rollback_index_files();
+   die(_("cannot commit HEAD ref"));
+   }
 
unlink(git_path("CHERRY_PICK_HEAD"));
unlink(git_path("REVERT_HEAD"));
diff --git a/builtin/fetch.c b/builtin/fetch.c
index 55f457c..ebfb854 100644
--- a/builtin/fetch.c
+++ b/builtin/fetch.c
@@ -388,7 +388,12 @@ static int s_update_ref(const char *action,
if (!lock)
return errno == ENOTDIR ? STORE_REF_ERROR_DF_CONFLICT :
  STORE_REF_ERROR_OTHER;
-   if (write_ref_sha1(lock, ref->new_sha1, msg) < 0)
+   if (write_ref_sha1(lock, ref->new_sha1, msg) < 0) {
+   unlock_ref(lock);
+   return errno == ENOTDIR ? STORE_REF_ERROR_DF_CONFLICT :
+ STORE_REF_ERROR_OTHER;
+   }
+   if (commit_ref_lock(lock) < 0)
return errno == ENOTDIR ? STORE_REF_ERROR_DF_CONFLICT :
  STORE_REF_ERROR_OTHER;
return 0;
diff --git a/builtin/receive-pack.c b/builtin/receive-pack.c
index c323081..4760274 100644
--- a/builtin/receive-pack.c
+++ b/builtin/receive-pack.c
@@ -587,8 +587,12 @@ static const char *update(struct command *cmd, struct 
shallow_info *si)
return "failed to lock";
}
if (write_ref_sha1(lock, new_sha1, "push")) {
+   unlock_ref(lock);
return "failed to write"; /* error() already called */
}
+   if (commit_ref_lock(lock))
+   return "failed to commit"; /* error() already called */
+
return NULL; /* good */
}
 }
diff --git a/builtin/replace.c b/builtin/replace.c
index b62420a..c09ff49 100644
--- a/builtin/replace.c
+++ b/builtin/replace.c
@@ -160,8 +160,12 @@ static int replace_object(const char *object_ref, const 
char *replace_ref,
lock = lock_any_ref_for_update(ref, prev, 0, NULL);
if (!lock)
die("%s: cannot lock the ref", ref);
-   if (write_ref_sha1(lock, repl, NULL) < 0)
+   if (write_ref_sha1(lock, repl, NULL) < 0) {
+   unlock_ref(lock);
die("%s: cannot update the ref", ref);
+   }
+   if (commit_ref_lock(lock) < 0)
+   die("%s: cannot commit the ref", ref);
 
return 0;
 }
diff --git a/builtin/tag.c b/builtin/tag.c
index 40356e3..8653a64 100644
--- a/builtin/tag.c
+++ b/bu