Skip to content

Commit 981f439

Browse files
committed
Expose Push progress reporting
1 parent 31291fe commit 981f439

10 files changed

+176
-86
lines changed

LibGit2Sharp.Tests/PushFixture.cs

+12-1
Original file line numberDiff line numberDiff line change
@@ -60,9 +60,20 @@ private void AssertPush(Action<Repository> push)
6060
[Fact]
6161
public void CanPushABranchTrackingAnUpstreamBranch()
6262
{
63+
bool packBuilderCalled = false;
64+
Handlers.PackBuilderProgressHandler packBuilderCb = (x, y, z) => { packBuilderCalled = true; return false; };
65+
6366
AssertPush(repo => repo.Network.Push(repo.Head));
6467
AssertPush(repo => repo.Network.Push(repo.Branches["master"]));
65-
AssertPush(repo => repo.Network.Push(repo.Network.Remotes["origin"], "HEAD", @"refs/heads/master", OnPushStatusError));
68+
69+
PushOptions options = new PushOptions()
70+
{
71+
OnPushStatusError = OnPushStatusError,
72+
OnPackBuilderProgress = packBuilderCb,
73+
};
74+
75+
AssertPush(repo => repo.Network.Push(repo.Network.Remotes["origin"], "HEAD", @"refs/heads/master", options));
76+
Assert.True(packBuilderCalled);
6677
}
6778

6879
[Fact]

LibGit2Sharp/Core/NativeMethods.cs

+12
Original file line numberDiff line numberDiff line change
@@ -626,6 +626,18 @@ internal static extern int git_object_peel(
626626
[DllImport(libgit2)]
627627
internal static extern int git_push_new(out PushSafeHandle push, RemoteSafeHandle remote);
628628

629+
/* Push network progress notification function */
630+
internal delegate int git_push_transfer_progress(uint current, uint total, UIntPtr bytes, IntPtr payload);
631+
internal delegate int git_packbuilder_progress(int stage, uint current, uint total, IntPtr payload);
632+
633+
[DllImport(libgit2)]
634+
internal static extern int git_push_set_callbacks(
635+
PushSafeHandle push,
636+
git_packbuilder_progress pack_progress_cb,
637+
IntPtr pack_progress_cb_payload,
638+
git_push_transfer_progress transfer_progress_cb,
639+
IntPtr transfer_progress_cb_payload);
640+
629641
[DllImport(libgit2)]
630642
internal static extern int git_push_set_options(PushSafeHandle push, GitPushOptions options);
631643

+39
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,39 @@
1+
using System;
2+
using LibGit2Sharp.Handlers;
3+
4+
namespace LibGit2Sharp.Core
5+
{
6+
//
7+
internal class PackbuilderCallbacks
8+
{
9+
private readonly PackBuilderProgressHandler onPackBuilderProgress;
10+
11+
/// <summary>S
12+
/// Constructor to set up the native callback given managed delegate.
13+
/// </summary>
14+
/// <param name="onPackBuilderProgress">The <see cref="PackBuilderProgressHandler"/> delegate that the git_packbuilder_progress will call.</param>
15+
internal PackbuilderCallbacks(PackBuilderProgressHandler onPackBuilderProgress)
16+
{
17+
this.onPackBuilderProgress = onPackBuilderProgress;
18+
}
19+
20+
/// <summary>
21+
/// Generates a delegate that matches the native git_packbuilder_progress function's signature and wraps the <see cref="PackBuilderProgressHandler"/> delegate.
22+
/// </summary>
23+
/// <returns>A delegate method with a signature that matches git_transfer_progress_callback.</returns>
24+
internal NativeMethods.git_packbuilder_progress GenerateCallback()
25+
{
26+
if (onPackBuilderProgress == null)
27+
{
28+
return null;
29+
}
30+
31+
return new PackbuilderCallbacks(onPackBuilderProgress).OnGitPackBuilderProgress;
32+
}
33+
34+
private int OnGitPackBuilderProgress(int stage, uint current, uint total, IntPtr payload)
35+
{
36+
return onPackBuilderProgress((PackBuilderStage) stage, (int)current, (int)total) ? -1 : 0;
37+
}
38+
}
39+
}

LibGit2Sharp/Core/Proxy.cs

+11
Original file line numberDiff line numberDiff line change
@@ -1134,6 +1134,17 @@ public static PushSafeHandle git_push_new(RemoteSafeHandle remote)
11341134
return handle;
11351135
}
11361136
}
1137+
public static void git_push_set_callbacks(
1138+
PushSafeHandle push,
1139+
NativeMethods.git_push_transfer_progress pushTransferProgress,
1140+
NativeMethods.git_packbuilder_progress packBuilderProgress)
1141+
{
1142+
using (ThreadAffinity())
1143+
{
1144+
int res = NativeMethods.git_push_set_callbacks(push, packBuilderProgress, IntPtr.Zero, pushTransferProgress, IntPtr.Zero);
1145+
Ensure.ZeroResult(res);
1146+
}
1147+
}
11371148

11381149
public static void git_push_set_options(PushSafeHandle push, GitPushOptions options)
11391150
{
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,38 @@
1+
using System;
2+
using LibGit2Sharp.Handlers;
3+
4+
namespace LibGit2Sharp.Core
5+
{
6+
internal class PushTransferCallbacks
7+
{
8+
private readonly PushTransferProgressHandler onPushTransferProgress;
9+
10+
/// <summary>
11+
/// Constructor to set up the native callback given managed delegate.
12+
/// </summary>
13+
/// <param name="onPushTransferProgress">The <see cref="TransferProgressHandler"/> delegate that the git_transfer_progress_callback will call.</param>
14+
internal PushTransferCallbacks(PushTransferProgressHandler onPushTransferProgress)
15+
{
16+
this.onPushTransferProgress = onPushTransferProgress;
17+
}
18+
19+
/// <summary>
20+
/// Generates a delegate that matches the native git_transfer_progress_callback function's signature and wraps the <see cref="PushTransferProgressHandler"/> delegate.
21+
/// </summary>
22+
/// <returns>A delegate method with a signature that matches git_transfer_progress_callback.</returns>
23+
internal NativeMethods.git_push_transfer_progress GenerateCallback()
24+
{
25+
if (onPushTransferProgress == null)
26+
{
27+
return null;
28+
}
29+
30+
return new PushTransferCallbacks(onPushTransferProgress).OnGitTransferProgress;
31+
}
32+
33+
private int OnGitTransferProgress(uint current, uint total, UIntPtr bytes, IntPtr payload)
34+
{
35+
return onPushTransferProgress((int)current, (int)total, (long)bytes) ? -1 : 0;
36+
}
37+
}
38+
}

LibGit2Sharp/Handlers.cs

+34
Original file line numberDiff line numberDiff line change
@@ -33,6 +33,24 @@
3333
/// <returns>Return negative integer to cancel.</returns>
3434
public delegate int TransferProgressHandler(TransferProgress progress);
3535

36+
/// <summary>
37+
/// Delegate definition for callback reporting push network progress.
38+
/// </summary>
39+
/// <param name="current">The current number of objects sent to server.</param>
40+
/// <param name="total">The total number of objects to send to the server.</param>
41+
/// <param name="bytes">The number of bytes sent to the server.</param>
42+
/// <returns>True to cancel.</returns>
43+
public delegate bool PushTransferProgressHandler(int current, int total, long bytes);
44+
45+
/// <summary>
46+
/// Delegate definition for callback reporting pack builder progress.
47+
/// </summary>
48+
/// <param name="stage">The current stage progress is being reported for.</param>
49+
/// <param name="current">The current number of objects processed in this this stage.</param>
50+
/// <param name="total">The total number of objects to process for the current stage.</param>
51+
/// <returns>True to cancel.</returns>
52+
public delegate bool PackBuilderProgressHandler(PackBuilderStage stage, int current, int total);
53+
3654
/// <summary>
3755
/// Delegate definition to handle reporting errors when updating references on the remote.
3856
/// </summary>
@@ -63,4 +81,20 @@
6381
/// </summary>
6482
/// <param name="unmatchedPath">The unmatched path.</param>
6583
public delegate void UnmatchedPathHandler(string unmatchedPath);
84+
85+
/// <summary>
86+
/// The stages of pack building.
87+
/// </summary>
88+
public enum PackBuilderStage
89+
{
90+
/// <summary>
91+
/// Counting stage.
92+
/// </summary>
93+
Counting,
94+
95+
/// <summary>
96+
/// Deltafying stage.
97+
/// </summary>
98+
Deltafying
99+
}
66100
}

LibGit2Sharp/LibGit2Sharp.csproj

+2
Original file line numberDiff line numberDiff line change
@@ -72,6 +72,8 @@
7272
<Compile Include="CommitSortStrategies.cs" />
7373
<Compile Include="CompareOptions.cs" />
7474
<Compile Include="Core\EncodingMarshaler.cs" />
75+
<Compile Include="Core\PushTransferProgressCallbacks.cs" />
76+
<Compile Include="Core\PackbuilderCallbacks.cs" />
7577
<Compile Include="PushOptions.cs" />
7678
<Compile Include="Core\GitBuf.cs" />
7779
<Compile Include="FilteringOptions.cs" />

LibGit2Sharp/Network.cs

+11-9
Original file line numberDiff line numberDiff line change
@@ -150,53 +150,47 @@ public virtual void Fetch(
150150
/// <param name="remote">The <see cref="Remote"/> to push to.</param>
151151
/// <param name="objectish">The source objectish to push.</param>
152152
/// <param name="destinationSpec">The reference to update on the remote.</param>
153-
/// <param name="onPushStatusError">Handler for reporting failed push updates.</param>
154153
/// <param name="pushOptions"><see cref="PushOptions"/> controlling push behavior</param>
155154
public virtual void Push(
156155
Remote remote,
157156
string objectish,
158157
string destinationSpec,
159-
PushStatusErrorHandler onPushStatusError,
160158
PushOptions pushOptions = null)
161159
{
162160
Ensure.ArgumentNotNull(remote, "remote");
163161
Ensure.ArgumentNotNull(objectish, "objectish");
164162
Ensure.ArgumentNotNullOrEmptyString(destinationSpec, destinationSpec);
165163

166164
Push(remote, string.Format(CultureInfo.InvariantCulture,
167-
"{0}:{1}", objectish, destinationSpec), onPushStatusError, pushOptions);
165+
"{0}:{1}", objectish, destinationSpec), pushOptions);
168166
}
169167

170168
/// <summary>
171169
/// Push specified reference to the <see cref="Remote"/>.
172170
/// </summary>
173171
/// <param name="remote">The <see cref="Remote"/> to push to.</param>
174172
/// <param name="pushRefSpec">The pushRefSpec to push.</param>
175-
/// <param name="onPushStatusError">Handler for reporting failed push updates.</param>
176173
/// <param name="pushOptions"><see cref="PushOptions"/> controlling push behavior</param>
177174
public virtual void Push(
178175
Remote remote,
179176
string pushRefSpec,
180-
PushStatusErrorHandler onPushStatusError,
181177
PushOptions pushOptions = null)
182178
{
183179
Ensure.ArgumentNotNull(remote, "remote");
184180
Ensure.ArgumentNotNullOrEmptyString(pushRefSpec, "pushRefSpec");
185181

186-
Push(remote, new string[] { pushRefSpec }, onPushStatusError, pushOptions);
182+
Push(remote, new string[] { pushRefSpec }, pushOptions);
187183
}
188184

189185
/// <summary>
190186
/// Push specified references to the <see cref="Remote"/>.
191187
/// </summary>
192188
/// <param name="remote">The <see cref="Remote"/> to push to.</param>
193189
/// <param name="pushRefSpecs">The pushRefSpecs to push.</param>
194-
/// <param name="onPushStatusError">Handler for reporting failed push updates.</param>
195190
/// <param name="pushOptions"><see cref="PushOptions"/> controlling push behavior</param>
196191
public virtual void Push(
197192
Remote remote,
198193
IEnumerable<string> pushRefSpecs,
199-
PushStatusErrorHandler onPushStatusError,
200194
PushOptions pushOptions = null)
201195
{
202196
Ensure.ArgumentNotNull(remote, "remote");
@@ -213,7 +207,7 @@ public virtual void Push(
213207
pushOptions = new PushOptions();
214208
}
215209

216-
PushCallbacks pushStatusUpdates = new PushCallbacks(onPushStatusError);
210+
PushCallbacks pushStatusUpdates = new PushCallbacks(pushOptions.OnPushStatusError);
217211

218212
// Load the remote.
219213
using (RemoteSafeHandle remoteHandle = Proxy.git_remote_load(repository.Handle, remote.Name, true))
@@ -229,6 +223,14 @@ public virtual void Push(
229223
// Perform the actual push.
230224
using (PushSafeHandle pushHandle = Proxy.git_push_new(remoteHandle))
231225
{
226+
PushTransferCallbacks pushTransferCallbacks = new PushTransferCallbacks(pushOptions.OnPushTransferProgress);
227+
PackbuilderCallbacks packBuilderCallbacks = new PackbuilderCallbacks(pushOptions.OnPackBuilderProgress);
228+
229+
NativeMethods.git_push_transfer_progress pushProgress = pushTransferCallbacks.GenerateCallback();
230+
NativeMethods.git_packbuilder_progress packBuilderProgress = packBuilderCallbacks.GenerateCallback();
231+
232+
Proxy.git_push_set_callbacks(pushHandle, pushProgress, packBuilderProgress);
233+
232234
// Set push options.
233235
Proxy.git_push_set_options(pushHandle,
234236
new GitPushOptions()

LibGit2Sharp/NetworkExtensions.cs

+2-76
Original file line numberDiff line numberDiff line change
@@ -25,21 +25,19 @@ public static void Push(
2525
PushStatusErrorHandler onPushStatusError = null,
2626
PushOptions pushOptions = null)
2727
{
28-
network.Push(new[] { branch }, onPushStatusError, pushOptions);
28+
network.Push(new[] { branch }, pushOptions);
2929
}
3030

3131
/// <summary>
3232
/// Push the specified branches to their tracked branches on the remote.
3333
/// </summary>
3434
/// <param name="network">The <see cref="Network"/> being worked with.</param>
3535
/// <param name="branches">The branches to push.</param>
36-
/// <param name="onPushStatusError">Handler for reporting failed push updates.</param>
3736
/// <param name="pushOptions"><see cref="PushOptions"/> controlling push behavior</param>
3837
/// <exception cref="LibGit2SharpException">Throws if either the Remote or the UpstreamBranchCanonicalName is not set.</exception>
3938
public static void Push(
4039
this Network network,
4140
IEnumerable<Branch> branches,
42-
PushStatusErrorHandler onPushStatusError = null,
4341
PushOptions pushOptions = null)
4442
{
4543
var enumeratedBranches = branches as IList<Branch> ?? branches.ToList();
@@ -55,80 +53,8 @@ public static void Push(
5553

5654
foreach (var branch in enumeratedBranches)
5755
{
58-
network.Push(branch.Remote, string.Format("{0}:{1}", branch.CanonicalName, branch.UpstreamBranchCanonicalName), onPushStatusError, pushOptions);
56+
network.Push(branch.Remote, string.Format("{0}:{1}", branch.CanonicalName, branch.UpstreamBranchCanonicalName), pushOptions);
5957
}
6058
}
61-
62-
/// <summary>
63-
/// Push the objectish to the destination reference on the <see cref="Remote"/>.
64-
/// </summary>
65-
/// <param name="network">The <see cref="Network"/> being worked with.</param>
66-
/// <param name="remote">The <see cref="Remote"/> to push to.</param>
67-
/// <param name="objectish">The source objectish to push.</param>
68-
/// <param name="destinationSpec">The reference to update on the remote.</param>
69-
/// <param name="pushOptions"><see cref="PushOptions"/> controlling push behavior</param>
70-
/// <returns>Results of the push operation.</returns>
71-
public static PushResult Push(
72-
this Network network,
73-
Remote remote,
74-
string objectish,
75-
string destinationSpec,
76-
PushOptions pushOptions = null)
77-
{
78-
Ensure.ArgumentNotNull(remote, "remote");
79-
Ensure.ArgumentNotNull(objectish, "objectish");
80-
Ensure.ArgumentNotNullOrEmptyString(destinationSpec, "destinationSpec");
81-
82-
return network.Push(remote, string.Format(CultureInfo.InvariantCulture,
83-
"{0}:{1}", objectish, destinationSpec), pushOptions);
84-
}
85-
86-
/// <summary>
87-
/// Push specified reference to the <see cref="Remote"/>.
88-
/// </summary>
89-
/// <param name="network">The <see cref="Network"/> being worked with.</param>
90-
/// <param name="remote">The <see cref="Remote"/> to push to.</param>
91-
/// <param name="pushRefSpec">The pushRefSpec to push.</param>
92-
/// <param name="pushOptions"><see cref="PushOptions"/> controlling push behavior</param>
93-
/// <returns>Results of the push operation.</returns>
94-
public static PushResult Push(
95-
this Network network,
96-
Remote remote,
97-
string pushRefSpec,
98-
PushOptions pushOptions = null)
99-
{
100-
Ensure.ArgumentNotNull(remote, "remote");
101-
Ensure.ArgumentNotNullOrEmptyString(pushRefSpec, "pushRefSpec");
102-
103-
return network.Push(remote, new string[] { pushRefSpec }, pushOptions);
104-
}
105-
106-
/// <summary>
107-
/// Push specified references to the <see cref="Remote"/>.
108-
/// </summary>
109-
/// <param name="network">The <see cref="Network"/> being worked with.</param>
110-
/// <param name="remote">The <see cref="Remote"/> to push to.</param>
111-
/// <param name="pushRefSpecs">The pushRefSpecs to push.</param>
112-
/// <param name="pushOptions"><see cref="PushOptions"/> controlling push behavior</param>
113-
/// <returns>Results of the push operation.</returns>
114-
public static PushResult Push(
115-
this Network network,
116-
Remote remote,
117-
IEnumerable<string> pushRefSpecs,
118-
PushOptions pushOptions = null)
119-
{
120-
Ensure.ArgumentNotNull(remote, "remote");
121-
Ensure.ArgumentNotNull(pushRefSpecs, "pushRefSpecs");
122-
123-
var failedRemoteUpdates = new List<PushStatusError>();
124-
125-
network.Push(
126-
remote,
127-
pushRefSpecs,
128-
failedRemoteUpdates.Add,
129-
pushOptions);
130-
131-
return new PushResult(failedRemoteUpdates);
132-
}
13359
}
13460
}

LibGit2Sharp/PushOptions.cs

+15
Original file line numberDiff line numberDiff line change
@@ -20,5 +20,20 @@ public sealed class PushOptions
2020
/// the number of threads to create.
2121
/// </summary>
2222
public int PackbuilderDegreeOfParallelism { get; set; }
23+
24+
/// <summary>
25+
/// Delegate to report errors when updating references on the remote.
26+
/// </summary>
27+
public PushStatusErrorHandler OnPushStatusError { get; set; }
28+
29+
/// <summary>
30+
/// Delegate to report push network transfer progress.
31+
/// </summary>
32+
public PushTransferProgressHandler OnPushTransferProgress { get; set; }
33+
34+
/// <summary>
35+
/// Delagate to report pack builder progress.
36+
/// </summary>
37+
public PackBuilderProgressHandler OnPackBuilderProgress { get; set; }
2338
}
2439
}

0 commit comments

Comments
 (0)