summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/push.h110
-rw-r--r--src/remote.c53
-rw-r--r--src/remote.h1
3 files changed, 152 insertions, 12 deletions
diff --git a/src/push.h b/src/push.h
index 68fa868dd..264ecad8c 100644
--- a/src/push.h
+++ b/src/push.h
@@ -51,4 +51,114 @@ struct git_push {
*/
void git_push_status_free(push_status *status);
+/**
+ * Create a new push object
+ *
+ * @param out New push object
+ * @param remote Remote instance
+ *
+ * @return 0 or an error code
+ */
+int git_push_new(git_push **out, git_remote *remote);
+
+/**
+ * Set options on a push object
+ *
+ * @param push The push object
+ * @param opts The options to set on the push object
+ *
+ * @return 0 or an error code
+ */
+int git_push_set_options(
+ git_push *push,
+ const git_push_options *opts);
+
+/**
+ * Set the callbacks for a push
+ *
+ * @param push The push object
+ * @param pack_progress_cb 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.
+ * @param pack_progress_cb_payload Payload for the pack progress callback.
+ * @param transfer_progress_cb 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.
+ * @param transfer_progress_cb_payload Payload for the network progress callback.
+ * @return 0 or an error code
+ */
+int git_push_set_callbacks(
+ git_push *push,
+ git_packbuilder_progress pack_progress_cb,
+ void *pack_progress_cb_payload,
+ git_push_transfer_progress transfer_progress_cb,
+ void *transfer_progress_cb_payload);
+
+/**
+ * Add a refspec to be pushed
+ *
+ * @param push The push object
+ * @param refspec Refspec string
+ *
+ * @return 0 or an error code
+ */
+int git_push_add_refspec(git_push *push, const char *refspec);
+
+/**
+ * Update remote tips after a push
+ *
+ * @param push The push object
+ * @param signature The identity to use when updating reflogs
+ * @param reflog_message The message to insert into the reflogs. If NULL, the
+ * default is "update by push".
+ *
+ * @return 0 or an error code
+ */
+int git_push_update_tips(
+ git_push *push,
+ const git_signature *signature,
+ const char *reflog_message);
+
+/**
+ * Perform the push
+ *
+ * This function will return an error in case of a protocol error or
+ * the server being unable to unpack the data we sent.
+ *
+ * The return value does not reflect whether the server accepted or
+ * refused any reference updates. Use `git_push_status_foreach()` in
+ * order to find out which updates were accepted or rejected.
+ *
+ * @param push The push object
+ *
+ * @return 0 or an error code
+ */
+int git_push_finish(git_push *push);
+
+/**
+ * Invoke callback `cb' on each status entry
+ *
+ * For each of the updated references, we receive a status report in the
+ * form of `ok refs/heads/master` or `ng refs/heads/master <msg>`.
+ * `msg != NULL` means the reference has not been updated for the given
+ * reason.
+ *
+ * Return a non-zero value from the callback to stop the loop.
+ *
+ * @param push The push object
+ * @param cb The callback to call on each object
+ *
+ * @return 0 on success, non-zero callback return value, or error code
+ */
+int git_push_status_foreach(git_push *push,
+ int (*cb)(const char *ref, const char *msg, void *data),
+ void *data);
+
+/**
+ * Free the given push object
+ *
+ * @param push The push object
+ */
+void git_push_free(git_push *push);
+
#endif
diff --git a/src/remote.c b/src/remote.c
index dd9b17854..af6c3ff60 100644
--- a/src/remote.c
+++ b/src/remote.c
@@ -18,6 +18,7 @@
#include "refs.h"
#include "refspec.h"
#include "fetchhead.h"
+#include "push.h"
static int dwim_refspecs(git_vector *out, git_vector *refspecs, git_vector *refs);
@@ -1275,6 +1276,11 @@ int git_remote_update_tips(
int error;
size_t i;
+ /* push has its own logic hidden away in the push object */
+ if (remote->push) {
+ return git_push_update_tips(remote->push, signature, reflog_message);
+ }
+
if (git_refspec__parse(&tagspec, GIT_REFSPEC_TAGS, true) < 0)
return -1;
@@ -1355,6 +1361,7 @@ void git_remote_free(git_remote *remote)
free_refspecs(&remote->passive_refspecs);
git_vector_free(&remote->passive_refspecs);
+ git_push_free(remote->push);
git__free(remote->url);
git__free(remote->pushurl);
git__free(remote->name);
@@ -2117,22 +2124,29 @@ 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 git_remote_upload(git_remote *remote, const git_strarray *refspecs, const git_push_options *opts)
{
- int error;
size_t i;
- git_push *push = NULL;
- git_remote_callbacks *cbs;
+ int error;
+ git_push *push;
git_refspec *spec;
+ git_remote_callbacks *cbs;
- assert(remote && refspecs);
+ assert(remote);
- if ((error = git_remote_connect(remote, GIT_DIRECTION_PUSH)) < 0)
+ if (!git_remote_connected(remote) &&
+ (error = git_remote_connect(remote, GIT_DIRECTION_PUSH)) < 0)
+ goto cleanup;
+
+ if (remote->push) {
+ git_push_free(remote->push);
+ remote->push = NULL;
+ }
+
+ if ((error = git_push_new(&remote->push, remote)) < 0)
return error;
- if ((error = git_push_new(&push, remote)) < 0)
- goto cleanup;
+ push = remote->push;
if (opts && (error = git_push_set_options(push, opts)) < 0)
goto cleanup;
@@ -2164,10 +2178,25 @@ int git_remote_push(git_remote *remote, git_strarray *refspecs, const git_push_o
(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:
+ return error;
+}
+
+int git_remote_push(git_remote *remote, const git_strarray *refspecs, const git_push_options *opts,
+ const git_signature *signature, const char *reflog_message)
+{
+ int error;
+
+ assert(remote && refspecs);
+
+ if ((error = git_remote_connect(remote, GIT_DIRECTION_PUSH)) < 0)
+ return error;
+
+ if ((error = git_remote_upload(remote, refspecs, opts)) < 0)
+ return error;
+
+ error = git_remote_update_tips(remote, signature, reflog_message);
+
git_remote_disconnect(remote);
- git_push_free(push);
return error;
}
diff --git a/src/remote.h b/src/remote.h
index b79ace438..ba7d6b0d9 100644
--- a/src/remote.h
+++ b/src/remote.h
@@ -28,6 +28,7 @@ struct git_remote {
void *transport_cb_payload;
git_transport *transport;
git_repository *repo;
+ git_push *push;
git_remote_callbacks callbacks;
git_transfer_progress stats;
unsigned int need_pack;