diff --git a/LibGit2Sharp.Tests/CloneFixture.cs b/LibGit2Sharp.Tests/CloneFixture.cs index 09af475f..be940881 100644 --- a/LibGit2Sharp.Tests/CloneFixture.cs +++ b/LibGit2Sharp.Tests/CloneFixture.cs @@ -46,7 +46,7 @@ public void CanCloneWithCheckoutBranchName(string branchName, string headTipId) { var scd = BuildSelfCleaningDirectory(); - string clonedRepoPath = Repository.Clone(BareTestRepoPath, scd.DirectoryPath, new CloneOptions { BranchName = branchName }); + string clonedRepoPath = Repository.Clone(BareTestRepoPath, scd.DirectoryPath, new CloneOptions { BranchName = branchName }, new ProxyOptions()); using (var repo = new Repository(clonedRepoPath)) { @@ -112,7 +112,7 @@ public void CanCloneBarely(string url) string clonedRepoPath = Repository.Clone(url, scd.DirectoryPath, new CloneOptions { IsBare = true - }); + }, new ProxyOptions()); using (var repo = new Repository(clonedRepoPath)) { @@ -135,7 +135,7 @@ public void WontCheckoutIfAskedNotTo(string url) string clonedRepoPath = Repository.Clone(url, scd.DirectoryPath, new CloneOptions() { Checkout = false - }); + }, new ProxyOptions()); using (var repo = new Repository(clonedRepoPath)) { @@ -160,7 +160,7 @@ public void CallsProgressCallbacks(string url) OnProgress = progress => { progressWasCalled = true; return true; }, OnUpdateTips = (name, oldId, newId) => { updateTipsWasCalled = true; return true; }, OnCheckoutProgress = (a, b, c) => checkoutWasCalled = true - }); + }, new ProxyOptions()); Assert.True(transferWasCalled); Assert.True(progressWasCalled); @@ -180,7 +180,7 @@ public void CanCloneWithCredentials() new CloneOptions() { CredentialsProvider = Constants.PrivateRepoCredentials - }); + }, new ProxyOptions()); using (var repo = new Repository(clonedRepoPath)) @@ -223,7 +223,7 @@ public void CanCloneFromBBWithCredentials(string url, string user, string pass, string clonedRepoPath = Repository.Clone(url, scd.DirectoryPath, new CloneOptions() { CredentialsProvider = (_url, _user, _cred) => CreateUsernamePasswordCredentials (user, pass, secure) - }); + }, new ProxyOptions()); using (var repo = new Repository(clonedRepoPath)) { @@ -290,7 +290,7 @@ public void CanInspectCertificateOnClone(string url, string hostname, Type certT }; Assert.Throws(() => - Repository.Clone(url, scd.DirectoryPath, options) + Repository.Clone(url, scd.DirectoryPath, options, new ProxyOptions()) ); Assert.True(wasCalled); @@ -438,7 +438,7 @@ public void CanRecursivelyCloneSubmodules() RepositoryOperationCompleted = repositoryOperationCompleted, }; - string clonedRepoPath = Repository.Clone(uri.AbsolutePath, scd.DirectoryPath, options); + string clonedRepoPath = Repository.Clone(uri.AbsolutePath, scd.DirectoryPath, options, new ProxyOptions()); string workDirPath; using(Repository repo = new Repository(clonedRepoPath)) @@ -522,7 +522,7 @@ public void CanCancelRecursiveClone() }; Assert.Throws(() => - Repository.Clone(uri.AbsolutePath, scd.DirectoryPath, options)); + Repository.Clone(uri.AbsolutePath, scd.DirectoryPath, options, new ProxyOptions())); // Cancel after super repository is cloned, but before submodule is cloned. cancelDepth = 1; @@ -531,7 +531,7 @@ public void CanCancelRecursiveClone() try { - Repository.Clone(uri.AbsolutePath, scd.DirectoryPath, options); + Repository.Clone(uri.AbsolutePath, scd.DirectoryPath, options, new ProxyOptions()); } catch(RecurseSubmodulesException ex) { @@ -563,7 +563,7 @@ public void CannotCloneWithForbiddenCustomHeaders() FetchOptions = new FetchOptions { CustomHeaders = new String[] { knownHeader } } }; - Assert.Throws(() => Repository.Clone(url, scd.DirectoryPath, cloneOptions)); + Assert.Throws(() => Repository.Clone(url, scd.DirectoryPath, cloneOptions, new ProxyOptions())); } [Fact] @@ -579,7 +579,7 @@ public void CannotCloneWithMalformedCustomHeaders() FetchOptions = new FetchOptions { CustomHeaders = new String[] { knownHeader } } }; - Assert.Throws(() => Repository.Clone(url, scd.DirectoryPath, cloneOptions)); + Assert.Throws(() => Repository.Clone(url, scd.DirectoryPath, cloneOptions, new ProxyOptions())); } [Fact] @@ -595,7 +595,7 @@ public void CanCloneWithCustomHeaders() FetchOptions = new FetchOptions { CustomHeaders = new String[] { knownHeader } } }; - var clonedRepoPath = Repository.Clone(url, scd.DirectoryPath, cloneOptions); + var clonedRepoPath = Repository.Clone(url, scd.DirectoryPath, cloneOptions, new ProxyOptions()); Assert.True(Directory.Exists(clonedRepoPath)); } } diff --git a/LibGit2Sharp.Tests/FetchFixture.cs b/LibGit2Sharp.Tests/FetchFixture.cs index 170b64d6..8e50683f 100644 --- a/LibGit2Sharp.Tests/FetchFixture.cs +++ b/LibGit2Sharp.Tests/FetchFixture.cs @@ -44,7 +44,7 @@ public void CanFetchIntoAnEmptyRepository(string url) } // Perform the actual fetch - Commands.Fetch(repo, remoteName, new string[0], new FetchOptions { OnUpdateTips = expectedFetchState.RemoteUpdateTipsHandler }, null); + Commands.Fetch(repo, remoteName, new string[0], new FetchOptions { OnUpdateTips = expectedFetchState.RemoteUpdateTipsHandler }, null, new ProxyOptions()); // Verify the expected expectedFetchState.CheckUpdatedReferences(repo); @@ -67,7 +67,7 @@ public void CanFetchIntoAnEmptyRepositoryWithCredentials() Commands.Fetch(repo, remoteName, new string[0], new FetchOptions { CredentialsProvider = Constants.PrivateRepoCredentials - }, null); + }, null, new ProxyOptions()); } } @@ -104,7 +104,7 @@ public void CanFetchAllTagsIntoAnEmptyRepository(string url) Commands.Fetch(repo, remoteName, new string[0], new FetchOptions { TagFetchMode = TagFetchMode.All, OnUpdateTips = expectedFetchState.RemoteUpdateTipsHandler - }, null); + }, null, new ProxyOptions()); // Verify the expected expectedFetchState.CheckUpdatedReferences(repo); @@ -150,7 +150,7 @@ public void CanFetchCustomRefSpecsIntoAnEmptyRepository(string url, string local Commands.Fetch(repo, remoteName, new string[] { refSpec }, new FetchOptions { TagFetchMode = TagFetchMode.None, OnUpdateTips = expectedFetchState.RemoteUpdateTipsHandler - }, null); + }, null, new ProxyOptions()); // Verify the expected expectedFetchState.CheckUpdatedReferences(repo); @@ -181,7 +181,7 @@ public void FetchRespectsConfiguredAutoTagSetting(TagFetchMode tagFetchMode, int r => r.TagFetchMode = tagFetchMode); // Perform the actual fetch. - Commands.Fetch(repo, remoteName, new string[0], null, null); + Commands.Fetch(repo, remoteName, new string[0], null, null, null); // Verify the number of fetched tags. Assert.Equal(expectedTagCount, repo.Tags.Count()); @@ -199,7 +199,7 @@ public void CanFetchAllTagsAfterAnInitialClone() using (var repo = new Repository(clonedRepoPath)) { - Commands.Fetch(repo, "origin", new string[0], new FetchOptions { TagFetchMode = TagFetchMode.All }, null); + Commands.Fetch(repo, "origin", new string[0], new FetchOptions { TagFetchMode = TagFetchMode.All }, null, new ProxyOptions()); } } @@ -225,17 +225,17 @@ public void FetchHonorsTheFetchPruneConfigurationEntry() // No pruning when the configuration entry isn't defined Assert.Null(clonedRepo.Config.Get("fetch.prune")); - Commands.Fetch(clonedRepo, "origin", new string[0], null, null); + Commands.Fetch(clonedRepo, "origin", new string[0], null, null, null); Assert.Equal(5, clonedRepo.Branches.Count(b => b.IsRemote)); // No pruning when the configuration entry is set to false clonedRepo.Config.Set("fetch.prune", false); - Commands.Fetch(clonedRepo, "origin", new string[0], null, null); + Commands.Fetch(clonedRepo, "origin", new string[0], null, null, null); Assert.Equal(5, clonedRepo.Branches.Count(b => b.IsRemote)); // Auto pruning when the configuration entry is set to true clonedRepo.Config.Set("fetch.prune", true); - Commands.Fetch(clonedRepo, "origin", new string[0], null, null); + Commands.Fetch(clonedRepo, "origin", new string[0], null, null, null); Assert.Equal(4, clonedRepo.Branches.Count(b => b.IsRemote)); } } @@ -253,7 +253,7 @@ public void CannotFetchWithForbiddenCustomHeaders() var options = new FetchOptions { CustomHeaders = new String[] { knownHeader } }; using (var repo = new Repository(clonedRepoPath)) { - Assert.Throws(() => Commands.Fetch(repo, "origin", new string[0], options, null)); + Assert.Throws(() => Commands.Fetch(repo, "origin", new string[0], options, null, new ProxyOptions())); } } @@ -270,7 +270,7 @@ public void CanFetchWithCustomHeaders() var options = new FetchOptions { CustomHeaders = new String[] { knownHeader } }; using (var repo = new Repository(clonedRepoPath)) { - Commands.Fetch(repo, "origin", new string[0], options, null); + Commands.Fetch(repo, "origin", new string[0], options, null, new ProxyOptions()); } } @@ -287,7 +287,7 @@ public void CannotFetchWithMalformedCustomHeaders() var options = new FetchOptions { CustomHeaders = new String[] { knownHeader } }; using (var repo = new Repository(clonedRepoPath)) { - Assert.Throws(() => Commands.Fetch(repo, "origin", new string[0], options, null)); + Assert.Throws(() => Commands.Fetch(repo, "origin", new string[0], options, null, new ProxyOptions())); } } diff --git a/LibGit2Sharp.Tests/NetworkFixture.cs b/LibGit2Sharp.Tests/NetworkFixture.cs index 3ac73a2e..21365809 100644 --- a/LibGit2Sharp.Tests/NetworkFixture.cs +++ b/LibGit2Sharp.Tests/NetworkFixture.cs @@ -130,7 +130,7 @@ public void CanListRemoteReferencesWithCredentials() { Remote remote = repo.Network.Remotes.Add(remoteName, Constants.PrivateRepoUrl); - var references = repo.Network.ListReferences(remote, Constants.PrivateRepoCredentials); + var references = repo.Network.ListReferences(remote, Constants.PrivateRepoCredentials, new ProxyOptions()); foreach (var reference in references) { @@ -164,7 +164,7 @@ public void CanPull(FastForwardStrategy fastForwardStrategy) } }; - MergeResult mergeResult = Commands.Pull(repo, Constants.Signature, pullOptions); + MergeResult mergeResult = Commands.Pull(repo, Constants.Signature, pullOptions, new ProxyOptions()); if(fastForwardStrategy == FastForwardStrategy.Default || fastForwardStrategy == FastForwardStrategy.FastForwardOnly) { @@ -197,7 +197,7 @@ public void CanPullIntoEmptyRepo() b => b.UpstreamBranch = "refs/heads/master"); // Pull! - MergeResult mergeResult = Commands.Pull(repo, Constants.Signature, new PullOptions()); + MergeResult mergeResult = Commands.Pull(repo, Constants.Signature, new PullOptions(), new ProxyOptions()); Assert.Equal(MergeStatus.FastForward, mergeResult.Status); Assert.Equal(mergeResult.Commit, repo.Branches["refs/remotes/origin/master"].Tip); @@ -224,7 +224,7 @@ public void PullWithoutMergeBranchThrows() try { - Commands.Pull(repo, Constants.Signature, new PullOptions()); + Commands.Pull(repo, Constants.Signature, new PullOptions(), new ProxyOptions()); } catch(MergeFetchHeadNotFoundException ex) { @@ -252,7 +252,7 @@ public void CanMergeFetchedRefs() Assert.False(repo.RetrieveStatus().Any()); Assert.Equal(repo.Lookup("refs/remotes/origin/master~1"), repo.Head.Tip); - Commands.Fetch(repo, repo.Head.RemoteName, new string[0], null, null); + Commands.Fetch(repo, repo.Head.RemoteName, new string[0], null, null, null); MergeOptions mergeOptions = new MergeOptions() { @@ -279,7 +279,7 @@ public void CanPruneRefs() using (var repo = new Repository(clonedRepoPath)) { repo.Network.Remotes.Add("pruner", clonedRepoPath2); - Commands.Fetch(repo, "pruner", new string[0], null, null); + Commands.Fetch(repo, "pruner", new string[0], null, null, null); Assert.NotNull(repo.Refs["refs/remotes/pruner/master"]); // Remove the branch from the source repository @@ -289,11 +289,11 @@ public void CanPruneRefs() } // and by default we don't prune it - Commands.Fetch(repo, "pruner", new string[0], null, null); + Commands.Fetch(repo, "pruner", new string[0], null, null, null); Assert.NotNull(repo.Refs["refs/remotes/pruner/master"]); // but we do when asked by the user - Commands.Fetch(repo, "pruner", new string[0], new FetchOptions { Prune = true}, null); + Commands.Fetch(repo, "pruner", new string[0], new FetchOptions { Prune = true}, null, new ProxyOptions()); Assert.Null(repo.Refs["refs/remotes/pruner/master"]); } } diff --git a/LibGit2Sharp.Tests/PushFixture.cs b/LibGit2Sharp.Tests/PushFixture.cs index d8cf2bef..e61c0b0f 100644 --- a/LibGit2Sharp.Tests/PushFixture.cs +++ b/LibGit2Sharp.Tests/PushFixture.cs @@ -75,7 +75,7 @@ public void CanPushABranchTrackingAnUpstreamBranch() OnPackBuilderProgress = packBuilderCb, }; - AssertPush(repo => repo.Network.Push(repo.Network.Remotes["origin"], "HEAD", @"refs/heads/master", options)); + AssertPush(repo => repo.Network.Push(repo.Network.Remotes["origin"], "HEAD", @"refs/heads/master", options, new ProxyOptions())); Assert.True(packBuilderCalled); } @@ -102,7 +102,7 @@ public void CanInvokePrePushCallbackAndSucceed() OnNegotiationCompletedBeforePush = prePushHook, }; - AssertPush(repo => repo.Network.Push(repo.Network.Remotes["origin"], "HEAD", @"refs/heads/master", options)); + AssertPush(repo => repo.Network.Push(repo.Network.Remotes["origin"], "HEAD", @"refs/heads/master", options, new ProxyOptions())); Assert.True(packBuilderCalled); Assert.True(prePushHandlerCalled); } @@ -130,7 +130,7 @@ public void CanInvokePrePushCallbackAndFail() OnNegotiationCompletedBeforePush = prePushHook }; - Assert.Throws(() => { AssertPush(repo => repo.Network.Push(repo.Network.Remotes["origin"], "HEAD", @"refs/heads/master", options)); }); + Assert.Throws(() => { AssertPush(repo => repo.Network.Push(repo.Network.Remotes["origin"], "HEAD", @"refs/heads/master", options, new ProxyOptions())); }); Assert.False(packBuilderCalled); Assert.True(prePushHandlerCalled); diff --git a/LibGit2Sharp.Tests/RepositoryFixture.cs b/LibGit2Sharp.Tests/RepositoryFixture.cs index 5c551fab..6e8a582a 100644 --- a/LibGit2Sharp.Tests/RepositoryFixture.cs +++ b/LibGit2Sharp.Tests/RepositoryFixture.cs @@ -213,13 +213,13 @@ public void CanFetchFromRemoteByName() } // Perform the actual fetch - Commands.Fetch(repo, remoteName, new string[0], new FetchOptions { OnUpdateTips = expectedFetchState.RemoteUpdateTipsHandler }, null); + Commands.Fetch(repo, remoteName, new string[0], new FetchOptions { OnUpdateTips = expectedFetchState.RemoteUpdateTipsHandler }, null, new ProxyOptions()); // Verify the expected state expectedFetchState.CheckUpdatedReferences(repo); // Now fetch the rest of the tags - Commands.Fetch(repo, remoteName, new string[0], new FetchOptions { TagFetchMode = TagFetchMode.All }, null); + Commands.Fetch(repo, remoteName, new string[0], new FetchOptions { TagFetchMode = TagFetchMode.All }, null, new ProxyOptions()); // Verify that the "nearly-dangling" tag is now in the repo. Tag nearlyDanglingTag = repo.Tags["nearly-dangling"]; @@ -698,7 +698,7 @@ public void CanListRemoteReferencesWithCredentials() "Populate Constants.PrivateRepo* to run this test"); IEnumerable references = Repository.ListRemoteReferences(Constants.PrivateRepoUrl, - Constants.PrivateRepoCredentials); + Constants.PrivateRepoCredentials, new ProxyOptions()); foreach (var reference in references) { diff --git a/LibGit2Sharp.Tests/SubmoduleFixture.cs b/LibGit2Sharp.Tests/SubmoduleFixture.cs index 735bfd93..2f37d202 100644 --- a/LibGit2Sharp.Tests/SubmoduleFixture.cs +++ b/LibGit2Sharp.Tests/SubmoduleFixture.cs @@ -215,7 +215,7 @@ public void UpdatingUninitializedSubmoduleThrows() Assert.NotNull(submodule); Assert.True(submodule.RetrieveStatus().HasFlag(SubmoduleStatus.WorkDirUninitialized)); - Assert.Throws(() => repo.Submodules.Update(submodule.Name, new SubmoduleUpdateOptions())); + Assert.Throws(() => repo.Submodules.Update(submodule.Name, new SubmoduleUpdateOptions(), new ProxyOptions())); } } @@ -244,7 +244,7 @@ public void CanUpdateSubmodule() }; repo.Submodules.Init(submodule.Name, false); - repo.Submodules.Update(submodule.Name, options); + repo.Submodules.Update(submodule.Name, options, new ProxyOptions()); Assert.True(submodule.RetrieveStatus().HasFlag(SubmoduleStatus.InWorkDir)); Assert.True(checkoutProgressCalled); @@ -269,7 +269,7 @@ public void CanInitializeAndUpdateSubmodule() Assert.NotNull(submodule); Assert.True(submodule.RetrieveStatus().HasFlag(SubmoduleStatus.WorkDirUninitialized)); - repo.Submodules.Update(submodule.Name, new SubmoduleUpdateOptions() { Init = true }); + repo.Submodules.Update(submodule.Name, new SubmoduleUpdateOptions() { Init = true }, new ProxyOptions()); Assert.True(submodule.RetrieveStatus().HasFlag(SubmoduleStatus.InWorkDir)); Assert.Equal((ObjectId)"480095882d281ed676fe5b863569520e54a7d5c0", submodule.HeadCommitId); @@ -292,7 +292,7 @@ public void CanUpdateSubmoduleAfterCheckout() Assert.True(submodule.RetrieveStatus().HasFlag(SubmoduleStatus.WorkDirUninitialized)); repo.Submodules.Init(submodule.Name, false); - repo.Submodules.Update(submodule.Name, new SubmoduleUpdateOptions()); + repo.Submodules.Update(submodule.Name, new SubmoduleUpdateOptions(), new ProxyOptions()); Assert.True(submodule.RetrieveStatus().HasFlag(SubmoduleStatus.InWorkDir)); @@ -305,7 +305,7 @@ public void CanUpdateSubmoduleAfterCheckout() Assert.Equal((ObjectId)"5e4963595a9774b90524d35a807169049de8ccad", submodule.IndexCommitId); Assert.Equal((ObjectId)"480095882d281ed676fe5b863569520e54a7d5c0", submodule.WorkDirCommitId); - repo.Submodules.Update(submodule.Name, new SubmoduleUpdateOptions()); + repo.Submodules.Update(submodule.Name, new SubmoduleUpdateOptions(), new ProxyOptions()); submodule = repo.Submodules[submoduleName]; Assert.Equal((ObjectId)"5e4963595a9774b90524d35a807169049de8ccad", submodule.HeadCommitId); diff --git a/LibGit2Sharp.Tests/desktop/SmartSubtransportFixture.cs b/LibGit2Sharp.Tests/desktop/SmartSubtransportFixture.cs index e72c0d7c..88b614c4 100644 --- a/LibGit2Sharp.Tests/desktop/SmartSubtransportFixture.cs +++ b/LibGit2Sharp.Tests/desktop/SmartSubtransportFixture.cs @@ -65,7 +65,7 @@ public void CustomSmartSubtransportTest(string scheme, string url) // Perform the actual fetch Commands.Fetch(repo, remoteName, new string[0], new FetchOptions { OnUpdateTips = expectedFetchState.RemoteUpdateTipsHandler, TagFetchMode = TagFetchMode.Auto }, - null); + null, new ProxyOptions()); // Verify the expected expectedFetchState.CheckUpdatedReferences(repo); @@ -118,7 +118,7 @@ public void CanUseCredentials(string scheme, string url, string user, string pas Commands.Fetch(repo, remoteName, new string[0], new FetchOptions { OnUpdateTips = expectedFetchState.RemoteUpdateTipsHandler, TagFetchMode = TagFetchMode.Auto, CredentialsProvider = (_user, _valid, _hostname) => new UsernamePasswordCredentials() { Username = user, Password = pass }, - }, null); + }, null, new ProxyOptions()); // Verify the expected expectedFetchState.CheckUpdatedReferences(repo); diff --git a/LibGit2Sharp/Commands/Fetch.cs b/LibGit2Sharp/Commands/Fetch.cs index eda0a671..dbea765c 100644 --- a/LibGit2Sharp/Commands/Fetch.cs +++ b/LibGit2Sharp/Commands/Fetch.cs @@ -29,18 +29,19 @@ private static RemoteHandle RemoteFromNameOrUrl(RepositoryHandle repoHandle, str /// /// The repository in which to fetch. /// The remote to fetch from. Either as a remote name or a URL + /// List of refspecs to apply as active. /// Fetch options. /// Log message for any ref updates. - /// List of refspecs to apply as active. - public static void Fetch(Repository repository, string remote, IEnumerable refspecs, FetchOptions options, string logMessage) + /// Proxy options. + public static void Fetch(Repository repository, string remote, IEnumerable refspecs, FetchOptions options, string logMessage, ProxyOptions proxy) { Ensure.ArgumentNotNull(remote, "remote"); options = options ?? new FetchOptions(); using (var remoteHandle = RemoteFromNameOrUrl(repository.Handle, remote)) using (var fetchOptionsWrapper = new GitFetchOptionsWrapper()) + using (var proxyOptionsWrapper = new GitProxyOptionsWrapper(proxy)) { - var callbacks = new RemoteCallbacks(options); GitRemoteCallbacks gitCallbacks = callbacks.GenerateCallbacks(); @@ -75,7 +76,7 @@ public static void Fetch(Repository repository, string remote, IEnumerableThe repository. /// The signature to use for the merge. /// The options for fetch and merging. - public static MergeResult Pull(Repository repository, Signature merger, PullOptions options) + /// The options for proxy settings. + public static MergeResult Pull(Repository repository, Signature merger, PullOptions options, ProxyOptions proxy) { Ensure.ArgumentNotNull(repository, "repository"); Ensure.ArgumentNotNull(merger, "merger"); @@ -34,7 +35,7 @@ public static MergeResult Pull(Repository repository, Signature merger, PullOpti throw new LibGit2SharpException("No upstream remote for the current branch."); } - Commands.Fetch(repository, currentBranch.RemoteName, new string[0], options.FetchOptions, null); + Commands.Fetch(repository, currentBranch.RemoteName, new string[0], options.FetchOptions, null, proxy); return repository.MergeFetchedRefs(merger, options.MergeOptions); } } diff --git a/LibGit2Sharp/Core/GitProxyOptions.cs b/LibGit2Sharp/Core/GitProxyOptions.cs index b62b8e08..f9818a28 100644 --- a/LibGit2Sharp/Core/GitProxyOptions.cs +++ b/LibGit2Sharp/Core/GitProxyOptions.cs @@ -16,8 +16,8 @@ internal struct GitProxyOptions public uint Version; public GitProxyType Type; public IntPtr Url; - public IntPtr CredentialsCb; - public IntPtr CertificateCheck; + public NativeMethods.git_cred_acquire_cb CredentialsCb; + public NativeMethods.git_transport_certificate_check_cb CertificateCheck; public IntPtr CbPayload; } } diff --git a/LibGit2Sharp/Core/GitProxyOptionsWrapper.cs b/LibGit2Sharp/Core/GitProxyOptionsWrapper.cs new file mode 100644 index 00000000..4fdc7980 --- /dev/null +++ b/LibGit2Sharp/Core/GitProxyOptionsWrapper.cs @@ -0,0 +1,54 @@ +using System; + +namespace LibGit2Sharp.Core +{ + internal class GitProxyOptionsWrapper : IDisposable + { + public GitProxyOptionsWrapper(ProxyOptions proxyOptions) + { + GitProxyOptions = BuildFrom(proxyOptions); + } + + internal GitProxyOptions GitProxyOptions; + + private GitRemoteCallbacks GitCallbacks; + + private GitProxyOptions BuildFrom(ProxyOptions proxyOptions) + { + var opts = new GitProxyOptions + { + Version = 1, + Type = GitProxyType.Auto + }; + + if (proxyOptions == null) + { + return opts; + } + + if (proxyOptions.Url != null) + { + opts.Url = StrictUtf8Marshaler.FromManaged(proxyOptions.Url); + opts.Type = GitProxyType.Specified; + } + + if (proxyOptions.CredentialsProvider != null || + proxyOptions.CertificateCheck != null) + { + var callbacks = new RemoteCallbacks(proxyOptions.CredentialsProvider, proxyOptions.CertificateCheck); + GitCallbacks = callbacks.GenerateCallbacks(); + + opts.CredentialsCb = GitCallbacks.acquire_credentials; + opts.CertificateCheck = GitCallbacks.certificate_check; + } + + return opts; + } + + public void Dispose() + { + EncodingMarshaler.Cleanup(GitProxyOptions.Url); + GitProxyOptions.Url = IntPtr.Zero; + } + } +} diff --git a/LibGit2Sharp/LibGit2Sharp.csproj b/LibGit2Sharp/LibGit2Sharp.csproj index 7625c654..52e0fedd 100644 --- a/LibGit2Sharp/LibGit2Sharp.csproj +++ b/LibGit2Sharp/LibGit2Sharp.csproj @@ -34,7 +34,7 @@ - + diff --git a/LibGit2Sharp/Network.cs b/LibGit2Sharp/Network.cs index 95ab3bd5..95851207 100644 --- a/LibGit2Sharp/Network.cs +++ b/LibGit2Sharp/Network.cs @@ -52,7 +52,7 @@ public virtual IEnumerable ListReferences(Remote remote) { Ensure.ArgumentNotNull(remote, "remote"); - return ListReferencesInternal(remote.Url, null); + return ListReferencesInternal(remote.Url, null, null); } /// @@ -66,13 +66,14 @@ public virtual IEnumerable ListReferences(Remote remote) /// /// The to list from. /// The used to connect to remote repository. + /// controlling proxy settings /// The references in the repository. - public virtual IEnumerable ListReferences(Remote remote, CredentialsHandler credentialsProvider) + public virtual IEnumerable ListReferences(Remote remote, CredentialsHandler credentialsProvider, ProxyOptions proxyOptions) { Ensure.ArgumentNotNull(remote, "remote"); Ensure.ArgumentNotNull(credentialsProvider, "credentialsProvider"); - return ListReferencesInternal(remote.Url, credentialsProvider); + return ListReferencesInternal(remote.Url, credentialsProvider, proxyOptions); } /// @@ -90,7 +91,7 @@ public virtual IEnumerable ListReferences(string url) { Ensure.ArgumentNotNull(url, "url"); - return ListReferencesInternal(url, null); + return ListReferencesInternal(url, null, null); } /// @@ -104,21 +105,23 @@ public virtual IEnumerable ListReferences(string url) /// /// The url to list from. /// The used to connect to remote repository. + /// controlling proxy settings /// The references in the remote repository. - public virtual IEnumerable ListReferences(string url, CredentialsHandler credentialsProvider) + public virtual IEnumerable ListReferences(string url, CredentialsHandler credentialsProvider, ProxyOptions proxyOptions) { Ensure.ArgumentNotNull(url, "url"); Ensure.ArgumentNotNull(credentialsProvider, "credentialsProvider"); - return ListReferencesInternal(url, credentialsProvider); + return ListReferencesInternal(url, credentialsProvider, proxyOptions); } - private IEnumerable ListReferencesInternal(string url, CredentialsHandler credentialsProvider) + private IEnumerable ListReferencesInternal(string url, CredentialsHandler credentialsProvider, ProxyOptions proxyOptions) { using (RemoteHandle remoteHandle = BuildRemoteHandle(repository.Handle, url)) + using (GitProxyOptionsWrapper proxyOptionsWrapper = new GitProxyOptionsWrapper(proxyOptions)) { GitRemoteCallbacks gitCallbacks = new GitRemoteCallbacks { version = 1 }; - GitProxyOptions proxyOptions = new GitProxyOptions { Version = 1, Type = GitProxyType.Auto }; + GitProxyOptions gitProxyOptions = proxyOptionsWrapper.GitProxyOptions; if (credentialsProvider != null) { @@ -126,7 +129,7 @@ private IEnumerable ListReferencesInternal(string url, CredentialsHan gitCallbacks = callbacks.GenerateCallbacks(); } - Proxy.git_remote_connect(remoteHandle, GitDirection.Fetch, ref gitCallbacks, ref proxyOptions); + Proxy.git_remote_connect(remoteHandle, GitDirection.Fetch, ref gitCallbacks, ref gitProxyOptions); return Proxy.git_remote_ls(repository, remoteHandle); } } @@ -149,7 +152,7 @@ static RemoteHandle BuildRemoteHandle(RepositoryHandle repoHandle, string url) /// The list of resfpecs to use public virtual void Fetch(string url, IEnumerable refspecs) { - Fetch(url, refspecs, null, null); + Fetch(url, refspecs, null, null, null); } /// @@ -158,9 +161,10 @@ public virtual void Fetch(string url, IEnumerable refspecs) /// The url to fetch from /// The list of resfpecs to use /// controlling fetch behavior - public virtual void Fetch(string url, IEnumerable refspecs, FetchOptions options) + /// controlling proxy settings + public virtual void Fetch(string url, IEnumerable refspecs, FetchOptions options, ProxyOptions proxy) { - Fetch(url, refspecs, options, null); + Fetch(url, refspecs, options, null, proxy); } /// @@ -171,7 +175,7 @@ public virtual void Fetch(string url, IEnumerable refspecs, FetchOptions /// Message to use when updating the reflog. public virtual void Fetch(string url, IEnumerable refspecs, string logMessage) { - Fetch(url, refspecs, null, logMessage); + Fetch(url, refspecs, null, logMessage, null); } /// @@ -181,16 +185,18 @@ public virtual void Fetch(string url, IEnumerable refspecs, string logMe /// The list of resfpecs to use /// controlling fetch behavior /// Message to use when updating the reflog. + /// controlling proxy settings public virtual void Fetch( string url, IEnumerable refspecs, FetchOptions options, - string logMessage) + string logMessage, + ProxyOptions proxy) { Ensure.ArgumentNotNull(url, "url"); Ensure.ArgumentNotNull(refspecs, "refspecs"); - Commands.Fetch(repository, url, refspecs, options, logMessage); + Commands.Fetch(repository, url, refspecs, options, logMessage, proxy); } /// @@ -208,12 +214,14 @@ public virtual void Push( /// /// The branch to push. /// controlling push behavior + /// controlling proxy settings /// Throws if either the Remote or the UpstreamBranchCanonicalName is not set. public virtual void Push( Branch branch, - PushOptions pushOptions) + PushOptions pushOptions, + ProxyOptions proxyOptions) { - Push(new[] { branch }, pushOptions); + Push(new[] { branch }, pushOptions, proxyOptions); } /// @@ -224,7 +232,7 @@ public virtual void Push( public virtual void Push( IEnumerable branches) { - Push(branches, null); + Push(branches, null, null); } /// @@ -232,10 +240,12 @@ public virtual void Push( /// /// The branches to push. /// controlling push behavior + /// controlling proxy settings /// Throws if either the Remote or the UpstreamBranchCanonicalName is not set. public virtual void Push( IEnumerable branches, - PushOptions pushOptions) + PushOptions pushOptions, + ProxyOptions proxyOptions) { var enumeratedBranches = branches as IList ?? branches.ToList(); @@ -254,7 +264,7 @@ public virtual void Push( { Push(remote, string.Format( CultureInfo.InvariantCulture, - "{0}:{1}", branch.CanonicalName, branch.UpstreamBranchCanonicalName), pushOptions); + "{0}:{1}", branch.CanonicalName, branch.UpstreamBranchCanonicalName), pushOptions, proxyOptions); } } } @@ -287,11 +297,13 @@ public virtual void Push( /// The source objectish to push. /// The reference to update on the remote. /// controlling push behavior + /// controlling proxy settings public virtual void Push( Remote remote, string objectish, string destinationSpec, - PushOptions pushOptions) + PushOptions pushOptions, + ProxyOptions proxyOptions) { Ensure.ArgumentNotNull(objectish, "objectish"); Ensure.ArgumentNotNullOrEmptyString(destinationSpec, "destinationSpec"); @@ -301,7 +313,8 @@ public virtual void Push( "{0}:{1}", objectish, destinationSpec), - pushOptions); + pushOptions, + proxyOptions); } /// @@ -321,14 +334,16 @@ public virtual void Push(Remote remote, string pushRefSpec) /// The to push to. /// The pushRefSpec to push. /// controlling push behavior + /// controlling proxy settings public virtual void Push( Remote remote, string pushRefSpec, - PushOptions pushOptions) + PushOptions pushOptions, + ProxyOptions proxyOptions) { Ensure.ArgumentNotNullOrEmptyString(pushRefSpec, "pushRefSpec"); - Push(remote, new[] { pushRefSpec }, pushOptions); + Push(remote, new[] { pushRefSpec }, pushOptions, proxyOptions); } /// @@ -338,7 +353,7 @@ public virtual void Push( /// The pushRefSpecs to push. public virtual void Push(Remote remote, IEnumerable pushRefSpecs) { - Push(remote, pushRefSpecs, null); + Push(remote, pushRefSpecs, null, null); } /// @@ -347,7 +362,8 @@ public virtual void Push(Remote remote, IEnumerable pushRefSpecs) /// The to push to. /// The pushRefSpecs to push. /// controlling push behavior - public virtual void Push(Remote remote, IEnumerable pushRefSpecs, PushOptions pushOptions) + /// controlling proxy settings + public virtual void Push(Remote remote, IEnumerable pushRefSpecs, PushOptions pushOptions, ProxyOptions proxyOptions) { Ensure.ArgumentNotNull(remote, "remote"); Ensure.ArgumentNotNull(pushRefSpecs, "pushRefSpecs"); @@ -365,6 +381,7 @@ public virtual void Push(Remote remote, IEnumerable pushRefSpecs, PushOp // Load the remote. using (RemoteHandle remoteHandle = Proxy.git_remote_lookup(repository.Handle, remote.Name, true)) + using (GitProxyOptionsWrapper proxyOptionsWrapper = new GitProxyOptionsWrapper(proxyOptions)) { var callbacks = new RemoteCallbacks(pushOptions); GitRemoteCallbacks gitCallbacks = callbacks.GenerateCallbacks(); @@ -375,7 +392,7 @@ public virtual void Push(Remote remote, IEnumerable pushRefSpecs, PushOp { PackbuilderDegreeOfParallelism = pushOptions.PackbuilderDegreeOfParallelism, RemoteCallbacks = gitCallbacks, - ProxyOptions = new GitProxyOptions { Version = 1, Type = GitProxyType.Auto }, + ProxyOptions = proxyOptionsWrapper.GitProxyOptions, }); } } diff --git a/LibGit2Sharp/ProxyOptions.cs b/LibGit2Sharp/ProxyOptions.cs new file mode 100644 index 00000000..b37e8b24 --- /dev/null +++ b/LibGit2Sharp/ProxyOptions.cs @@ -0,0 +1,26 @@ +using LibGit2Sharp.Handlers; + +namespace LibGit2Sharp +{ + /// + /// Options for connecting through a proxy. + /// + public sealed class ProxyOptions + { + /// + /// The URL of the proxy. + /// + public string Url { get; set; } + + /// + /// This will be called if the remote host requires authentication in order to connect to it. + /// + public CredentialsHandler CredentialsProvider { get; set; } + + /// + /// If cert verification fails, this will be called to let the user make the final decision + /// of whether to allow the connection to proceed. + /// + public CertificateCheckHandler CertificateCheck { get; set; } + } +} diff --git a/LibGit2Sharp/RemoteCallbacks.cs b/LibGit2Sharp/RemoteCallbacks.cs index ce5dccf8..9d2cba70 100644 --- a/LibGit2Sharp/RemoteCallbacks.cs +++ b/LibGit2Sharp/RemoteCallbacks.cs @@ -12,11 +12,16 @@ namespace LibGit2Sharp /// internal class RemoteCallbacks { - internal RemoteCallbacks(CredentialsHandler credentialsProvider) + internal RemoteCallbacks(CredentialsHandler credentialsProvider, CertificateCheckHandler certificateCheck) { CredentialsProvider = credentialsProvider; + CertificateCheck = certificateCheck; } + internal RemoteCallbacks(CredentialsHandler credentialsProvider) + : this(credentialsProvider, null) + { } + internal RemoteCallbacks(PushOptions pushOptions) { if (pushOptions == null) diff --git a/LibGit2Sharp/Repository.cs b/LibGit2Sharp/Repository.cs index e87bd29f..84d17cba 100644 --- a/LibGit2Sharp/Repository.cs +++ b/LibGit2Sharp/Repository.cs @@ -673,7 +673,7 @@ internal Commit LookupCommit(string committish) /// The references in the remote repository. public static IEnumerable ListRemoteReferences(string url) { - return ListRemoteReferences(url, null); + return ListRemoteReferences(url, null, null); } /// @@ -686,13 +686,15 @@ public static IEnumerable ListRemoteReferences(string url) /// /// The url to list from. /// The used to connect to remote repository. + /// controlling proxy settings. /// The references in the remote repository. - public static IEnumerable ListRemoteReferences(string url, CredentialsHandler credentialsProvider) + public static IEnumerable ListRemoteReferences(string url, CredentialsHandler credentialsProvider, ProxyOptions proxyOptions) { Ensure.ArgumentNotNull(url, "url"); using (RepositoryHandle repositoryHandle = Proxy.git_repository_new()) - using (RemoteHandle remoteHandle = ConnectToAnonymousRemote(repositoryHandle, url, credentialsProvider)) + using (GitProxyOptionsWrapper proxyOptionsWrapper = new GitProxyOptionsWrapper(proxyOptions)) + using (RemoteHandle remoteHandle = ConnectToAnonymousRemote(repositoryHandle, url, credentialsProvider, proxyOptionsWrapper.GitProxyOptions)) { return Proxy.git_remote_ls(null, remoteHandle); } @@ -703,24 +705,25 @@ public static IEnumerable ListRemoteReferences(string url, Credential /// /// The url to retrieve from. /// The used to connect to remote repository. + /// controlling proxy settings. /// The reference name. - public static string GetRemoteDefaultBranch(string url, CredentialsHandler credentialsProvider) + public static string GetRemoteDefaultBranch(string url, CredentialsHandler credentialsProvider, ProxyOptions proxyOptions) { Ensure.ArgumentNotNull(url, "url"); using (RepositoryHandle repositoryHandle = Proxy.git_repository_new()) - using (RemoteHandle remoteHandle = ConnectToAnonymousRemote(repositoryHandle, url, credentialsProvider)) + using (GitProxyOptionsWrapper proxyOptionsWrapper = new GitProxyOptionsWrapper(proxyOptions)) + using (RemoteHandle remoteHandle = ConnectToAnonymousRemote(repositoryHandle, url, credentialsProvider, proxyOptionsWrapper.GitProxyOptions)) { return Proxy.git_remote_default_branch(remoteHandle); } } - private static RemoteHandle ConnectToAnonymousRemote(RepositoryHandle repositoryHandle, string url, CredentialsHandler credentialsProvider) + private static RemoteHandle ConnectToAnonymousRemote(RepositoryHandle repositoryHandle, string url, CredentialsHandler credentialsProvider, GitProxyOptions proxyOptions) { RemoteHandle remoteHandle = Proxy.git_remote_create_anonymous(repositoryHandle, url); var gitCallbacks = new GitRemoteCallbacks { version = 1 }; - var proxyOptions = new GitProxyOptions { Version = 1, Type = GitProxyType.Auto }; if (credentialsProvider != null) { @@ -766,7 +769,7 @@ public static string Discover(string startingPath) /// The path to the created repository. public static string Clone(string sourceUrl, string workdirPath) { - return Clone(sourceUrl, workdirPath, null); + return Clone(sourceUrl, workdirPath, null, null); } /// @@ -782,9 +785,9 @@ public static string Clone(string sourceUrl, string workdirPath) /// URI for the remote repository /// Local path to clone into /// controlling clone behavior + /// controlling proxy options /// The path to the created repository. - public static string Clone(string sourceUrl, string workdirPath, - CloneOptions options) + public static string Clone(string sourceUrl, string workdirPath, CloneOptions options, ProxyOptions proxy) { Ensure.ArgumentNotNull(sourceUrl, "sourceUrl"); Ensure.ArgumentNotNull(workdirPath, "workdirPath"); @@ -806,11 +809,12 @@ public static string Clone(string sourceUrl, string workdirPath, using (var checkoutOptionsWrapper = new GitCheckoutOptsWrapper(options)) using (var fetchOptionsWrapper = new GitFetchOptionsWrapper()) + using (var proxyOptionsWrapper = new GitProxyOptionsWrapper(proxy)) { var gitCheckoutOptions = checkoutOptionsWrapper.Options; var gitFetchOptions = fetchOptionsWrapper.Options; - gitFetchOptions.ProxyOptions = new GitProxyOptions { Version = 1, Type = GitProxyType.Auto }; + gitFetchOptions.ProxyOptions = proxyOptionsWrapper.GitProxyOptions; gitFetchOptions.RemoteCallbacks = new RemoteCallbacks(options).GenerateCallbacks(); if (options.FetchOptions != null && options.FetchOptions.CustomHeaders != null) { @@ -849,7 +853,7 @@ public static string Clone(string sourceUrl, string workdirPath, // Recursively clone submodules if requested. try { - RecursivelyCloneSubmodules(options, clonedRepoPath, 1); + RecursivelyCloneSubmodules(options, clonedRepoPath, 1, proxy); } catch (Exception ex) { @@ -868,7 +872,8 @@ public static string Clone(string sourceUrl, string workdirPath, /// Options controlling clone behavior. /// Path of the parent repository. /// The current depth of the recursion. - private static void RecursivelyCloneSubmodules(CloneOptions options, string repoPath, int recursionDepth) + /// Options controlling proxy settings. + private static void RecursivelyCloneSubmodules(CloneOptions options, string repoPath, int recursionDepth, ProxyOptions proxy) { if (options.RecurseSubmodules) { @@ -912,7 +917,7 @@ private static void RecursivelyCloneSubmodules(CloneOptions options, string repo throw new UserCancelledException("Recursive clone of submodules was cancelled."); } - repo.Submodules.Update(sm.Name, updateOptions); + repo.Submodules.Update(sm.Name, updateOptions, proxy); OnRepositoryOperationCompleted(options.RepositoryOperationCompleted, context); @@ -926,7 +931,7 @@ private static void RecursivelyCloneSubmodules(CloneOptions options, string repo // Check submodules to see if they have their own submodules. foreach (string submodule in submodules) { - RecursivelyCloneSubmodules(options, submodule, recursionDepth + 1); + RecursivelyCloneSubmodules(options, submodule, recursionDepth + 1, proxy); } } } diff --git a/LibGit2Sharp/SubmoduleCollection.cs b/LibGit2Sharp/SubmoduleCollection.cs index 6858451e..8fecf694 100644 --- a/LibGit2Sharp/SubmoduleCollection.cs +++ b/LibGit2Sharp/SubmoduleCollection.cs @@ -81,7 +81,8 @@ public virtual void Init(string name, bool overwrite) /// /// The name of the submodule to update. /// Options controlling submodule udpate behavior and callbacks. - public virtual void Update(string name, SubmoduleUpdateOptions options) + /// Options controlling proxy settings. + public virtual void Update(string name, SubmoduleUpdateOptions options, ProxyOptions proxy) { options = options ?? new SubmoduleUpdateOptions(); @@ -94,6 +95,7 @@ public virtual void Update(string name, SubmoduleUpdateOptions options) } using (GitCheckoutOptsWrapper checkoutOptionsWrapper = new GitCheckoutOptsWrapper(options)) + using (GitProxyOptionsWrapper proxyOptionsWrapper = new GitProxyOptionsWrapper(proxy)) { var gitCheckoutOptions = checkoutOptionsWrapper.Options; @@ -106,7 +108,7 @@ public virtual void Update(string name, SubmoduleUpdateOptions options) CheckoutOptions = gitCheckoutOptions, FetchOptions = new GitFetchOptions { - ProxyOptions = new GitProxyOptions { Version = 1, Type = GitProxyType.Auto }, + ProxyOptions = proxyOptionsWrapper.GitProxyOptions, RemoteCallbacks = gitRemoteCallbacks }, CloneCheckoutStrategy = CheckoutStrategy.GIT_CHECKOUT_SAFE diff --git a/version.json b/version.json index a9d8c893..fdff6c69 100644 --- a/version.json +++ b/version.json @@ -1,6 +1,6 @@ { "$schema": "https://raw.githubusercontent.com/AArnott/Nerdbank.GitVersioning/master/src/NerdBank.GitVersioning/version.schema.json", - "version": "1.110.20", + "version": "1.111.0", "cloudBuild": { "buildNumber": { "enabled": true