Commit 3149547b5ae526f28412574d64d874a4dfd2ed9c

Carlos Martín Nieto 2014-10-10T12:39:53

remote: introduce git_remote_push() This function, similar in style to git_remote_fetch(), performs all the steps required for a push, with a similar interface. The remote callbacks struct has learnt about the push callbacks, letting us set the callbacks a single time instead of setting some in the remote and some in the push operation.

diff --git a/include/git2/remote.h b/include/git2/remote.h
index 0d7fd23..bb5aac4 100644
--- a/include/git2/remote.h
+++ b/include/git2/remote.h
@@ -14,6 +14,7 @@
 #include "indexer.h"
 #include "strarray.h"
 #include "transport.h"
+#include "push.h"
 
 /**
  * @file git2/remote.h
@@ -390,6 +391,22 @@ GIT_EXTERN(int) git_remote_fetch(
 		const char *reflog_message);
 
 /**
+ * Perform a push
+ *
+ * Peform all the steps from a push.
+ *
+ * @param remote the remote to push to
+ * @param refspecs the refspecs to use for pushing
+ * @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
+ */
+GIT_EXTERN(int) git_remote_push(git_remote *remote,
+				git_strarray *refspecs,
+				const git_push_options *opts,
+				const git_signature *signature, const char *reflog_message);
+
+/**
  * Get a list of the configured remotes for a repo
  *
  * The string array must be freed by the user.
@@ -462,6 +479,28 @@ struct git_remote_callbacks {
 	int (*update_tips)(const char *refname, const git_oid *a, const git_oid *b, void *data);
 
 	/**
+	 * Function to call with progress information during pack
+	 * building. Be aware that this is called inline with pack
+	 * building operations, so performance may be affected.
+	 */
+	git_packbuilder_progress pack_progress;
+
+	/**
+	 * Function to call with progress information during the
+	 * upload portion of a push. Be aware that this is called
+	 * inline with pack building operations, so performance may be
+	 * affected.
+	 */
+	git_push_transfer_progress push_transfer_progress;
+
+	/**
+	 * Called for each updated reference on push. If `status` is
+	 * not `NULL`, the update was rejected by the remote server
+	 * and `status` contains the reason given.
+	 */
+	int (*push_update_reference)(const char *refname, const char *status, void *data);
+
+	/**
 	 * This will be passed to each of the callbacks in this struct
 	 * as the last parameter.
 	 */
diff --git a/src/remote.c b/src/remote.c
index cc9f85c..524d5a3 100644
--- a/src/remote.c
+++ b/src/remote.c
@@ -2111,3 +2111,53 @@ int git_remote_default_branch(git_buf *out, git_remote *remote)
 
 	return git_buf_puts(out, guess->name);
 }
+
+int git_remote_push(git_remote *remote, git_strarray *refspecs, const git_push_options *opts,
+		    const git_signature *signature, const char *reflog_message)
+{
+	int error;
+	size_t i;
+	git_push *push = NULL;
+	git_remote_callbacks *cbs;
+
+	assert(remote && refspecs);
+
+	if ((error = git_remote_connect(remote, GIT_DIRECTION_PUSH)) < 0)
+		return error;
+
+	if ((error = git_push_new(&push, remote)) < 0)
+		goto cleanup;
+
+	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;
+	}
+
+	cbs = &remote->callbacks;
+	if ((error = git_push_set_callbacks(push,
+					    cbs->pack_progress, cbs->payload,
+					    cbs->push_transfer_progress, cbs->payload)) < 0)
+		goto cleanup;
+
+	if ((error = git_push_finish(push)) < 0)
+		goto cleanup;
+
+	if (!git_push_unpack_ok(push)) {
+		error = -1;
+		giterr_set(GITERR_NET, "error in the remote while trying to unpack");
+		goto cleanup;
+	}
+
+	if ((error = git_push_status_foreach(push, cbs->push_update_reference, cbs->payload)) < 0)
+		goto cleanup;
+
+	error = git_push_update_tips(push, signature, reflog_message);
+
+cleanup:
+	git_remote_disconnect(remote);
+	git_push_free(push);
+	return error;
+}
diff --git a/tests/online/push_util.h b/tests/online/push_util.h
index 7736912..3d4a388 100644
--- a/tests/online/push_util.h
+++ b/tests/online/push_util.h
@@ -12,7 +12,7 @@ extern const git_oid OID_ZERO;
  * @param data pointer to a record_callbacks_data instance
  */
 #define RECORD_CALLBACKS_INIT(data) \
-	{ GIT_REMOTE_CALLBACKS_VERSION, NULL, NULL, cred_acquire_cb, NULL, NULL, record_update_tips_cb, data }
+	{ GIT_REMOTE_CALLBACKS_VERSION, NULL, NULL, cred_acquire_cb, NULL, NULL, record_update_tips_cb, NULL, NULL, NULL, data }
 
 typedef struct {
 	char *name;