Commit 64e3e6d43acbbf6cc8f8a4c612547c5a575c4031

Carlos Martín Nieto 2014-10-11T12:25:50

remote: use configured push refspecs if none are given If the user does not pass any refspecs to push, try to use those configured via the configuration or via add_push().

diff --git a/include/git2/remote.h b/include/git2/remote.h
index bb5aac4..ef24229 100644
--- a/include/git2/remote.h
+++ b/include/git2/remote.h
@@ -396,7 +396,8 @@ GIT_EXTERN(int) git_remote_fetch(
  * Peform all the steps from a push.
  *
  * @param remote the remote to push to
- * @param refspecs the refspecs to use for pushing
+ * @param refspecs the refspecs to use for pushing. If none are
+ * passed, the configured refspecs will be used
  * @param opts the options
  * @param signature signature to use for the reflog of updated references
  * @param reflog_message message to use for the reflog of upated references
diff --git a/src/remote.c b/src/remote.c
index 524d5a3..4cfae10 100644
--- a/src/remote.c
+++ b/src/remote.c
@@ -2119,6 +2119,7 @@ int git_remote_push(git_remote *remote, git_strarray *refspecs, const git_push_o
 	size_t i;
 	git_push *push = NULL;
 	git_remote_callbacks *cbs;
+	git_refspec *spec;
 
 	assert(remote && refspecs);
 
@@ -2131,9 +2132,18 @@ int git_remote_push(git_remote *remote, git_strarray *refspecs, const git_push_o
 	if (opts && (error = git_push_set_options(push, opts)) < 0)
 		goto cleanup;
 
-	for (i = 0; i < refspecs->count; i++) {
-		if ((error = git_push_add_refspec(push, refspecs->strings[i])) < 0)
-			goto cleanup;
+	if (refspecs && refspecs->count > 0) {
+		for (i = 0; i < refspecs->count; i++) {
+			if ((error = git_push_add_refspec(push, refspecs->strings[i])) < 0)
+				goto cleanup;
+		}
+	} else {
+		git_vector_foreach(&remote->refspecs, i, spec) {
+			if (!spec->push)
+				continue;
+			if ((error = git_push_add_refspec(push, spec->string)) < 0)
+				goto cleanup;
+		}
 	}
 
 	cbs = &remote->callbacks;
diff --git a/tests/online/push.c b/tests/online/push.c
index ec213db..ddc46f6 100644
--- a/tests/online/push.c
+++ b/tests/online/push.c
@@ -463,7 +463,7 @@ static void do_push(
 	git_push_options opts = GIT_PUSH_OPTIONS_INIT;
 	size_t i;
 	int error;
-	git_strarray specs;
+	git_strarray specs = {0};
 	git_signature *pusher;
 	git_remote_callbacks callbacks;
 	record_callbacks_data *data;
@@ -482,9 +482,11 @@ static void do_push(
 		callbacks.push_update_reference = record_push_status_cb;
 		cl_git_pass(git_remote_set_callbacks(_remote, &callbacks));
 
-		specs.count = refspecs_len;
-		specs.strings = git__calloc(refspecs_len, sizeof(char *));
-		cl_assert(specs.strings);
+		if (refspecs_len) {
+			specs.count = refspecs_len;
+			specs.strings = git__calloc(refspecs_len, sizeof(char *));
+			cl_assert(specs.strings);
+		}
 
 		for (i = 0; i < refspecs_len; i++)
 			specs.strings[i] = (char *) refspecs[i];
@@ -878,3 +880,35 @@ void test_online_push__notes(void)
 
 	git_signature_free(signature);
 }
+
+void test_online_push__configured(void)
+{
+	git_oid note_oid, *target_oid, expected_oid;
+	git_signature *signature;
+	const char *specs[] = { "refs/notes/commits:refs/notes/commits" };
+	push_status exp_stats[] = { { "refs/notes/commits", 1 } };
+	expected_ref exp_refs[] = { { "refs/notes/commits", &expected_oid } };
+	const char *specs_del[] = { ":refs/notes/commits" };
+
+	git_oid_fromstr(&expected_oid, "8461a99b27b7043e58ff6e1f5d2cf07d282534fb");
+
+	target_oid = &_oid_b6;
+
+	cl_git_pass(git_remote_add_push(_remote, specs[0]));
+
+	/* Create note to push */
+	cl_git_pass(git_signature_new(&signature, "nulltoken", "emeric.fermas@gmail.com", 1323847743, 60)); /* Wed Dec 14 08:29:03 2011 +0100 */
+	cl_git_pass(git_note_create(&note_oid, _repo, signature, signature, NULL, target_oid, "hello world\n", 0));
+
+	do_push(NULL, 0,
+		exp_stats, ARRAY_SIZE(exp_stats),
+		exp_refs, ARRAY_SIZE(exp_refs), 0, 1, 1);
+
+	/* And make sure to delete the note */
+
+	do_push(specs_del, ARRAY_SIZE(specs_del),
+		exp_stats, 1,
+		NULL, 0, 0, 0, 0);
+
+	git_signature_free(signature);
+}