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.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135
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;