Add git_push_options, to set packbuilder parallelism
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 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152
diff --git a/include/git2/push.h b/include/git2/push.h
index 6e07f36..8caf9a4 100644
--- a/include/git2/push.h
+++ b/include/git2/push.h
@@ -19,6 +19,26 @@
GIT_BEGIN_DECL
/**
+ * Controls the behavior of a git_push object.
+ */
+typedef struct {
+ unsigned int version;
+
+ /**
+ * If the transport being used to push to the remote requires the creation
+ * of a pack file, this controls the number of worker threads used by
+ * the packbuilder when creating that pack file to be sent to the remote.
+ *
+ * If set to 0, the packbuilder will auto-detect the number of threads
+ * to create. The default value is 1.
+ */
+ unsigned int pb_parallelism;
+} git_push_options;
+
+#define GIT_PUSH_OPTIONS_VERSION 1
+#define GIT_PUSH_OPTIONS_INIT { GIT_PUSH_OPTIONS_VERSION }
+
+/**
* Create a new push object
*
* @param out New push object
@@ -29,6 +49,18 @@ GIT_BEGIN_DECL
GIT_EXTERN(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
+ */
+GIT_EXTERN(int) git_push_set_options(
+ git_push *push,
+ const git_push_options *opts);
+
+/**
* Add a refspec to be pushed
*
* @param push The push object
diff --git a/src/pack-objects.c b/src/pack-objects.c
index a76f8a1..e4b6719 100644
--- a/src/pack-objects.c
+++ b/src/pack-objects.c
@@ -144,7 +144,14 @@ on_error:
unsigned int git_packbuilder_set_threads(git_packbuilder *pb, unsigned int n)
{
assert(pb);
+
+#ifdef GIT_THREADS
pb->nr_threads = n;
+#else
+ GIT_UNUSED(n);
+ assert(1 == pb->nr_threads);
+#endif
+
return pb->nr_threads;
}
diff --git a/src/push.c b/src/push.c
index 64aaead..628df7a 100644
--- a/src/push.c
+++ b/src/push.c
@@ -40,6 +40,7 @@ int git_push_new(git_push **out, git_remote *remote)
p->repo = remote->repo;
p->remote = remote;
p->report_status = 1;
+ p->pb_parallelism = 1;
if (git_vector_init(&p->specs, 0, push_spec_rref_cmp) < 0) {
git__free(p);
@@ -56,6 +57,18 @@ int git_push_new(git_push **out, git_remote *remote)
return 0;
}
+int git_push_set_options(git_push *push, const git_push_options *opts)
+{
+ if (!push || !opts)
+ return -1;
+
+ GITERR_CHECK_VERSION(opts, GIT_PUSH_OPTIONS_VERSION, "git_push_options");
+
+ push->pb_parallelism = opts->pb_parallelism;
+
+ return 0;
+}
+
static void free_refspec(push_spec *spec)
{
if (spec == NULL)
@@ -449,8 +462,12 @@ static int do_push(git_push *push)
* objects. In this case the client MUST send an empty pack-file.
*/
- if ((error = git_packbuilder_new(&push->pb, push->repo)) < 0 ||
- (error = calculate_work(push)) < 0 ||
+ if ((error = git_packbuilder_new(&push->pb, push->repo)) < 0)
+ goto on_error;
+
+ git_packbuilder_set_threads(push->pb, push->pb_parallelism);
+
+ if ((error = calculate_work(push)) < 0 ||
(error = queue_objects(push)) < 0 ||
(error = transport->push(transport, push)) < 0)
goto on_error;
diff --git a/src/push.h b/src/push.h
index 0ac8ef9..6295831 100644
--- a/src/push.h
+++ b/src/push.h
@@ -36,6 +36,9 @@ struct git_push {
/* report-status */
bool unpack_ok;
git_vector status;
+
+ /* options */
+ unsigned pb_parallelism;
};
#endif
diff --git a/tests-clar/online/push.c b/tests-clar/online/push.c
index 5618347..907d6d2 100644
--- a/tests-clar/online/push.c
+++ b/tests-clar/online/push.c
@@ -349,13 +349,18 @@ static void do_push(const char *refspecs[], size_t refspecs_len,
expected_ref expected_refs[], size_t expected_refs_len, int expected_ret)
{
git_push *push;
+ git_push_options opts = GIT_PUSH_OPTIONS_INIT;
size_t i;
int ret;
if (_remote) {
+ /* Auto-detect the number of threads to use */
+ opts.pb_parallelism = 0;
+
cl_git_pass(git_remote_connect(_remote, GIT_DIRECTION_PUSH));
cl_git_pass(git_push_new(&push, _remote));
+ cl_git_pass(git_push_set_options(push, &opts));
for (i = 0; i < refspecs_len; i++)
cl_git_pass(git_push_add_refspec(push, refspecs[i]));