Commit b8b897bbc54db5efe34a4adef1f12acb546ce27d

Philip Kelley 2013-02-11T08:28:53

Add git_push_options, to set packbuilder parallelism

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]));