Merge branch 'jk/send-pack' into HEAD
authorJunio C Hamano <gitster@pobox.com>
Wed, 31 Oct 2007 04:38:04 +0000 (21:38 -0700)
committerJunio C Hamano <gitster@pobox.com>
Wed, 31 Oct 2007 04:38:04 +0000 (21:38 -0700)
* jk/send-pack:
t5516: test update of local refs on push
send-pack: don't update tracking refs on error

send-pack.c
t/t5516-fetch-push.sh
index e9b9a39f411b6cfff1c0a4bc3f7e31274c8d2782..25053d2c2f7daa9aa392693a892db7e80c8b6469 100644 (file)
@@ -178,6 +178,35 @@ static int receive_status(int in)
        return ret;
 }
 
+static void update_tracking_ref(struct remote *remote, struct ref *ref)
+{
+       struct refspec rs;
+       int will_delete_ref;
+
+       rs.src = ref->name;
+       rs.dst = NULL;
+
+       if (!ref->peer_ref)
+               return;
+
+       will_delete_ref = is_null_sha1(ref->peer_ref->new_sha1);
+
+       if (!will_delete_ref &&
+                       !hashcmp(ref->old_sha1, ref->peer_ref->new_sha1))
+               return;
+
+       if (!remote_find_tracking(remote, &rs)) {
+               fprintf(stderr, "updating local tracking ref '%s'\n", rs.dst);
+               if (is_null_sha1(ref->peer_ref->new_sha1)) {
+                       if (delete_ref(rs.dst, NULL))
+                               error("Failed to delete");
+               } else
+                       update_ref("update by push", rs.dst,
+                                       ref->new_sha1, NULL, 0, 0);
+               free(rs.dst);
+       }
+}
+
 static int send_pack(int in, int out, struct remote *remote, int nr_refspec, char **refspec)
 {
        struct ref *ref;
@@ -306,22 +335,6 @@ static int send_pack(int in, int out, struct remote *remote, int nr_refspec, cha
                        fprintf(stderr, "\n  from %s\n  to   %s\n",
                                old_hex, new_hex);
                }
-               if (remote && !dry_run) {
-                       struct refspec rs;
-                       rs.src = ref->name;
-                       rs.dst = NULL;
-                       if (!remote_find_tracking(remote, &rs)) {
-                               fprintf(stderr, " Also local %s\n", rs.dst);
-                               if (will_delete_ref) {
-                                       if (delete_ref(rs.dst, NULL)) {
-                                               error("Failed to delete");
-                                       }
-                               } else
-                                       update_ref("update by push", rs.dst,
-                                               ref->new_sha1, NULL, 0, 0);
-                               free(rs.dst);
-                       }
-               }
        }
 
        packet_flush(out);
@@ -334,6 +347,11 @@ static int send_pack(int in, int out, struct remote *remote, int nr_refspec, cha
                        ret = -4;
        }
 
+       if (!dry_run && remote && ret == 0) {
+               for (ref = remote_refs; ref; ref = ref->next)
+                       update_tracking_ref(remote, ref);
+       }
+
        if (!new_refs && ret == 0)
                fprintf(stderr, "Everything up-to-date\n");
        return ret;
index 4fbd5b1f473578ac5a1ac61a87883015c04fdc63..86f9b5346a0d7d8807d8c37c063690540873813a 100755 (executable)
@@ -254,4 +254,32 @@ test_expect_success 'push with dry-run' '
        check_push_result $old_commit heads/master
 '
 
+test_expect_success 'push updates local refs' '
+
+       rm -rf parent child &&
+       mkdir parent && cd parent && git init &&
+               echo one >foo && git add foo && git commit -m one &&
+       cd .. &&
+       git clone parent child && cd child &&
+               echo two >foo && git commit -a -m two &&
+               git push &&
+       test $(git rev-parse master) = $(git rev-parse remotes/origin/master)
+
+'
+
+test_expect_success 'push does not update local refs on failure' '
+
+       rm -rf parent child &&
+       mkdir parent && cd parent && git init &&
+               echo one >foo && git add foo && git commit -m one &&
+               echo exit 1 >.git/hooks/pre-receive &&
+               chmod +x .git/hooks/pre-receive &&
+       cd .. &&
+       git clone parent child && cd child &&
+               echo two >foo && git commit -a -m two || exit 1
+               git push && exit 1
+       test $(git rev-parse master) != $(git rev-parse remotes/origin/master)
+
+'
+
 test_done