Skip to content

Fetch should report progress through callbacks. #238

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 1 commit into from
Nov 3, 2012
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
4 changes: 2 additions & 2 deletions LibGit2Sharp.Tests/RemoteFixture.cs
Original file line number Diff line number Diff line change
Expand Up @@ -103,7 +103,7 @@ public void CanFetchIntoAnEmptyRepository(string url)
}

// Perform the actual fetch
remote.Fetch(new FetchProgress(), onUpdateTips: expectedFetchState.RemoteUpdateTipsHandler);
remote.Fetch(onUpdateTips: expectedFetchState.RemoteUpdateTipsHandler);

// Verify the expected
expectedFetchState.CheckUpdatedReferences(repo);
Expand Down Expand Up @@ -141,7 +141,7 @@ public void CanFetchAllTagsIntoAnEmptyRepository(string url)
}

// Perform the actual fetch
remote.Fetch(new FetchProgress(), TagFetchMode.All, onUpdateTips: expectedFetchState.RemoteUpdateTipsHandler);
remote.Fetch(TagFetchMode.All, onUpdateTips: expectedFetchState.RemoteUpdateTipsHandler);

// Verify the expected
expectedFetchState.CheckUpdatedReferences(repo);
Expand Down
17 changes: 17 additions & 0 deletions LibGit2Sharp/Core/GitTransferProgress.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
using System;
using System.Runtime.InteropServices;

namespace LibGit2Sharp.Core
{
/// <summary>
/// Managed structure corresponding to git_transfer_progress native structure.
/// </summary>
[StructLayout(LayoutKind.Sequential)]
internal struct GitTransferProgress
{
public uint total_objects;
public uint indexed_objects;
public uint received_objects;
public UIntPtr received_bytes;
}
}
2 changes: 1 addition & 1 deletion LibGit2Sharp/Core/NativeMethods.cs
Original file line number Diff line number Diff line change
Expand Up @@ -784,7 +784,7 @@ internal static extern int git_tag_delete(
[DllImport(libgit2)]
internal static extern void git_threads_shutdown();

internal delegate void git_transfer_progress_callback(IntPtr stats, IntPtr payload);
internal delegate void git_transfer_progress_callback(ref GitTransferProgress stats, IntPtr payload);

[DllImport(libgit2)]
internal static extern int git_tree_create_fromindex(out GitOid treeOid, IndexSafeHandle index);
Expand Down
8 changes: 5 additions & 3 deletions LibGit2Sharp/Core/Proxy.cs
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@
using System.Runtime.InteropServices;
using System.Threading;
using LibGit2Sharp.Core.Handles;
using LibGit2Sharp.Handlers;

// ReSharper disable InconsistentNaming
namespace LibGit2Sharp.Core
Expand Down Expand Up @@ -1046,12 +1047,13 @@ public static void git_remote_disconnect(RemoteSafeHandle remote)
}
}

// TODO: callback & payload
public static void git_remote_download(RemoteSafeHandle remote, ref long bytes, ref GitIndexerStats indexerStats)
public static void git_remote_download(RemoteSafeHandle remote, TransferProgressHandler onTransferProgress)
{
using (ThreadAffinity())
{
int res = NativeMethods.git_remote_download(remote, null, IntPtr.Zero);
NativeMethods.git_transfer_progress_callback cb = TransferCallbacks.GenerateCallback(onTransferProgress);

int res = NativeMethods.git_remote_download(remote, cb, IntPtr.Zero);
Ensure.Success(res);
}
}
Expand Down
52 changes: 0 additions & 52 deletions LibGit2Sharp/FetchProgress.cs

This file was deleted.

19 changes: 16 additions & 3 deletions LibGit2Sharp/Handlers.cs
Original file line number Diff line number Diff line change
@@ -1,12 +1,19 @@
using System;
using LibGit2Sharp.Core;

namespace LibGit2Sharp.Handlers
{
/// <summary>
/// Delegate definition to handle Progress callback.
/// Delegate definition to handle Progress callback.
/// Returns the text as reported by the server. The text
/// in the serverProgressOutput parameter is not delivered
/// in any particular units (i.e. not necessarily delivered
/// as whole lines) and is likely to be chunked as partial lines.
/// </summary>
/// <param name="message">Progress message.</param>
public delegate void ProgressHandler(string message);
/// <param name="serverProgressOutput">text reported by the server.
/// Text can be chunked at arbitrary increments (i.e. can be composed
/// of a partial line of text).</param>
public delegate void ProgressHandler(string serverProgressOutput);

/// <summary>
/// Delegate definition to handle UpdateTips callback.
Expand All @@ -23,4 +30,10 @@ namespace LibGit2Sharp.Handlers
/// <param name="RemoteCompletionType"></param>
/// <returns></returns>
public delegate int CompletionHandler(RemoteCompletionType RemoteCompletionType);

/// <summary>
/// Delegate definition for transfer progress callback.
/// </summary>
/// <param name="progress">The <see cref = "TransferProgress" /> object containing progress information.</param>
public delegate void TransferProgressHandler(TransferProgress progress);
}
4 changes: 3 additions & 1 deletion LibGit2Sharp/LibGit2Sharp.csproj
Original file line number Diff line number Diff line change
Expand Up @@ -70,6 +70,7 @@
<Compile Include="ContentChanges.cs" />
<Compile Include="Core\GitCheckoutOpts.cs" />
<Compile Include="Core\GitConfigEntry.cs" />
<Compile Include="Core\GitTransferProgress.cs" />
<Compile Include="Core\Proxy.cs" />
<Compile Include="Handlers.cs" />
<Compile Include="ReferenceCollectionExtensions.cs" />
Expand All @@ -79,7 +80,6 @@
<Compile Include="RemoteCompletionType.cs" />
<Compile Include="TagCollectionExtensions.cs" />
<Compile Include="Core\Compat\Environment.cs" />
<Compile Include="FetchProgress.cs" />
<Compile Include="Core\FilePath.cs" />
<Compile Include="Core\FilePathExtensions.cs" />
<Compile Include="Core\FilePathMarshaler.cs" />
Expand Down Expand Up @@ -121,6 +121,8 @@
<Compile Include="Note.cs" />
<Compile Include="RepositoryNotFoundException.cs" />
<Compile Include="TagFetchMode.cs" />
<Compile Include="TransferCallbacks.cs" />
<Compile Include="TransferProgress.cs" />
<Compile Include="TreeChanges.cs" />
<Compile Include="TreeEntryChanges.cs" />
<Compile Include="LibGit2SharpException.cs" />
Expand Down
14 changes: 6 additions & 8 deletions LibGit2Sharp/Remote.cs
Original file line number Diff line number Diff line change
Expand Up @@ -51,20 +51,19 @@ internal static Remote BuildFromPtr(RemoteSafeHandle handle, Repository repo)
/// <summary>
/// Fetch from the <see cref = "Remote" />.
/// </summary>
/// <param name="progress">The <see cref = "FetchProgress" /> datastructure where the progress of the fetch is reported.</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>
public virtual void Fetch(FetchProgress progress = null,
/// <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>
public virtual void Fetch(
TagFetchMode tagFetchMode = TagFetchMode.Auto,
ProgressHandler onProgress = null,
CompletionHandler onCompletion = null,
UpdateTipsHandler onUpdateTips = null)
UpdateTipsHandler onUpdateTips = null,
TransferProgressHandler onTransferProgress = null)
{
progress = progress ?? new FetchProgress();
progress.Reset();

using (RemoteSafeHandle remoteHandle = Proxy.git_remote_load(repository.Handle, this.Name, true))
{
var callbacks = new RemoteCallbacks(onProgress, onCompletion, onUpdateTips);
Expand All @@ -85,8 +84,7 @@ public virtual void Fetch(FetchProgress progress = null,
try
{
Proxy.git_remote_connect(remoteHandle, GitDirection.Fetch);

Proxy.git_remote_download(remoteHandle, ref progress.bytes, ref progress.IndexerStats.gitIndexerStats);
Proxy.git_remote_download(remoteHandle, onTransferProgress);
}
finally
{
Expand Down
10 changes: 6 additions & 4 deletions LibGit2Sharp/RepositoryExtensions.cs
Original file line number Diff line number Diff line change
Expand Up @@ -151,22 +151,24 @@ public static Commit Commit(this IRepository repository, string message, Signatu
/// </summary>
/// <param name="repository">The <see cref = "Repository" /> being worked with.</param>
/// <param name="remoteName">The name of the <see cref="Remote"/> to fetch from.</param>
/// <param name="progress">The <see cref = "FetchProgress" /> datastructure where the progress of the fetch is reported.</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>
public static void Fetch(this IRepository repository, string remoteName, FetchProgress progress = null,
/// <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>
public static void Fetch(this IRepository repository, string remoteName,
TagFetchMode tagFetchMode = TagFetchMode.Auto,
ProgressHandler onProgress = null,
CompletionHandler onCompletion = null,
UpdateTipsHandler onUpdateTips = null)
UpdateTipsHandler onUpdateTips = null,
TransferProgressHandler onTransferProgress = null)
{
Ensure.ArgumentNotNull(repository, "repository");
Ensure.ArgumentNotNullOrEmptyString(remoteName, "remoteName");

Remote remote = repository.Remotes.RemoteForName(remoteName, true);
remote.Fetch(progress, tagFetchMode, onProgress, onCompletion, onUpdateTips);
remote.Fetch(tagFetchMode, onProgress, onCompletion, onUpdateTips, onTransferProgress);
}

private static Signature BuildSignatureFromGlobalConfiguration(IRepository repository, DateTimeOffset now)
Expand Down
54 changes: 54 additions & 0 deletions LibGit2Sharp/TransferCallbacks.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,54 @@
using System;
using LibGit2Sharp.Core;
using LibGit2Sharp.Handlers;

namespace LibGit2Sharp
{
/// <summary>
/// Class to handle the mapping between libgit2 git_transfer_progress_callback function and
/// a corresponding <see cref = "TransferProgressHandler" />. Generates a delegate that
/// wraps the <see cref = "TransferProgressHandler" /> delegate with a delegate that matches
/// the git_transfer_progress_callback signature.
/// </summary>
internal class TransferCallbacks
{
/// <summary>
/// Managed delegate to be called in response to a git_transfer_progress_callback callback from libgit2.
/// </summary>
private TransferProgressHandler onTransferProgress;

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

/// <summary>
/// Generates a delegate that matches the native git_transfer_progress_callback function's signature and wraps the <see cref = "TransferProgressHandler" /> delegate.
/// </summary>
/// <param name="onTransferProgress">The <see cref = "TransferProgressHandler" /> delegate to call in responde to a the native git_transfer_progress_callback callback.</param>
/// <returns>A delegate method with a signature that matches git_transfer_progress_callback.</returns>
internal static NativeMethods.git_transfer_progress_callback GenerateCallback(TransferProgressHandler onTransferProgress)
{
if (onTransferProgress == null)
{
return null;
}

return new TransferCallbacks(onTransferProgress).OnGitTransferProgress;
}

/// <summary>
/// The delegate with the signature that matches the native git_transfer_progress_callback function's signature.
/// </summary>
/// <param name="progress"><see cref = "GitTransferProgress" /> structure containing progress information.</param>
/// <param name="payload">Payload data.</param>
private void OnGitTransferProgress(ref GitTransferProgress progress, IntPtr payload)
{
onTransferProgress(new TransferProgress(progress));
}
}
}
71 changes: 71 additions & 0 deletions LibGit2Sharp/TransferProgress.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,71 @@
using System;
using LibGit2Sharp.Core;

namespace LibGit2Sharp
{
/// <summary>
/// Expose progress values from a fetch operation.
/// </summary>
public class TransferProgress
{
private GitTransferProgress gitTransferProgress;

/// <summary>
/// Empty constructor.
/// </summary>
protected TransferProgress()
{ }

/// <summary>
/// Constructor.
/// </summary>
internal TransferProgress(GitTransferProgress gitTransferProgress)
{
this.gitTransferProgress = gitTransferProgress;
}

/// <summary>
/// Total number of objects.
/// </summary>
public virtual int TotalObjects
{
Copy link
Member

Choose a reason for hiding this comment

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

I'd prefer not decorating this with a [CLSCompliant(false)]

What's the maximum object numbers that could be reached? Wouldn't int be enough? Should we have to deal with more than 2,147,483,647 objects, we could still make this a long

Copy link
Member Author

Choose a reason for hiding this comment

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

I imagine int would be enough. I was reflecting the types that these values are as in libgit2. I will change the uints to be ints, and the ulong to be a long .

get
{
return (int) gitTransferProgress.total_objects;
}
}

/// <summary>
/// Number of objects indexed.
/// </summary>
public virtual int IndexedObjects
{
get
{
return (int) gitTransferProgress.indexed_objects;
}
}

/// <summary>
/// Number of objects received.
/// </summary>
public virtual int ReceivedObjects
{
get
{
return (int) gitTransferProgress.received_objects;
}
}

/// <summary>
/// Number of bytes received.
/// </summary>
public virtual long ReceivedBytes
{
get
{
return (long) gitTransferProgress.received_bytes;
}
}
}
}