Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion LibGit2Sharp.Tests/CloneFixture.cs
Original file line number Diff line number Diff line change
Expand Up @@ -116,7 +116,7 @@ public void CallsProgressCallbacks(string url)
var scd = BuildSelfCleaningDirectory();

Repository.Clone(url, scd.DirectoryPath,
onTransferProgress: _ => { transferWasCalled = true; return 0; },
onTransferProgress: _ => { transferWasCalled = true; return true; },
onCheckoutProgress: (a, b, c) => checkoutWasCalled = true);

Assert.True(transferWasCalled);
Expand Down
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 true; };

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
6 changes: 3 additions & 3 deletions LibGit2Sharp.Tests/TestHelpers/ExpectedFetchState.cs
Original file line number Diff line number Diff line change
Expand Up @@ -78,8 +78,8 @@ public void AddExpectedTag(string tagName, ObjectId oldId, TestRemoteInfo.Expect
/// <param name="referenceName">Name of reference being updated.</param>
/// <param name="oldId">Old ID of reference.</param>
/// <param name="newId">New ID of reference.</param>
/// <returns>0 on success; a negative value to abort the process.</returns>
public int RemoteUpdateTipsHandler(string referenceName, ObjectId oldId, ObjectId newId)
/// <returns>True to continue, false to cancel.</returns>
public bool RemoteUpdateTipsHandler(string referenceName, ObjectId oldId, ObjectId newId)
{
// assert that we have not seen this reference before
Assert.DoesNotContain(referenceName, ObservedReferenceUpdates.Keys);
Expand All @@ -97,7 +97,7 @@ public int RemoteUpdateTipsHandler(string referenceName, ObjectId oldId, ObjectI
Assert.Equal(referenceUpdate.NewId, newId);
}

return 0;
return true;
}

/// <summary>
Expand Down
6 changes: 3 additions & 3 deletions LibGit2Sharp/CheckoutCallbacks.cs
Original file line number Diff line number Diff line change
Expand Up @@ -100,14 +100,14 @@ private int OnGitCheckoutNotify(
IntPtr workdirPtr,
IntPtr payloadPtr)
{
int result = 0;
bool result = true;
if (this.onCheckoutNotify != null)
{
FilePath path = LaxFilePathMarshaler.FromNative(pathPtr) ?? FilePath.Empty;
result = onCheckoutNotify(path.Native, why) ? 0 : 1;
result = onCheckoutNotify(path.Native, why);
}

return result;
return Proxy.ConvertResultToCancelFlag(result);
}
}
}
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 @@ internal static extern int git_object_peel(
[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
38 changes: 38 additions & 0 deletions LibGit2Sharp/Core/PackbuilderCallbacks.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 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 Proxy.ConvertResultToCancelFlag(onPackBuilderProgress((PackBuilderStage)stage, (int)current, (int)total));
}
}
}
25 changes: 25 additions & 0 deletions LibGit2Sharp/Core/Proxy.cs
Original file line number Diff line number Diff line change
Expand Up @@ -1135,6 +1135,18 @@ public static PushSafeHandle git_push_new(RemoteSafeHandle remote)
}
}

public static void git_push_set_callbacks(

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Newline above 🙏

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)
{
using (ThreadAffinity())
Expand Down Expand Up @@ -2513,6 +2525,19 @@ public void Dispose()
{ typeof(bool), value => git_config_parse_bool(value) },
{ typeof(string), value => value },
};

/// <summary>
/// Helper method for consistent conversion of return value on
/// Callbacks that support cancellation from bool to native type.
/// True indicates that function should continue, false indicates
/// user wants to cancel.
/// </summary>
/// <param name="result"></param>
/// <returns></returns>
internal static int ConvertResultToCancelFlag(bool result)
{
return result ? 0 : -1;
}
}
}
// ReSharper restore InconsistentNaming
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 Proxy.ConvertResultToCancelFlag(onPushTransferProgress((int)current, (int)total, (long)bytes));
}
}
}
45 changes: 37 additions & 8 deletions LibGit2Sharp/Handlers.cs
Original file line number Diff line number Diff line change
Expand Up @@ -18,20 +18,33 @@
/// <param name="referenceName">Name of the updated reference.</param>
/// <param name="oldId">Old ID of the reference.</param>
/// <param name="newId">New ID of the reference.</param>
/// <returns>Return negative integer to cancel.</returns>
public delegate int UpdateTipsHandler(string referenceName, ObjectId oldId, ObjectId newId);
/// <returns>True to continue, false to cancel.</returns>
public delegate bool UpdateTipsHandler(string referenceName, ObjectId oldId, ObjectId newId);

/// <summary>
/// Delegate definition to handle Completion callback.
/// Delegate definition for transfer progress callback.
/// </summary>
public delegate int CompletionHandler(RemoteCompletionType remoteCompletionType);
/// <param name="progress">The <see cref="TransferProgress"/> object containing progress information.</param>
/// <returns>True to continue, false to cancel.</returns>
public delegate bool TransferProgressHandler(TransferProgress progress);

/// <summary>
/// Delegate definition for transfer progress callback.
/// Delegate definition for callback reporting push network progress.
/// </summary>
/// <param name="progress">The <see cref="TransferProgress"/> object containing progress information.</param>
/// <returns>Return negative integer to cancel.</returns>
public delegate int TransferProgressHandler(TransferProgress progress);
/// <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 continue, false 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 continue, false 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.
Expand Down Expand Up @@ -63,4 +76,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
26 changes: 13 additions & 13 deletions LibGit2Sharp/Network.cs
Original file line number Diff line number Diff line change
Expand Up @@ -95,7 +95,6 @@ public virtual IEnumerable<DirectReference> ListReferences(Remote remote)
/// <param name="remote">The remote to fetch</param>
/// <param name="tagFetchMode">Optional parameter indicating what tags to download.</param>
/// <param name="onProgress">Progress callback. Corresponds to libgit2 progress callback.</param>
/// <param name="onCompletion">Completion callback. Corresponds to libgit2 completion callback.</param>
/// <param name="onUpdateTips">UpdateTips callback. Corresponds to libgit2 update_tips callback.</param>
/// <param name="onTransferProgress">Callback method that transfer progress will be reported through.
/// Reports the client's state regarding the received and processed (bytes, objects) from the server.</param>
Expand All @@ -104,7 +103,6 @@ public virtual void Fetch(
Remote remote,
TagFetchMode? tagFetchMode = null,
ProgressHandler onProgress = null,
CompletionHandler onCompletion = null,
UpdateTipsHandler onUpdateTips = null,
TransferProgressHandler onTransferProgress = null,
Credentials credentials = null)
Expand All @@ -113,7 +111,7 @@ public virtual void Fetch(

using (RemoteSafeHandle remoteHandle = Proxy.git_remote_load(repository.Handle, remote.Name, true))
{
var callbacks = new RemoteCallbacks(onProgress, onTransferProgress, onCompletion, onUpdateTips, credentials);
var callbacks = new RemoteCallbacks(onProgress, onTransferProgress, onUpdateTips, credentials);
GitRemoteCallbacks gitCallbacks = callbacks.GenerateCallbacks();

if (tagFetchMode.HasValue)
Expand Down Expand Up @@ -150,53 +148,47 @@ public virtual void Fetch(
/// <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,12 +205,12 @@ public virtual void Push(
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))
{
var callbacks = new RemoteCallbacks(null, null, null, null, pushOptions.Credentials);
var callbacks = new RemoteCallbacks(null, null, null, pushOptions.Credentials);
GitRemoteCallbacks gitCallbacks = callbacks.GenerateCallbacks();
Proxy.git_remote_set_callbacks(remoteHandle, ref gitCallbacks);

Expand All @@ -229,6 +221,14 @@ public virtual void Push(
// 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
Loading