Skip to content

Commit

Permalink
Expose Push progress reporting
Browse files Browse the repository at this point in the history
  • Loading branch information
jamill committed Oct 18, 2013
1 parent 31291fe commit 981f439
Show file tree
Hide file tree
Showing 10 changed files with 176 additions and 86 deletions.
13 changes: 12 additions & 1 deletion LibGit2Sharp.Tests/PushFixture.cs
Original file line number Diff line number Diff line change
Expand Up @@ -60,9 +60,20 @@ private void AssertPush(Action<Repository> push)
[Fact]
public void CanPushABranchTrackingAnUpstreamBranch()
{
bool packBuilderCalled = false;
Handlers.PackBuilderProgressHandler packBuilderCb = (x, y, z) => { packBuilderCalled = true; return false; };

AssertPush(repo => repo.Network.Push(repo.Head));
AssertPush(repo => repo.Network.Push(repo.Branches["master"]));
AssertPush(repo => repo.Network.Push(repo.Network.Remotes["origin"], "HEAD", @"refs/heads/master", OnPushStatusError));

PushOptions options = new PushOptions()
{
OnPushStatusError = OnPushStatusError,
OnPackBuilderProgress = packBuilderCb,
};

AssertPush(repo => repo.Network.Push(repo.Network.Remotes["origin"], "HEAD", @"refs/heads/master", options));
Assert.True(packBuilderCalled);
}

[Fact]
Expand Down
12 changes: 12 additions & 0 deletions LibGit2Sharp/Core/NativeMethods.cs
Original file line number Diff line number Diff line change
Expand Up @@ -626,6 +626,18 @@ private static bool IsRunningOnLinux()
[DllImport(libgit2)]
internal static extern int git_push_new(out PushSafeHandle push, RemoteSafeHandle remote);

/* Push network progress notification function */
internal delegate int git_push_transfer_progress(uint current, uint total, UIntPtr bytes, IntPtr payload);
internal delegate int git_packbuilder_progress(int stage, uint current, uint total, IntPtr payload);

[DllImport(libgit2)]
internal static extern int git_push_set_callbacks(
PushSafeHandle push,
git_packbuilder_progress pack_progress_cb,
IntPtr pack_progress_cb_payload,
git_push_transfer_progress transfer_progress_cb,
IntPtr transfer_progress_cb_payload);

[DllImport(libgit2)]
internal static extern int git_push_set_options(PushSafeHandle push, GitPushOptions options);

Expand Down
39 changes: 39 additions & 0 deletions LibGit2Sharp/Core/PackbuilderCallbacks.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
using System;
using LibGit2Sharp.Handlers;

namespace LibGit2Sharp.Core
{
//
internal class PackbuilderCallbacks
{
private readonly PackBuilderProgressHandler onPackBuilderProgress;

/// <summary>S
/// Constructor to set up the native callback given managed delegate.
/// </summary>
/// <param name="onPackBuilderProgress">The <see cref="PackBuilderProgressHandler"/> delegate that the git_packbuilder_progress will call.</param>
internal PackbuilderCallbacks(PackBuilderProgressHandler onPackBuilderProgress)
{
this.onPackBuilderProgress = onPackBuilderProgress;
}

/// <summary>
/// Generates a delegate that matches the native git_packbuilder_progress function's signature and wraps the <see cref="PackBuilderProgressHandler"/> delegate.
/// </summary>
/// <returns>A delegate method with a signature that matches git_transfer_progress_callback.</returns>
internal NativeMethods.git_packbuilder_progress GenerateCallback()
{
if (onPackBuilderProgress == null)
{
return null;
}

return new PackbuilderCallbacks(onPackBuilderProgress).OnGitPackBuilderProgress;
}

private int OnGitPackBuilderProgress(int stage, uint current, uint total, IntPtr payload)
{
return onPackBuilderProgress((PackBuilderStage) stage, (int)current, (int)total) ? -1 : 0;
}
}
}
11 changes: 11 additions & 0 deletions LibGit2Sharp/Core/Proxy.cs
Original file line number Diff line number Diff line change
Expand Up @@ -1134,6 +1134,17 @@ public static PushSafeHandle git_push_new(RemoteSafeHandle remote)
return handle;
}
}
public static void git_push_set_callbacks(
PushSafeHandle push,
NativeMethods.git_push_transfer_progress pushTransferProgress,
NativeMethods.git_packbuilder_progress packBuilderProgress)
{
using (ThreadAffinity())
{
int res = NativeMethods.git_push_set_callbacks(push, packBuilderProgress, IntPtr.Zero, pushTransferProgress, IntPtr.Zero);
Ensure.ZeroResult(res);
}
}

public static void git_push_set_options(PushSafeHandle push, GitPushOptions options)
{
Expand Down
38 changes: 38 additions & 0 deletions LibGit2Sharp/Core/PushTransferProgressCallbacks.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
using System;
using LibGit2Sharp.Handlers;

namespace LibGit2Sharp.Core
{
internal class PushTransferCallbacks
{
private readonly PushTransferProgressHandler onPushTransferProgress;

/// <summary>
/// Constructor to set up the native callback given managed delegate.
/// </summary>
/// <param name="onPushTransferProgress">The <see cref="TransferProgressHandler"/> delegate that the git_transfer_progress_callback will call.</param>
internal PushTransferCallbacks(PushTransferProgressHandler onPushTransferProgress)
{
this.onPushTransferProgress = onPushTransferProgress;
}

/// <summary>
/// Generates a delegate that matches the native git_transfer_progress_callback function's signature and wraps the <see cref="PushTransferProgressHandler"/> delegate.
/// </summary>
/// <returns>A delegate method with a signature that matches git_transfer_progress_callback.</returns>
internal NativeMethods.git_push_transfer_progress GenerateCallback()
{
if (onPushTransferProgress == null)
{
return null;
}

return new PushTransferCallbacks(onPushTransferProgress).OnGitTransferProgress;
}

private int OnGitTransferProgress(uint current, uint total, UIntPtr bytes, IntPtr payload)
{
return onPushTransferProgress((int)current, (int)total, (long)bytes) ? -1 : 0;
}
}
}
34 changes: 34 additions & 0 deletions LibGit2Sharp/Handlers.cs
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,24 @@
/// <returns>Return negative integer to cancel.</returns>
public delegate int TransferProgressHandler(TransferProgress progress);

/// <summary>
/// Delegate definition for callback reporting push network progress.
/// </summary>
/// <param name="current">The current number of objects sent to server.</param>
/// <param name="total">The total number of objects to send to the server.</param>
/// <param name="bytes">The number of bytes sent to the server.</param>
/// <returns>True to cancel.</returns>
public delegate bool PushTransferProgressHandler(int current, int total, long bytes);

/// <summary>
/// Delegate definition for callback reporting pack builder progress.
/// </summary>
/// <param name="stage">The current stage progress is being reported for.</param>
/// <param name="current">The current number of objects processed in this this stage.</param>
/// <param name="total">The total number of objects to process for the current stage.</param>
/// <returns>True to cancel.</returns>
public delegate bool PackBuilderProgressHandler(PackBuilderStage stage, int current, int total);

/// <summary>
/// Delegate definition to handle reporting errors when updating references on the remote.
/// </summary>
Expand Down Expand Up @@ -63,4 +81,20 @@
/// </summary>
/// <param name="unmatchedPath">The unmatched path.</param>
public delegate void UnmatchedPathHandler(string unmatchedPath);

/// <summary>
/// The stages of pack building.
/// </summary>
public enum PackBuilderStage
{
/// <summary>
/// Counting stage.
/// </summary>
Counting,

/// <summary>
/// Deltafying stage.
/// </summary>
Deltafying
}
}
2 changes: 2 additions & 0 deletions LibGit2Sharp/LibGit2Sharp.csproj
Original file line number Diff line number Diff line change
Expand Up @@ -72,6 +72,8 @@
<Compile Include="CommitSortStrategies.cs" />
<Compile Include="CompareOptions.cs" />
<Compile Include="Core\EncodingMarshaler.cs" />
<Compile Include="Core\PushTransferProgressCallbacks.cs" />
<Compile Include="Core\PackbuilderCallbacks.cs" />
<Compile Include="PushOptions.cs" />
<Compile Include="Core\GitBuf.cs" />
<Compile Include="FilteringOptions.cs" />
Expand Down
20 changes: 11 additions & 9 deletions LibGit2Sharp/Network.cs
Original file line number Diff line number Diff line change
Expand Up @@ -150,53 +150,47 @@ public virtual IEnumerable<DirectReference> ListReferences(Remote remote)
/// <param name="remote">The <see cref="Remote"/> to push to.</param>
/// <param name="objectish">The source objectish to push.</param>
/// <param name="destinationSpec">The reference to update on the remote.</param>
/// <param name="onPushStatusError">Handler for reporting failed push updates.</param>
/// <param name="pushOptions"><see cref="PushOptions"/> controlling push behavior</param>
public virtual void Push(
Remote remote,
string objectish,
string destinationSpec,
PushStatusErrorHandler onPushStatusError,
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, pushOptions);
"{0}:{1}", objectish, destinationSpec), pushOptions);
}

/// <summary>
/// Push specified reference to the <see cref="Remote"/>.
/// </summary>
/// <param name="remote">The <see cref="Remote"/> to push to.</param>
/// <param name="pushRefSpec">The pushRefSpec to push.</param>
/// <param name="onPushStatusError">Handler for reporting failed push updates.</param>
/// <param name="pushOptions"><see cref="PushOptions"/> controlling push behavior</param>
public virtual void Push(
Remote remote,
string pushRefSpec,
PushStatusErrorHandler onPushStatusError,
PushOptions pushOptions = null)
{
Ensure.ArgumentNotNull(remote, "remote");
Ensure.ArgumentNotNullOrEmptyString(pushRefSpec, "pushRefSpec");

Push(remote, new string[] { pushRefSpec }, onPushStatusError, pushOptions);
Push(remote, new string[] { pushRefSpec }, pushOptions);
}

/// <summary>
/// Push specified references to the <see cref="Remote"/>.
/// </summary>
/// <param name="remote">The <see cref="Remote"/> to push to.</param>
/// <param name="pushRefSpecs">The pushRefSpecs to push.</param>
/// <param name="onPushStatusError">Handler for reporting failed push updates.</param>
/// <param name="pushOptions"><see cref="PushOptions"/> controlling push behavior</param>
public virtual void Push(
Remote remote,
IEnumerable<string> pushRefSpecs,
PushStatusErrorHandler onPushStatusError,
PushOptions pushOptions = null)
{
Ensure.ArgumentNotNull(remote, "remote");
Expand All @@ -213,7 +207,7 @@ public virtual IEnumerable<DirectReference> ListReferences(Remote remote)
pushOptions = new PushOptions();
}

PushCallbacks pushStatusUpdates = new PushCallbacks(onPushStatusError);
PushCallbacks pushStatusUpdates = new PushCallbacks(pushOptions.OnPushStatusError);

// Load the remote.
using (RemoteSafeHandle remoteHandle = Proxy.git_remote_load(repository.Handle, remote.Name, true))
Expand All @@ -229,6 +223,14 @@ public virtual IEnumerable<DirectReference> ListReferences(Remote remote)
// Perform the actual push.
using (PushSafeHandle pushHandle = Proxy.git_push_new(remoteHandle))
{
PushTransferCallbacks pushTransferCallbacks = new PushTransferCallbacks(pushOptions.OnPushTransferProgress);
PackbuilderCallbacks packBuilderCallbacks = new PackbuilderCallbacks(pushOptions.OnPackBuilderProgress);

NativeMethods.git_push_transfer_progress pushProgress = pushTransferCallbacks.GenerateCallback();
NativeMethods.git_packbuilder_progress packBuilderProgress = packBuilderCallbacks.GenerateCallback();

Proxy.git_push_set_callbacks(pushHandle, pushProgress, packBuilderProgress);

// Set push options.
Proxy.git_push_set_options(pushHandle,
new GitPushOptions()
Expand Down
78 changes: 2 additions & 76 deletions LibGit2Sharp/NetworkExtensions.cs
Original file line number Diff line number Diff line change
Expand Up @@ -25,21 +25,19 @@ public static class NetworkExtensions
PushStatusErrorHandler onPushStatusError = null,
PushOptions pushOptions = null)
{
network.Push(new[] { branch }, onPushStatusError, pushOptions);
network.Push(new[] { branch }, pushOptions);
}

/// <summary>
/// Push the specified branches to their tracked branches on the remote.
/// </summary>
/// <param name="network">The <see cref="Network"/> being worked with.</param>
/// <param name="branches">The branches to push.</param>
/// <param name="onPushStatusError">Handler for reporting failed push updates.</param>
/// <param name="pushOptions"><see cref="PushOptions"/> controlling push behavior</param>
/// <exception cref="LibGit2SharpException">Throws if either the Remote or the UpstreamBranchCanonicalName is not set.</exception>
public static void Push(
this Network network,
IEnumerable<Branch> branches,
PushStatusErrorHandler onPushStatusError = null,
PushOptions pushOptions = null)
{
var enumeratedBranches = branches as IList<Branch> ?? branches.ToList();
Expand All @@ -55,80 +53,8 @@ public static class NetworkExtensions

foreach (var branch in enumeratedBranches)
{
network.Push(branch.Remote, string.Format("{0}:{1}", branch.CanonicalName, branch.UpstreamBranchCanonicalName), onPushStatusError, pushOptions);
network.Push(branch.Remote, string.Format("{0}:{1}", branch.CanonicalName, branch.UpstreamBranchCanonicalName), pushOptions);
}
}

/// <summary>
/// Push the objectish to the destination reference on the <see cref="Remote"/>.
/// </summary>
/// <param name="network">The <see cref="Network"/> being worked with.</param>
/// <param name="remote">The <see cref="Remote"/> to push to.</param>
/// <param name="objectish">The source objectish to push.</param>
/// <param name="destinationSpec">The reference to update on the remote.</param>
/// <param name="pushOptions"><see cref="PushOptions"/> controlling push behavior</param>
/// <returns>Results of the push operation.</returns>
public static PushResult Push(
this Network network,
Remote remote,
string objectish,
string destinationSpec,
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), pushOptions);
}

/// <summary>
/// Push specified reference to the <see cref="Remote"/>.
/// </summary>
/// <param name="network">The <see cref="Network"/> being worked with.</param>
/// <param name="remote">The <see cref="Remote"/> to push to.</param>
/// <param name="pushRefSpec">The pushRefSpec to push.</param>
/// <param name="pushOptions"><see cref="PushOptions"/> controlling push behavior</param>
/// <returns>Results of the push operation.</returns>
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 string[] { pushRefSpec }, pushOptions);
}

/// <summary>
/// Push specified references to the <see cref="Remote"/>.
/// </summary>
/// <param name="network">The <see cref="Network"/> being worked with.</param>
/// <param name="remote">The <see cref="Remote"/> to push to.</param>
/// <param name="pushRefSpecs">The pushRefSpecs to push.</param>
/// <param name="pushOptions"><see cref="PushOptions"/> controlling push behavior</param>
/// <returns>Results of the push operation.</returns>
public static PushResult Push(
this Network network,
Remote remote,
IEnumerable<string> pushRefSpecs,
PushOptions pushOptions = null)
{
Ensure.ArgumentNotNull(remote, "remote");
Ensure.ArgumentNotNull(pushRefSpecs, "pushRefSpecs");

var failedRemoteUpdates = new List<PushStatusError>();

network.Push(
remote,
pushRefSpecs,
failedRemoteUpdates.Add,
pushOptions);

return new PushResult(failedRemoteUpdates);
}
}
}
15 changes: 15 additions & 0 deletions LibGit2Sharp/PushOptions.cs
Original file line number Diff line number Diff line change
Expand Up @@ -20,5 +20,20 @@ public sealed class PushOptions
/// the number of threads to create.
/// </summary>
public int PackbuilderDegreeOfParallelism { get; set; }

/// <summary>
/// Delegate to report errors when updating references on the remote.
/// </summary>
public PushStatusErrorHandler OnPushStatusError { get; set; }

/// <summary>
/// Delegate to report push network transfer progress.
/// </summary>
public PushTransferProgressHandler OnPushTransferProgress { get; set; }

/// <summary>
/// Delagate to report pack builder progress.
/// </summary>
public PackBuilderProgressHandler OnPackBuilderProgress { get; set; }
}
}

0 comments on commit 981f439

Please sign in to comment.