Example #1
0
        public async Task Synchronize(string tag, IConsole console)
        {
            TransferProgressHandler transferHandler = e =>
            {
                //Console.WriteLine (string.Format ("Bytes: {1}, Objects: {2}/{3}, Indexed: {0}", e.IndexedObjects, ByteSizeHelper.ToString (e.ReceivedBytes),
                //	e.ReceivedObjects, e.TotalObjects));
                return(true);
            };

            CheckoutProgressHandler checkoutHandler =
                (path, steps, totalSteps) =>
            {
                console.OverWrite($"Checkout: {steps}/{totalSteps}");
            };

            var repo = Path.Combine(Platform.ReposDirectory, Name);

            LibGit2Sharp.Repository repository = null;

            if (LibGit2Sharp.Repository.IsValid(repo))
            {
                repository = new LibGit2Sharp.Repository(repo);

                await Task.Factory.StartNew(() =>
                {
                    LibGit2Sharp.Commands.Fetch(repository, repository.Network.Remotes["origin"].Name, repository.Network.Remotes["origin"].FetchRefSpecs.Select(s => s.Specification),
                                                new FetchOptions {
                        OnTransferProgress = transferHandler, TagFetchMode = TagFetchMode.All
                    }, "");
                });
            }
            else
            {
                if (Directory.Exists(repo))
                {
                    Directory.Delete(repo, true);
                }

                await Task.Factory.StartNew(() =>
                {
                    LibGit2Sharp.Repository.Clone(RepoUrl, repo,
                                                  new CloneOptions
                    {
                        OnTransferProgress = transferHandler,
                        Checkout           = false,
                        OnCheckoutProgress = checkoutHandler
                    });
                    repository = new LibGit2Sharp.Repository(repo);
                });
            }

            await Task.Factory.StartNew(() =>
            {
                LibGit2Sharp.Commands.Checkout(repository, tag, new CheckoutOptions {
                    OnCheckoutProgress = checkoutHandler
                });
            });

            console.OverWrite("Package installed Successfully.");
        }
Example #2
0
        /// <summary>
        ///   Fetch from the <see cref = "Remote" />.
        /// </summary>
        /// <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>
        /// <param name="credentials">Credentials to use for username/password authentication.</param>
        public virtual void Fetch(
            Remote remote,
            TagFetchMode tagFetchMode                  = TagFetchMode.Auto,
            ProgressHandler onProgress                 = null,
            CompletionHandler onCompletion             = null,
            UpdateTipsHandler onUpdateTips             = null,
            TransferProgressHandler onTransferProgress = null,
            Credentials credentials = null)
        {
            Ensure.ArgumentNotNull(remote, "remote");

            // We need to keep a reference to the git_cred_acquire_cb callback around
            // so it will not be garbage collected before we are done with it.
            // Note that we also have a GC.KeepAlive call at the end of the method.
            NativeMethods.git_cred_acquire_cb credentialCallback = null;

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

                Proxy.git_remote_set_autotag(remoteHandle, tagFetchMode);

                if (credentials != null)
                {
                    credentialCallback = (out IntPtr cred, IntPtr url, IntPtr username_from_url, uint types, IntPtr payload) =>
                                         NativeMethods.git_cred_userpass_plaintext_new(out cred, credentials.Username, credentials.Password);

                    Proxy.git_remote_set_cred_acquire_cb(
                        remoteHandle,
                        credentialCallback,
                        IntPtr.Zero);
                }

                // It is OK to pass the reference to the GitCallbacks directly here because libgit2 makes a copy of
                // the data in the git_remote_callbacks structure. If, in the future, libgit2 changes its implementation
                // to store a reference to the git_remote_callbacks structure this would introduce a subtle bug
                // where the managed layer could move the git_remote_callbacks to a different location in memory,
                // but libgit2 would still reference the old address.
                //
                // Also, if GitRemoteCallbacks were a class instead of a struct, we would need to guard against
                // GC occuring in between setting the remote callbacks and actual usage in one of the functions afterwords.
                Proxy.git_remote_set_callbacks(remoteHandle, ref gitCallbacks);

                try
                {
                    Proxy.git_remote_connect(remoteHandle, GitDirection.Fetch);
                    Proxy.git_remote_download(remoteHandle, onTransferProgress);
                    Proxy.git_remote_update_tips(remoteHandle);
                }
                finally
                {
                    Proxy.git_remote_disconnect(remoteHandle);
                }
            }

            // To be safe, make sure the credential callback is kept until
            // alive until at least this point.
            GC.KeepAlive(credentialCallback);
        }
Example #3
0
 internal RemoteCallbacks(FetchOptions fetchOptions)
 {
     Ensure.ArgumentNotNull(fetchOptions, "fetchOptions");
     Progress = fetchOptions.OnProgress;
     DownloadTransferProgress = fetchOptions.OnTransferProgress;
     UpdateTips = fetchOptions.OnUpdateTips;
     Credentials = fetchOptions.Credentials;
 }
        /// <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;
        }
Example #5
0
 internal RemoteCallbacks(
     ProgressHandler onProgress = null,
     TransferProgressHandler onDownloadProgress = null,
     UpdateTipsHandler onUpdateTips             = null,
     Credentials credentials = null)
 {
     Progress = onProgress;
     DownloadTransferProgress = onDownloadProgress;
     UpdateTips  = onUpdateTips;
     Credentials = credentials;
 }
 internal RemoteCallbacks(
     ProgressHandler onProgress = null,
     TransferProgressHandler onDownloadProgress = null,
     UpdateTipsHandler onUpdateTips = null,
     CredentialsHandler credentialsProvider = null)
 {
     Progress = onProgress;
     DownloadTransferProgress = onDownloadProgress;
     UpdateTips = onUpdateTips;
     CredentialsProvider = credentialsProvider;
 }
Example #7
0
 internal RemoteCallbacks(
     ProgressHandler onProgress = null,
     TransferProgressHandler onDownloadProgress = null,
     UpdateTipsHandler onUpdateTips             = null,
     ICredentialsProvider credentialsProvider   = null)
 {
     Progress = onProgress;
     DownloadTransferProgress = onDownloadProgress;
     UpdateTips          = onUpdateTips;
     CredentialsProvider = credentialsProvider.GetCredentialsHandler();
 }
Example #8
0
        public static void Clone(string source, string target, Action <TransferProgress> progress)
        {
            TransferProgressHandler progressHandler = (tp) =>
            {
                progress(tp);
                return(true);
            };

            Repository.Clone(source, target, new CloneOptions {
                OnTransferProgress = progressHandler
            });
        }
Example #9
0
        public static Repository Clone(string sourceUrl, string workdirPath,
                                       bool bare,
                                       bool checkout,
                                       TransferProgressHandler onTransferProgress,
                                       CheckoutProgressHandler onCheckoutProgress,
                                       RepositoryOptions options,
                                       Credentials credentials)
        {
            string gitDirPath = Clone(sourceUrl, workdirPath, bare,
                                      checkout, onTransferProgress, onCheckoutProgress, credentials);

            return(new Repository(gitDirPath, options));
        }
Example #10
0
        /// <summary>
        /// Fetch from the specified remote.
        /// </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="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>
        /// <param name="credentials">Credentials to use for username/password authentication.</param>
        public static void Fetch(this IRepository repository, string remoteName,
                                 TagFetchMode tagFetchMode                  = TagFetchMode.Auto,
                                 ProgressHandler onProgress                 = null,
                                 CompletionHandler onCompletion             = null,
                                 UpdateTipsHandler onUpdateTips             = null,
                                 TransferProgressHandler onTransferProgress = null,
                                 Credentials credentials = null)
        {
            Ensure.ArgumentNotNull(repository, "repository");
            Ensure.ArgumentNotNullOrEmptyString(remoteName, "remoteName");

            Remote remote = repository.Network.Remotes.RemoteForName(remoteName, true);

            repository.Network.Fetch(remote, tagFetchMode, onProgress, onCompletion, onUpdateTips,
                                     onTransferProgress, credentials);
        }
Example #11
0
        /// <summary>
        /// Clone with specified options.
        /// </summary>
        /// <param name="sourceUrl">URI for the remote repository</param>
        /// <param name="workdirPath">Local path to clone into</param>
        /// <param name="bare">True will result in a bare clone, false a full clone.</param>
        /// <param name="checkout">If true, the origin's HEAD will be checked out. This only applies
        /// to non-bare repositories.</param>
        /// <param name="onTransferProgress">Handler for network transfer and indexing progress information</param>
        /// <param name="onCheckoutProgress">Handler for checkout progress information</param>
        /// <param name="credentials">Credentials to use for user/pass authentication</param>
        /// <returns>The path to the created repository.</returns>
        public static string Clone(string sourceUrl, string workdirPath,
                                   bool bare     = false,
                                   bool checkout = true,
                                   TransferProgressHandler onTransferProgress = null,
                                   CheckoutProgressHandler onCheckoutProgress = null,
                                   Credentials credentials = null)
        {
            CheckoutCallbacks checkoutCallbacks = CheckoutCallbacks.GenerateCheckoutCallbacks(onCheckoutProgress, null);

            var cloneOpts = new GitCloneOptions
            {
                Bare = bare ? 1 : 0,
                TransferProgressCallback = TransferCallbacks.GenerateCallback(onTransferProgress),
                CheckoutOpts             =
                {
                    version     = 1,
                    progress_cb =
                        checkoutCallbacks.CheckoutProgressCallback,
                    checkout_strategy = checkout
                                            ? CheckoutStrategy.GIT_CHECKOUT_SAFE_CREATE
                                            : CheckoutStrategy.GIT_CHECKOUT_NONE
                },
            };

            if (credentials != null)
            {
                cloneOpts.CredAcquireCallback =
                    (out IntPtr cred, IntPtr url, IntPtr username_from_url, uint types, IntPtr payload) =>
                    NativeMethods.git_cred_userpass_plaintext_new(out cred, credentials.Username, credentials.Password);
            }

            FilePath repoPath;

            using (RepositorySafeHandle repo = Proxy.git_clone(sourceUrl, workdirPath, cloneOpts))
            {
                repoPath = Proxy.git_repository_path(repo);
            }

            // To be safe, make sure the credential callback is kept until
            // alive until at least this point.
            GC.KeepAlive(cloneOpts.CredAcquireCallback);

            return(repoPath.Native);
        }
        public static async Task<bool> Clone(string cloneTo, IProgress<double> progress)
        {
            bool succeeded = true;

            await Task.Run(() =>
            {
                var thandler = new TransferProgressHandler(h =>
                {

                    progress.Report(((double)h.ReceivedObjects / h.TotalObjects) * 100);
                    //progress.Report(String.Format("{0}/{1}", (double)h.ReceivedObjects, (double)h.TotalObjects));

                    return 0;

                });

                var chandler = new CheckoutProgressHandler((path, completedSteps, totalSteps) =>
                {

                    //progress.Report(String.Format("{0}/{1}", (double)completedSteps, (double)totalSteps));

                    progress.Report(((double)completedSteps / totalSteps) * 100);

                });

                try
                {
                    Repository.Clone(TrinityCoreGit, cloneTo, false, true, thandler, chandler);
                }
                catch (LibGit2SharpException)
                {
                    //MessageBox.Show("The selected trunk location is not a valid git repository.", "Something went wrong!", System.Windows.MessageBoxButton.OK, System.Windows.MessageBoxImage.Error);
                    succeeded = false;
                }
                catch (Exception)
                {
                    succeeded = false;
                }
            });

            return succeeded;
        }
Example #13
0
        /// <summary>
        /// Fetch from the <see cref="Remote"/>.
        /// </summary>
        /// <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="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>
        /// <param name="credentials">Credentials to use for username/password authentication.</param>
        public virtual void Fetch(
            Remote remote,
            TagFetchMode? tagFetchMode = null,
            ProgressHandler onProgress = null,
            UpdateTipsHandler onUpdateTips = null,
            TransferProgressHandler onTransferProgress = null,
            Credentials credentials = null)
        {
            Ensure.ArgumentNotNull(remote, "remote");

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

                if (tagFetchMode.HasValue)
                {
                    Proxy.git_remote_set_autotag(remoteHandle, tagFetchMode.Value);
                }

                // It is OK to pass the reference to the GitCallbacks directly here because libgit2 makes a copy of
                // the data in the git_remote_callbacks structure. If, in the future, libgit2 changes its implementation
                // to store a reference to the git_remote_callbacks structure this would introduce a subtle bug
                // where the managed layer could move the git_remote_callbacks to a different location in memory,
                // but libgit2 would still reference the old address.
                //
                // Also, if GitRemoteCallbacks were a class instead of a struct, we would need to guard against
                // GC occuring in between setting the remote callbacks and actual usage in one of the functions afterwords.
                Proxy.git_remote_set_callbacks(remoteHandle, ref gitCallbacks);

                try
                {
                    Proxy.git_remote_connect(remoteHandle, GitDirection.Fetch);
                    Proxy.git_remote_download(remoteHandle);
                    Proxy.git_remote_update_tips(remoteHandle);
                }
                finally
                {
                    Proxy.git_remote_disconnect(remoteHandle);
                }
            }
        }
Example #14
0
        public static async Task ClonePublicHttpSubmodule(IConsole console, string sourceurl, string workingPath)
        {
            TransferProgressHandler transferHandler = e =>
            {
                console.OverWrite(
                    $"Bytes: {ByteSizeHelper.ToString(e.ReceivedBytes)}, Objects: {e.ReceivedObjects}/{e.TotalObjects}, Indexed: {e.IndexedObjects}");
                return(true);
            };

            CheckoutProgressHandler checkoutHandler =
                (path, steps, totalSteps) => { console.OverWrite($"Checkout: {steps}/{totalSteps}"); };

            await
            Task.Factory.StartNew(
                () =>
            {
                Repository.Clone(sourceurl, workingPath,
                                 new CloneOptions {
                    OnTransferProgress = transferHandler, OnCheckoutProgress = checkoutHandler
                });
            });
        }
        public static async Task Clone(string cloneTo, IProgress <double> progress)
        {
            await Task.Run(() =>
            {
                var thandler = new TransferProgressHandler(h =>
                {
                    progress.Report(((double)h.ReceivedObjects / h.TotalObjects) * 100);

                    return(0);
                });

                var chandler = new CheckoutProgressHandler((path, completedSteps, totalSteps) =>

                                                           progress.Report(((double)completedSteps / totalSteps) * 100)

                                                           );

                using (var repo = Repository.Clone(TrinityCoreGit, cloneTo, false, true, thandler, chandler))
                {
                }
            });
        }
Example #16
0
        public static async Task <bool> Clone(string cloneTo, IProgress <double> progress)
        {
            bool succeeded = true;

            await Task.Run(() =>
            {
                var thandler = new TransferProgressHandler(h =>
                {
                    progress.Report(((double)h.ReceivedObjects / h.TotalObjects) * 100);
                    //progress.Report(String.Format("{0}/{1}", (double)h.ReceivedObjects, (double)h.TotalObjects));

                    return(0);
                });

                var chandler = new CheckoutProgressHandler((path, completedSteps, totalSteps) =>
                {
                    //progress.Report(String.Format("{0}/{1}", (double)completedSteps, (double)totalSteps));

                    progress.Report(((double)completedSteps / totalSteps) * 100);
                });

                try
                {
                    Repository.Clone(TrinityCoreGit, cloneTo, false, true, thandler, chandler);
                }
                catch (LibGit2SharpException)
                {
                    //MessageBox.Show("The selected trunk location is not a valid git repository.", "Something went wrong!", System.Windows.MessageBoxButton.OK, System.Windows.MessageBoxImage.Error);
                    succeeded = false;
                }
                catch (Exception)
                {
                    succeeded = false;
                }
            });

            return(succeeded);
        }
Example #17
0
        /// <summary>
        /// Clone with specified options.
        /// </summary>
        /// <param name="sourceUrl">URI for the remote repository</param>
        /// <param name="workdirPath">Local path to clone into</param>
        /// <param name="bare">True will result in a bare clone, false a full clone.</param>
        /// <param name="checkout">If true, the origin's HEAD will be checked out. This only applies
        /// to non-bare repositories.</param>
        /// <param name="onTransferProgress">Handler for network transfer and indexing progress information</param>
        /// <param name="onCheckoutProgress">Handler for checkout progress information</param>
        /// <param name="credentials">Credentials to use for user/pass authentication</param>
        /// <returns>The path to the created repository.</returns>
        public static string Clone(string sourceUrl, string workdirPath,
                                   bool bare     = false,
                                   bool checkout = true,
                                   TransferProgressHandler onTransferProgress = null,
                                   CheckoutProgressHandler onCheckoutProgress = null,
                                   Credentials credentials = null)
        {
            CheckoutCallbacks checkoutCallbacks = CheckoutCallbacks.GenerateCheckoutCallbacks(onCheckoutProgress, null);

            var callbacks = new RemoteCallbacks(null, onTransferProgress, null, credentials);
            GitRemoteCallbacks gitCallbacks = callbacks.GenerateCallbacks();

            var cloneOpts = new GitCloneOptions
            {
                Bare         = bare ? 1 : 0,
                CheckoutOpts =
                {
                    version     = 1,
                    progress_cb =
                        checkoutCallbacks.CheckoutProgressCallback,
                    checkout_strategy = checkout
                                            ? CheckoutStrategy.GIT_CHECKOUT_SAFE_CREATE
                                            : CheckoutStrategy.GIT_CHECKOUT_NONE
                },
                RemoteCallbacks = gitCallbacks,
            };

            FilePath repoPath;

            using (RepositorySafeHandle repo = Proxy.git_clone(sourceUrl, workdirPath, cloneOpts))
            {
                repoPath = Proxy.git_repository_path(repo);
            }

            return(repoPath.Native);
        }
Example #18
0
        internal RemoteCallbacks(FetchOptionsBase fetchOptions)
        {
            if (fetchOptions == null)
            {
                return;
            }

            Progress = fetchOptions.OnProgress;
            DownloadTransferProgress = fetchOptions.OnTransferProgress;
            UpdateTips = fetchOptions.OnUpdateTips;
            CredentialsProvider = fetchOptions.CredentialsProvider;
            CertificateCheck = fetchOptions.CertificateCheck;
        }
Example #19
0
 public virtual void Fetch(
     Remote remote,
     TagFetchMode? tagFetchMode = null,
     ProgressHandler onProgress = null,
     UpdateTipsHandler onUpdateTips = null,
     TransferProgressHandler onTransferProgress = null,
     Credentials credentials = null)
 {
     Fetch(remote, new FetchOptions
     {
         TagFetchMode = tagFetchMode,
         OnProgress = onProgress,
         OnUpdateTips = onUpdateTips,
         OnTransferProgress = onTransferProgress,
         Credentials = credentials
     });
 }
Example #20
0
 /// <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;
 }
Example #21
0
        /// <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);
        }
Example #22
0
        /// <summary>
        ///   Fetch from the <see cref = "Remote" />.
        /// </summary>
        /// <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>
        /// <param name="credentials">Credentials to use for username/password authentication.</param>
        public virtual void Fetch(
            Remote remote,
            TagFetchMode tagFetchMode = TagFetchMode.Auto,
            ProgressHandler onProgress = null,
            CompletionHandler onCompletion = null,
            UpdateTipsHandler onUpdateTips = null,
            TransferProgressHandler onTransferProgress = null,
            Credentials credentials = null)
        {
            Ensure.ArgumentNotNull(remote, "remote");

            // We need to keep a reference to the git_cred_acquire_cb callback around
            // so it will not be garbage collected before we are done with it.
            // Note that we also have a GC.KeepAlive call at the end of the method.
            NativeMethods.git_cred_acquire_cb credentialCallback = null;

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

                Proxy.git_remote_set_autotag(remoteHandle, tagFetchMode);

                if (credentials != null)
                {
                    credentialCallback = (out IntPtr cred, IntPtr url, IntPtr username_from_url, uint types, IntPtr payload) =>
                        NativeMethods.git_cred_userpass_plaintext_new(out cred, credentials.Username, credentials.Password);

                    Proxy.git_remote_set_cred_acquire_cb(
                        remoteHandle,
                        credentialCallback,
                        IntPtr.Zero);
                }

                // It is OK to pass the reference to the GitCallbacks directly here because libgit2 makes a copy of
                // the data in the git_remote_callbacks structure. If, in the future, libgit2 changes its implementation
                // to store a reference to the git_remote_callbacks structure this would introduce a subtle bug
                // where the managed layer could move the git_remote_callbacks to a different location in memory,
                // but libgit2 would still reference the old address.
                //
                // Also, if GitRemoteCallbacks were a class instead of a struct, we would need to guard against
                // GC occuring in between setting the remote callbacks and actual usage in one of the functions afterwords.
                Proxy.git_remote_set_callbacks(remoteHandle, ref gitCallbacks);

                try
                {
                    Proxy.git_remote_connect(remoteHandle, GitDirection.Fetch);
                    Proxy.git_remote_download(remoteHandle, onTransferProgress);
                    Proxy.git_remote_update_tips(remoteHandle);
                }
                finally
                {
                    Proxy.git_remote_disconnect(remoteHandle);
                }
            }

            // To be safe, make sure the credential callback is kept until
            // alive until at least this point.
            GC.KeepAlive(credentialCallback);
        }
 /// <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;
 }