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 } }