Skip to content
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

Add proxy options #2065

Merged
merged 9 commits into from
Dec 3, 2023
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.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
108 changes: 56 additions & 52 deletions LibGit2Sharp.Tests/CloneFixture.cs
Original file line number Diff line number Diff line change
Expand Up @@ -151,10 +151,14 @@ public void CallsProgressCallbacks(string url)

Repository.Clone(url, scd.DirectoryPath, new CloneOptions()
{
OnTransferProgress = _ => { transferWasCalled = true; return true; },
OnProgress = progress => { progressWasCalled = true; return true; },
OnUpdateTips = (name, oldId, newId) => { updateTipsWasCalled = true; return true; },
FetchOptions =
{
OnTransferProgress = _ => { transferWasCalled = true; return true; },
OnProgress = progress => { progressWasCalled = true; return true; },
OnUpdateTips = (name, oldId, newId) => { updateTipsWasCalled = true; return true; }
},
OnCheckoutProgress = (a, b, c) => checkoutWasCalled = true

});

Assert.True(transferWasCalled);
Expand All @@ -174,7 +178,7 @@ public void CanCloneWithCredentials()
string clonedRepoPath = Repository.Clone(Constants.PrivateRepoUrl, scd.DirectoryPath,
new CloneOptions()
{
CredentialsProvider = Constants.PrivateRepoCredentials
FetchOptions = { CredentialsProvider = Constants.PrivateRepoCredentials }
});


Expand Down Expand Up @@ -249,43 +253,46 @@ public void CanInspectCertificateOnClone(string url, string hostname, Type certT

var options = new CloneOptions
{
CertificateCheck = (cert, valid, host) =>
FetchOptions =
{
wasCalled = true;

Assert.Equal(hostname, host);
Assert.Equal(certType, cert.GetType());

if (certType == typeof(CertificateX509))
CertificateCheck = (cert, valid, host) =>
{
Assert.True(valid);
var x509 = ((CertificateX509)cert).Certificate;
// we get a string with the different fields instead of a structure, so...
Assert.Contains("CN=github.com,", x509.Subject);
checksHappy = true;
return false;
}
wasCalled = true;

Assert.Equal(hostname, host);
Assert.Equal(certType, cert.GetType());

if (certType == typeof(CertificateX509))
{
Assert.True(valid);
var x509 = ((CertificateX509)cert).Certificate;
// we get a string with the different fields instead of a structure, so...
Assert.Contains("CN=github.com,", x509.Subject);
checksHappy = true;
return false;
}

if (certType == typeof(CertificateSsh))
{
var hostkey = (CertificateSsh)cert;
Assert.True(hostkey.HasMD5);
/*
* Once you've connected and thus your ssh has stored the hostkey,
* you can get the hostkey for a host with
*
* ssh-keygen -F github.com -l | tail -n 1 | cut -d ' ' -f 2 | tr -d ':'
*
* though GitHub's hostkey won't change anytime soon.
*/
Assert.Equal("1627aca576282d36631b564debdfa648",
BitConverter.ToString(hostkey.HashMD5).ToLower().Replace("-", ""));
checksHappy = true;
return false;
}

if (certType == typeof(CertificateSsh))
{
var hostkey = (CertificateSsh)cert;
Assert.True(hostkey.HasMD5);
/*
* Once you've connected and thus your ssh has stored the hostkey,
* you can get the hostkey for a host with
*
* ssh-keygen -F github.com -l | tail -n 1 | cut -d ' ' -f 2 | tr -d ':'
*
* though GitHub's hostkey won't change anytime soon.
*/
Assert.Equal("1627aca576282d36631b564debdfa648",
BitConverter.ToString(hostkey.HashMD5).ToLower().Replace("-", ""));
checksHappy = true;
return false;
}

return false;
},
}
};

Assert.Throws<UserCancelledException>(() =>
Expand Down Expand Up @@ -432,9 +439,12 @@ public void CanRecursivelyCloneSubmodules()
{
RecurseSubmodules = true,
OnCheckoutProgress = checkoutProgressHandler,
OnUpdateTips = remoteRefUpdated,
RepositoryOperationStarting = repositoryOperationStarting,
RepositoryOperationCompleted = repositoryOperationCompleted,
FetchOptions =
{
OnUpdateTips = remoteRefUpdated,
RepositoryOperationStarting = repositoryOperationStarting,
RepositoryOperationCompleted = repositoryOperationCompleted
}
};

string clonedRepoPath = Repository.Clone(uri.AbsolutePath, scd.DirectoryPath, options);
Expand Down Expand Up @@ -517,7 +527,7 @@ public void CanCancelRecursiveClone()
CloneOptions options = new CloneOptions()
{
RecurseSubmodules = true,
RepositoryOperationStarting = repositoryOperationStarting,
FetchOptions = { RepositoryOperationStarting = repositoryOperationStarting }
};

Assert.Throws<UserCancelledException>(() =>
Expand Down Expand Up @@ -557,10 +567,8 @@ public void CannotCloneWithForbiddenCustomHeaders()
const string url = "https://github.com/libgit2/TestGitRepository";

const string knownHeader = "User-Agent: mygit-201";
var cloneOptions = new CloneOptions()
{
FetchOptions = new FetchOptions { CustomHeaders = new String[] { knownHeader } }
};
var cloneOptions = new CloneOptions();
cloneOptions.FetchOptions.CustomHeaders = new string[] { knownHeader };

Assert.Throws<LibGit2SharpException>(() => Repository.Clone(url, scd.DirectoryPath, cloneOptions));
}
Expand All @@ -573,10 +581,8 @@ public void CannotCloneWithMalformedCustomHeaders()
const string url = "https://github.com/libgit2/TestGitRepository";

const string knownHeader = "hello world";
var cloneOptions = new CloneOptions()
{
FetchOptions = new FetchOptions { CustomHeaders = new String[] { knownHeader } }
};
var cloneOptions = new CloneOptions();
cloneOptions.FetchOptions.CustomHeaders = new string[] { knownHeader };

Assert.Throws<LibGit2SharpException>(() => Repository.Clone(url, scd.DirectoryPath, cloneOptions));
}
Expand All @@ -589,10 +595,8 @@ public void CanCloneWithCustomHeaders()
const string url = "https://github.com/libgit2/TestGitRepository";

const string knownHeader = "X-Hello: world";
var cloneOptions = new CloneOptions()
{
FetchOptions = new FetchOptions { CustomHeaders = new String[] { knownHeader } }
};
var cloneOptions = new CloneOptions();
cloneOptions.FetchOptions.CustomHeaders = new string[] { knownHeader };

var clonedRepoPath = Repository.Clone(url, scd.DirectoryPath, cloneOptions);
Assert.True(Directory.Exists(clonedRepoPath));
Expand Down
4 changes: 2 additions & 2 deletions LibGit2Sharp.Tests/SubmoduleFixture.cs
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,6 @@
using System.Linq;
using LibGit2Sharp.Tests.TestHelpers;
using Xunit;
using Xunit.Extensions;

namespace LibGit2Sharp.Tests
{
Expand Down Expand Up @@ -240,9 +239,10 @@ public void CanUpdateSubmodule()
OnCheckoutProgress = (x, y, z) => checkoutProgressCalled = true,
OnCheckoutNotify = (x, y) => { checkoutNotifyCalled = true; return true; },
CheckoutNotifyFlags = CheckoutNotifyFlags.Updated,
OnUpdateTips = (x, y, z) => { updateTipsCalled = true; return true; },
};

options.FetchOptions.OnUpdateTips = (x, y, z) => { updateTipsCalled = true; return true; };

repo.Submodules.Init(submodule.Name, false);
repo.Submodules.Update(submodule.Name, options);

Expand Down
4 changes: 2 additions & 2 deletions LibGit2Sharp/CloneOptions.cs
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ namespace LibGit2Sharp
/// <summary>
/// Options to define clone behaviour
/// </summary>
public sealed class CloneOptions : FetchOptionsBase, IConvertableToGitCheckoutOpts
public sealed class CloneOptions : IConvertableToGitCheckoutOpts
{
/// <summary>
/// Creates default <see cref="CloneOptions"/> for a non-bare clone
Expand Down Expand Up @@ -46,7 +46,7 @@ public CloneOptions()
/// <summary>
/// Gets or sets the fetch options.
/// </summary>
public FetchOptions FetchOptions { get; set; }
public FetchOptions FetchOptions { get; } = new();

#region IConvertableToGitCheckoutOpts

Expand Down
3 changes: 1 addition & 2 deletions LibGit2Sharp/Commands/Fetch.cs
Original file line number Diff line number Diff line change
@@ -1,5 +1,4 @@
using System.Collections.Generic;
using LibGit2Sharp;
using LibGit2Sharp.Core;
using LibGit2Sharp.Core.Handles;

Expand Down Expand Up @@ -75,7 +74,7 @@ public static void Fetch(Repository repository, string remote, IEnumerable<strin
fetchOptions.CustomHeaders = GitStrArrayManaged.BuildFrom(options.CustomHeaders);
}

fetchOptions.ProxyOptions = new GitProxyOptions { Version = 1 };
fetchOptions.ProxyOptions = options.ProxyOptions.CreateGitProxyOptions();

Proxy.git_remote_fetch(remoteHandle, refspecs, fetchOptions, logMessage);
}
Expand Down
9 changes: 5 additions & 4 deletions LibGit2Sharp/Core/GitFetchOptionsWrapper.cs
Original file line number Diff line number Diff line change
Expand Up @@ -2,16 +2,16 @@

namespace LibGit2Sharp.Core
{
/// <summary>
/// Git fetch options wrapper. Disposable wrapper for GitFetchOptions
/// <summary>
/// Git fetch options wrapper. Disposable wrapper for GitFetchOptions
/// </summary>
internal class GitFetchOptionsWrapper : IDisposable
{
public GitFetchOptionsWrapper() : this(new GitFetchOptions()) { }

public GitFetchOptionsWrapper(GitFetchOptions fetchOptions)
{
this.Options = fetchOptions;
Options = fetchOptions;
}

public GitFetchOptions Options { get; private set; }
Expand All @@ -23,7 +23,8 @@ protected virtual void Dispose(bool disposing)
if (disposedValue)
return;

this.Options.CustomHeaders.Dispose();
Options.CustomHeaders.Dispose();
EncodingMarshaler.Cleanup(Options.ProxyOptions.Url);
disposedValue = true;
}

Expand Down
6 changes: 3 additions & 3 deletions LibGit2Sharp/Core/GitProxyOptions.cs
Original file line number Diff line number Diff line change
Expand Up @@ -16,8 +16,8 @@ internal struct GitProxyOptions
public uint Version;
public GitProxyType Type;
public IntPtr Url;
public IntPtr CredentialsCb;
public IntPtr CertificateCheck;
public IntPtr CbPayload;
public NativeMethods.git_cred_acquire_cb Credentials;
public NativeMethods.git_transport_certificate_check_cb CertificateCheck;
public IntPtr Payload;
}
}
32 changes: 32 additions & 0 deletions LibGit2Sharp/Core/GitProxyOptionsWrapper.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
using System;

namespace LibGit2Sharp.Core
{
internal class GitProxyOptionsWrapper : IDisposable
{
public GitProxyOptionsWrapper() : this(new GitProxyOptions()) { }

public GitProxyOptionsWrapper(GitProxyOptions fetchOptions)
{
Options = fetchOptions;
}

public GitProxyOptions Options { get; private set; }

private bool disposedValue = false;

protected virtual void Dispose(bool disposing)
{
if (disposedValue)
return;

EncodingMarshaler.Cleanup(Options.Url);
disposedValue = true;
}

public void Dispose()
{
Dispose(true);
}
}
}
1 change: 1 addition & 0 deletions LibGit2Sharp/Core/GitPushOptionsWrapper.cs
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@ protected virtual void Dispose(bool disposing)
return;

this.Options.CustomHeaders.Dispose();
EncodingMarshaler.Cleanup(Options.ProxyOptions.Url);
disposedValue = true;
}

Expand Down
2 changes: 0 additions & 2 deletions LibGit2Sharp/Core/GitSubmoduleOptions.cs
Original file line number Diff line number Diff line change
Expand Up @@ -11,8 +11,6 @@ internal struct GitSubmoduleUpdateOptions

public GitFetchOptions FetchOptions;

public CheckoutStrategy CloneCheckoutStrategy;

public int AllowFetch;
}
}
8 changes: 4 additions & 4 deletions LibGit2Sharp/FetchOptions.cs
Original file line number Diff line number Diff line change
Expand Up @@ -28,14 +28,14 @@ public sealed class FetchOptions : FetchOptionsBase

/// <summary>
/// Get/Set the custom headers.
///
/// <para>
/// This allows you to set custom headers (e.g. X-Forwarded-For,
///
/// <para>
/// This allows you to set custom headers (e.g. X-Forwarded-For,
/// X-Request-Id, etc),
/// </para>
/// </summary>
/// <remarks>
/// Libgit2 sets some headers for HTTP requests (User-Agent, Host,
/// Libgit2 sets some headers for HTTP requests (User-Agent, Host,
/// Accept, Content-Type, Transfer-Encoding, Content-Length, Accept) that
/// cannot be overriden.
/// </remarks>
Expand Down
7 changes: 6 additions & 1 deletion LibGit2Sharp/FetchOptionsBase.cs
Original file line number Diff line number Diff line change
Expand Up @@ -35,7 +35,7 @@ internal FetchOptionsBase()

/// <summary>
/// This handler will be called to let the user make a decision on whether to allow
/// the connection to preoceed based on the certificate presented by the server.
/// the connection to proceed based on the certificate presented by the server.
/// </summary>
public CertificateCheckHandler CertificateCheck { get; set; }

Expand All @@ -48,5 +48,10 @@ internal FetchOptionsBase()
/// Completed operating on the current repository.
/// </summary>
public RepositoryOperationCompleted RepositoryOperationCompleted { get; set; }

/// <summary>
/// Options for connecting through a proxy.
/// </summary>
public ProxyOptions ProxyOptions { get; } = new();
}
}
1 change: 1 addition & 0 deletions LibGit2Sharp/LibGit2Sharp.csproj
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@

<PropertyGroup>
<TargetFrameworks>net472;net6.0</TargetFrameworks>
<LangVersion>10.0</LangVersion>
<GenerateDocumentationFile>true</GenerateDocumentationFile>
<Description>LibGit2Sharp brings all the might and speed of libgit2, a native Git implementation, to the managed world of .NET</Description>
<Company>LibGit2Sharp contributors</Company>
Expand Down