Commit 013924c17c03c42bce363ea1ddc949444164c2bc

Edward Thomson 2014-12-05T23:44:34

Merge pull request #2730 from libgit2/cmn/local-push Adjust the local transport for the common refspec parser

diff --git a/src/remote.c b/src/remote.c
index 0b00733..531912c 100644
--- a/src/remote.c
+++ b/src/remote.c
@@ -2166,7 +2166,8 @@ int git_remote_push(git_remote *remote, git_strarray *refspecs, const git_push_o
 		goto cleanup;
 	}
 
-	if ((error = git_push_status_foreach(push, cbs->push_update_reference, cbs->payload)) < 0)
+	if (cbs->push_update_reference &&
+	    (error = git_push_status_foreach(push, cbs->push_update_reference, cbs->payload)) < 0)
 		goto cleanup;
 
 	error = git_push_update_tips(push, signature, reflog_message);
diff --git a/src/transports/local.c b/src/transports/local.c
index c544fa9..3846f06 100644
--- a/src/transports/local.c
+++ b/src/transports/local.c
@@ -339,14 +339,11 @@ static int local_push_update_remote_ref(
 	int error;
 	git_reference *remote_ref = NULL;
 
-	/* rref will be NULL if it is implicit in the pushspec (e.g. 'b1:') */
-	rref = rref ? rref : lref;
-
-	if (lref) {
+	/* check for lhs, if it's empty it means to delete */
+	if (lref[0] != '\0') {
 		/* Create or update a ref */
-		if ((error = git_reference_create(NULL, remote_repo, rref, loid,
-				!git_oid_iszero(roid), NULL, NULL)) < 0)
-			return error;
+		error = git_reference_create(NULL, remote_repo, rref, loid,
+					     !git_oid_iszero(roid), NULL, NULL);
 	} else {
 		/* Delete a ref */
 		if ((error = git_reference_lookup(&remote_ref, remote_repo, rref)) < 0) {
@@ -355,13 +352,11 @@ static int local_push_update_remote_ref(
 			return error;
 		}
 
-		if ((error = git_reference_delete(remote_ref)) < 0)
-			return error;
-
+		error = git_reference_delete(remote_ref);
 		git_reference_free(remote_ref);
 	}
 
-	return 0;
+	return error;
 }
 
 static int local_push(
diff --git a/tests/network/remote/local.c b/tests/network/remote/local.c
index fd755b8..1132d95 100644
--- a/tests/network/remote/local.c
+++ b/tests/network/remote/local.c
@@ -466,3 +466,37 @@ void test_network_remote_local__update_tips_for_new_remote(void) {
 	git_repository_free(src_repo);
 	cl_fixture_cleanup("testrepo.git");
 }
+
+void test_network_remote_local__push_delete(void)
+{
+	git_repository *src_repo;
+	git_repository *dst_repo;
+	git_remote *remote;
+	git_reference *ref;
+	char *spec_push[] = { "refs/heads/master" };
+	char *spec_delete[] = { ":refs/heads/master" };
+	git_strarray specs = {
+		spec_push,
+		1,
+	};
+
+	src_repo = cl_git_sandbox_init("testrepo.git");
+	cl_git_pass(git_repository_init(&dst_repo, "target.git", 1));
+
+	cl_git_pass(git_remote_create(&remote, src_repo, "origin", "./target.git"));
+
+	/* Push the master branch and verify it's there */
+	cl_git_pass(git_remote_push(remote, &specs, NULL, NULL, NULL));
+	cl_git_pass(git_reference_lookup(&ref, dst_repo, "refs/heads/master"));
+	git_reference_free(ref);
+
+	specs.strings = spec_delete;
+	cl_git_pass(git_remote_push(remote, &specs, NULL, NULL, NULL));
+	cl_git_fail(git_reference_lookup(&ref, dst_repo, "refs/heads/master"));
+
+	cl_fixture_cleanup("target.git");
+
+	git_remote_free(remote);
+	git_repository_free(dst_repo);
+	git_repository_free(src_repo);
+}