]> granicus.if.org Git - git/commitdiff
walker.c: use ref transaction for ref updates
authorRonnie Sahlberg <sahlberg@google.com>
Thu, 17 Apr 2014 18:31:06 +0000 (11:31 -0700)
committerJunio C Hamano <gitster@pobox.com>
Wed, 3 Sep 2014 17:04:15 +0000 (10:04 -0700)
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 collisions that the previous locking would
protect against and cause the fetch to fail for are even more rare.

Signed-off-by: Ronnie Sahlberg <sahlberg@google.com>
Reviewed-by: Michael Haggerty <mhagger@alum.mit.edu>
Signed-off-by: Jonathan Nieder <jrnieder@gmail.com>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
walker.c

index 1dd86b8f33e04cfc6c0616578416acb1160b5718..b8a5441d6a7cf1d3981ef17473f41a1984e73647 100644 (file)
--- a/walker.c
+++ b/walker.c
@@ -251,40 +251,40 @@ 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 refname = STRBUF_INIT;
+       struct strbuf err = STRBUF_INIT;
+       struct ref_transaction *transaction = NULL;
        unsigned char *sha1 = xmalloc(targets * 20);
-       char *msg;
-       int ret;
-       int i;
+       char *msg = NULL;
+       int i, ret = -1;
 
        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 done;
                }
        }
-
        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 done;
                }
                if (process(walker, lookup_unknown_object(&sha1[20 * i])))
-                       goto unlock_and_fail;
+                       goto done;
        }
 
        if (loop(walker))
-               goto unlock_and_fail;
-
+               goto done;
+       if (!write_ref) {
+               ret = 0;
+               goto done;
+       }
        if (write_ref_log_details) {
                msg = xmalloc(strlen(write_ref_log_details) + 12);
                sprintf(msg, "fetch from %s", write_ref_log_details);
@@ -292,23 +292,33 @@ int walker_fetch(struct walker *walker, int targets, char **target,
                msg = NULL;
        }
        for (i = 0; i < targets; i++) {
-               if (!write_ref || !write_ref[i])
+               if (!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(&refname);
+               strbuf_addf(&refname, "refs/%s", write_ref[i]);
+               if (ref_transaction_update(transaction, refname.buf,
+                                          &sha1[20 * i], NULL, 0, 0,
+                                          &err)) {
+                       error("%s", err.buf);
+                       goto done;
+               }
+       }
+       if (ref_transaction_commit(transaction,
+                                  msg ? msg : "fetch (unknown)",
+                                  &err)) {
+               error("%s", err.buf);
+               goto done;
        }
-       free(msg);
-
-       return 0;
 
-unlock_and_fail:
-       for (i = 0; i < targets; i++)
-               if (lock[i])
-                       unlock_ref(lock[i]);
+       ret = 0;
 
-       return -1;
+done:
+       ref_transaction_free(transaction);
+       free(msg);
+       free(sha1);
+       strbuf_release(&err);
+       strbuf_release(&refname);
+       return ret;
 }
 
 void walker_free(struct walker *walker)