using System;
using LibGit2Sharp.Core;
using LibGit2Sharp.Handlers;
namespace LibGit2Sharp
{
///
/// Class to translate libgit2 callbacks into delegates exposed by LibGit2Sharp.
/// Handles generating libgit2 git_remote_callbacks datastructure given a set
/// of LibGit2Sharp delegates and handles propagating libgit2 callbacks into
/// corresponding LibGit2Sharp exposed delegates.
///
internal class RemoteCallbacks
{
internal RemoteCallbacks(
ProgressHandler onProgress = null,
TransferProgressHandler onDownloadProgress = null,
UpdateTipsHandler onUpdateTips = null,
Credentials credentials = null)
{
Progress = onProgress;
DownloadTransferProgress = onDownloadProgress;
UpdateTips = onUpdateTips;
Credentials = credentials;
}
internal RemoteCallbacks(FetchOptions fetchOptions)
{
Ensure.ArgumentNotNull(fetchOptions, "fetchOptions");
Progress = fetchOptions.OnProgress;
DownloadTransferProgress = fetchOptions.OnTransferProgress;
UpdateTips = fetchOptions.OnUpdateTips;
Credentials = fetchOptions.Credentials;
}
#region Delegates
///
/// Progress callback. Corresponds to libgit2 progress callback.
///
private readonly ProgressHandler Progress;
///
/// UpdateTips callback. Corresponds to libgit2 update_tips callback.
///
private readonly UpdateTipsHandler UpdateTips;
///
/// Managed delegate to be called in response to a git_transfer_progress_callback callback from libgit2.
/// This will in turn call the user provided delegate.
///
private readonly TransferProgressHandler DownloadTransferProgress;
#endregion
///
/// The credentials to use for the credential callback.
///
Credentials Credentials;
internal GitRemoteCallbacks GenerateCallbacks()
{
var callbacks = new GitRemoteCallbacks {version = 1};
if (Progress != null)
{
callbacks.progress = GitProgressHandler;
}
if (UpdateTips != null)
{
callbacks.update_tips = GitUpdateTipsHandler;
}
if (Credentials != null)
{
callbacks.acquire_credentials = Credentials.GitCredentialHandler;
}
if (DownloadTransferProgress != null)
{
callbacks.download_progress = GitDownloadTransferProgressHandler;
}
return callbacks;
}
#region Handlers to respond to callbacks raised by libgit2
///
/// Handler for libgit2 Progress callback. Converts values
/// received from libgit2 callback to more suitable types
/// and calls delegate provided by LibGit2Sharp consumer.
///
/// IntPtr to string from libgit2
/// length of string
/// IntPtr to optional payload passed back to the callback.
/// 0 on success; a negative value to abort the process.
private int GitProgressHandler(IntPtr str, int len, IntPtr data)
{
ProgressHandler onProgress = Progress;
bool shouldContinue = true;
if (onProgress != null)
{
string message = LaxUtf8Marshaler.FromNative(str, len);
shouldContinue = onProgress(message);
}
return Proxy.ConvertResultToCancelFlag(shouldContinue);
}
///
/// Handler for libgit2 update_tips callback. Converts values
/// received from libgit2 callback to more suitable types
/// and calls delegate provided by LibGit2Sharp consumer.
///
/// IntPtr to string
/// Old reference ID
/// New referene ID
/// IntPtr to optional payload passed back to the callback.
/// 0 on success; a negative value to abort the process.
private int GitUpdateTipsHandler(IntPtr str, ref GitOid oldId, ref GitOid newId, IntPtr data)
{
UpdateTipsHandler onUpdateTips = UpdateTips;
bool shouldContinue = true;
if (onUpdateTips != null)
{
string refName = LaxUtf8Marshaler.FromNative(str);
shouldContinue = onUpdateTips(refName, oldId, newId);
}
return Proxy.ConvertResultToCancelFlag(shouldContinue);
}
///
/// The delegate with the signature that matches the native git_transfer_progress_callback function's signature.
///
/// structure containing progress information.
/// Payload data.
/// the result of the wrapped
private int GitDownloadTransferProgressHandler(ref GitTransferProgress progress, IntPtr payload)
{
bool shouldContinue = true;
if (DownloadTransferProgress != null)
{
shouldContinue = DownloadTransferProgress(new TransferProgress(progress));
}
return Proxy.ConvertResultToCancelFlag(shouldContinue);
}
#endregion
}
}