From 4d4ebe2ead9fd31bd7c1c5bbc43721a9dc2570ab Mon Sep 17 00:00:00 2001 From: Jameson Miller Date: Tue, 9 Jul 2013 11:25:52 -0400 Subject: [PATCH] Allow push APIs to set packbuilder parallelism --- LibGit2Sharp/Core/GitPushOptions.cs | 12 +++++++++ LibGit2Sharp/Core/NativeMethods.cs | 3 +++ LibGit2Sharp/Core/Proxy.cs | 9 +++++++ LibGit2Sharp/LibGit2Sharp.csproj | 2 ++ LibGit2Sharp/Network.cs | 30 ++++++++++++++++------- LibGit2Sharp/NetworkExtensions.cs | 38 +++++++++++++++++------------ LibGit2Sharp/PushOptions.cs | 24 ++++++++++++++++++ 7 files changed, 94 insertions(+), 24 deletions(-) create mode 100644 LibGit2Sharp/Core/GitPushOptions.cs create mode 100644 LibGit2Sharp/PushOptions.cs diff --git a/LibGit2Sharp/Core/GitPushOptions.cs b/LibGit2Sharp/Core/GitPushOptions.cs new file mode 100644 index 000000000..bf6058d67 --- /dev/null +++ b/LibGit2Sharp/Core/GitPushOptions.cs @@ -0,0 +1,12 @@ +using System; +using System.Runtime.InteropServices; + +namespace LibGit2Sharp.Core +{ + [StructLayout(LayoutKind.Sequential)] + internal class GitPushOptions + { + public int Version = 1; + public int PackbuilderDegreeOfParallelism; + } +} diff --git a/LibGit2Sharp/Core/NativeMethods.cs b/LibGit2Sharp/Core/NativeMethods.cs index 8c72d7cbd..30ce01c48 100644 --- a/LibGit2Sharp/Core/NativeMethods.cs +++ b/LibGit2Sharp/Core/NativeMethods.cs @@ -616,6 +616,9 @@ internal static extern int git_object_peel( [DllImport(libgit2)] internal static extern int git_push_new(out PushSafeHandle push, RemoteSafeHandle remote); + [DllImport(libgit2)] + internal static extern int git_push_set_options(PushSafeHandle push, GitPushOptions options); + [DllImport(libgit2)] internal static extern int git_push_add_refspec( PushSafeHandle push, diff --git a/LibGit2Sharp/Core/Proxy.cs b/LibGit2Sharp/Core/Proxy.cs index babcaabc8..aeefea824 100644 --- a/LibGit2Sharp/Core/Proxy.cs +++ b/LibGit2Sharp/Core/Proxy.cs @@ -1111,6 +1111,15 @@ public static PushSafeHandle git_push_new(RemoteSafeHandle remote) } } + public static void git_push_set_options(PushSafeHandle push, GitPushOptions options) + { + using (ThreadAffinity()) + { + int res = NativeMethods.git_push_set_options(push, options); + Ensure.ZeroResult(res); + } + } + public static void git_push_status_foreach(PushSafeHandle push, NativeMethods.push_status_foreach_cb status_cb) { using (ThreadAffinity()) diff --git a/LibGit2Sharp/LibGit2Sharp.csproj b/LibGit2Sharp/LibGit2Sharp.csproj index d38c5eed3..2d568a804 100644 --- a/LibGit2Sharp/LibGit2Sharp.csproj +++ b/LibGit2Sharp/LibGit2Sharp.csproj @@ -72,6 +72,7 @@ + @@ -104,6 +105,7 @@ + diff --git a/LibGit2Sharp/Network.cs b/LibGit2Sharp/Network.cs index 42d16bd55..b77cb8792 100644 --- a/LibGit2Sharp/Network.cs +++ b/LibGit2Sharp/Network.cs @@ -151,20 +151,20 @@ public virtual void Fetch( /// The source objectish to push. /// The reference to update on the remote. /// Handler for reporting failed push updates. - /// Credentials to use for user/pass authentication + /// controlling push behavior public virtual void Push( Remote remote, string objectish, string destinationSpec, PushStatusErrorHandler onPushStatusError, - Credentials credentials = null) + PushOptions pushOptions = null) { Ensure.ArgumentNotNull(remote, "remote"); Ensure.ArgumentNotNull(objectish, "objectish"); Ensure.ArgumentNotNullOrEmptyString(destinationSpec, destinationSpec); Push(remote, string.Format(CultureInfo.InvariantCulture, - "{0}:{1}", objectish, destinationSpec), onPushStatusError, credentials); + "{0}:{1}", objectish, destinationSpec), onPushStatusError, pushOptions); } /// @@ -173,17 +173,17 @@ public virtual void Push( /// The to push to. /// The pushRefSpec to push. /// Handler for reporting failed push updates. - /// Credentials to use for user/pass authentication + /// controlling push behavior public virtual void Push( Remote remote, string pushRefSpec, PushStatusErrorHandler onPushStatusError, - Credentials credentials = null) + PushOptions pushOptions = null) { Ensure.ArgumentNotNull(remote, "remote"); Ensure.ArgumentNotNullOrEmptyString(pushRefSpec, "pushRefSpec"); - Push(remote, new string[] { pushRefSpec }, onPushStatusError, credentials); + Push(remote, new string[] { pushRefSpec }, onPushStatusError, pushOptions); } /// @@ -192,12 +192,12 @@ public virtual void Push( /// The to push to. /// The pushRefSpecs to push. /// Handler for reporting failed push updates. - /// Credentials to use for user/pass authentication + /// controlling push behavior public virtual void Push( Remote remote, IEnumerable pushRefSpecs, PushStatusErrorHandler onPushStatusError, - Credentials credentials = null) + PushOptions pushOptions = null) { Ensure.ArgumentNotNull(remote, "remote"); Ensure.ArgumentNotNull(pushRefSpecs, "pushRefSpecs"); @@ -208,12 +208,17 @@ public virtual void Push( return; } + if (pushOptions == null) + { + pushOptions = new PushOptions(); + } + PushCallbacks pushStatusUpdates = new PushCallbacks(onPushStatusError); // Load the remote. using (RemoteSafeHandle remoteHandle = Proxy.git_remote_load(repository.Handle, remote.Name, true)) { - var callbacks = new RemoteCallbacks(null, null, null, null, credentials); + var callbacks = new RemoteCallbacks(null, null, null, null, pushOptions.Credentials); GitRemoteCallbacks gitCallbacks = callbacks.GenerateCallbacks(); Proxy.git_remote_set_callbacks(remoteHandle, ref gitCallbacks); @@ -224,6 +229,13 @@ public virtual void Push( // Perform the actual push. using (PushSafeHandle pushHandle = Proxy.git_push_new(remoteHandle)) { + // Set push options. + Proxy.git_push_set_options(pushHandle, + new GitPushOptions() + { + PackbuilderDegreeOfParallelism = pushOptions.PackbuilderDegreeOfParallelism + }); + // Add refspecs. foreach (string pushRefSpec in pushRefSpecs) { diff --git a/LibGit2Sharp/NetworkExtensions.cs b/LibGit2Sharp/NetworkExtensions.cs index 1d4671ae9..59493b827 100644 --- a/LibGit2Sharp/NetworkExtensions.cs +++ b/LibGit2Sharp/NetworkExtensions.cs @@ -17,15 +17,15 @@ public static class NetworkExtensions /// The being worked with. /// The branch to push. /// Handler for reporting failed push updates. - /// Credentials to use for user/pass authentication. + /// controlling push behavior /// Throws if either the Remote or the UpstreamBranchCanonicalName is not set. public static void Push( this Network network, Branch branch, PushStatusErrorHandler onPushStatusError = null, - Credentials credentials = null) + PushOptions pushOptions = null) { - network.Push(new[] { branch }, onPushStatusError, credentials); + network.Push(new[] { branch }, onPushStatusError, pushOptions); } /// @@ -34,13 +34,13 @@ public static void Push( /// The being worked with. /// The branches to push. /// Handler for reporting failed push updates. - /// Credentials to use for user/pass authentication. + /// controlling push behavior /// Throws if either the Remote or the UpstreamBranchCanonicalName is not set. public static void Push( this Network network, IEnumerable branches, PushStatusErrorHandler onPushStatusError = null, - Credentials credentials = null) + PushOptions pushOptions = null) { var enumeratedBranches = branches as IList ?? branches.ToList(); @@ -55,7 +55,7 @@ public static void Push( foreach (var branch in enumeratedBranches) { - network.Push(branch.Remote, string.Format("{0}:{1}", branch.CanonicalName, branch.UpstreamBranchCanonicalName), onPushStatusError, credentials); + network.Push(branch.Remote, string.Format("{0}:{1}", branch.CanonicalName, branch.UpstreamBranchCanonicalName), onPushStatusError, pushOptions); } } @@ -66,21 +66,21 @@ public static void Push( /// The to push to. /// The source objectish to push. /// The reference to update on the remote. - /// Credentials to use for user/pass authentication + /// controlling push behavior /// Results of the push operation. public static PushResult Push( this Network network, Remote remote, string objectish, string destinationSpec, - Credentials credentials = null) + PushOptions pushOptions = null) { Ensure.ArgumentNotNull(remote, "remote"); Ensure.ArgumentNotNull(objectish, "objectish"); Ensure.ArgumentNotNullOrEmptyString(destinationSpec, "destinationSpec"); return network.Push(remote, string.Format(CultureInfo.InvariantCulture, - "{0}:{1}", objectish, destinationSpec), credentials); + "{0}:{1}", objectish, destinationSpec), pushOptions); } /// @@ -89,14 +89,18 @@ public static PushResult Push( /// The being worked with. /// The to push to. /// The pushRefSpec to push. - /// Credentials to use for user/pass authentication + /// controlling push behavior /// Results of the push operation. - public static PushResult Push(this Network network, Remote remote, string pushRefSpec, Credentials credentials = null) + public static PushResult Push( + this Network network, + Remote remote, + string pushRefSpec, + PushOptions pushOptions = null) { Ensure.ArgumentNotNull(remote, "remote"); Ensure.ArgumentNotNullOrEmptyString(pushRefSpec, "pushRefSpec"); - return network.Push(remote, new[] { pushRefSpec }, credentials); + return network.Push(remote, new string[] { pushRefSpec }, pushOptions); } /// @@ -105,9 +109,13 @@ public static PushResult Push(this Network network, Remote remote, string pushRe /// The being worked with. /// The to push to. /// The pushRefSpecs to push. - /// Credentials to use for user/pass authentication + /// controlling push behavior /// Results of the push operation. - public static PushResult Push(this Network network, Remote remote, IEnumerable pushRefSpecs, Credentials credentials = null) + public static PushResult Push( + this Network network, + Remote remote, + IEnumerable pushRefSpecs, + PushOptions pushOptions = null) { Ensure.ArgumentNotNull(remote, "remote"); Ensure.ArgumentNotNull(pushRefSpecs, "pushRefSpecs"); @@ -118,7 +126,7 @@ public static PushResult Push(this Network network, Remote remote, IEnumerable + /// Collection of parameters controlling Push behavior. + /// + public sealed class PushOptions + { + /// + /// The to authenticate with during the push. + /// + public Credentials Credentials { get; set; } + + /// + /// 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. + /// The default is 0, which indicates that the packbuilder will auto-detect + /// the number of threads to create. + /// + public int PackbuilderDegreeOfParallelism { get; set; } + } +}