Skip to content

Commit cd24df2

Browse files
authored
Merge pull request #2065 from libgit2/proxy-options
Add proxy options
2 parents 1cc55f0 + 01a6ccb commit cd24df2

19 files changed

+444
-142
lines changed

LibGit2Sharp.Tests/CloneFixture.cs

+56-52
Original file line numberDiff line numberDiff line change
@@ -151,10 +151,14 @@ public void CallsProgressCallbacks(string url)
151151

152152
Repository.Clone(url, scd.DirectoryPath, new CloneOptions()
153153
{
154-
OnTransferProgress = _ => { transferWasCalled = true; return true; },
155-
OnProgress = progress => { progressWasCalled = true; return true; },
156-
OnUpdateTips = (name, oldId, newId) => { updateTipsWasCalled = true; return true; },
154+
FetchOptions =
155+
{
156+
OnTransferProgress = _ => { transferWasCalled = true; return true; },
157+
OnProgress = progress => { progressWasCalled = true; return true; },
158+
OnUpdateTips = (name, oldId, newId) => { updateTipsWasCalled = true; return true; }
159+
},
157160
OnCheckoutProgress = (a, b, c) => checkoutWasCalled = true
161+
158162
});
159163

160164
Assert.True(transferWasCalled);
@@ -174,7 +178,7 @@ public void CanCloneWithCredentials()
174178
string clonedRepoPath = Repository.Clone(Constants.PrivateRepoUrl, scd.DirectoryPath,
175179
new CloneOptions()
176180
{
177-
CredentialsProvider = Constants.PrivateRepoCredentials
181+
FetchOptions = { CredentialsProvider = Constants.PrivateRepoCredentials }
178182
});
179183

180184

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

250254
var options = new CloneOptions
251255
{
252-
CertificateCheck = (cert, valid, host) =>
256+
FetchOptions =
253257
{
254-
wasCalled = true;
255-
256-
Assert.Equal(hostname, host);
257-
Assert.Equal(certType, cert.GetType());
258-
259-
if (certType == typeof(CertificateX509))
258+
CertificateCheck = (cert, valid, host) =>
260259
{
261-
Assert.True(valid);
262-
var x509 = ((CertificateX509)cert).Certificate;
263-
// we get a string with the different fields instead of a structure, so...
264-
Assert.Contains("CN=github.com,", x509.Subject);
265-
checksHappy = true;
266-
return false;
267-
}
260+
wasCalled = true;
261+
262+
Assert.Equal(hostname, host);
263+
Assert.Equal(certType, cert.GetType());
264+
265+
if (certType == typeof(CertificateX509))
266+
{
267+
Assert.True(valid);
268+
var x509 = ((CertificateX509)cert).Certificate;
269+
// we get a string with the different fields instead of a structure, so...
270+
Assert.Contains("CN=github.com,", x509.Subject);
271+
checksHappy = true;
272+
return false;
273+
}
274+
275+
if (certType == typeof(CertificateSsh))
276+
{
277+
var hostkey = (CertificateSsh)cert;
278+
Assert.True(hostkey.HasMD5);
279+
/*
280+
* Once you've connected and thus your ssh has stored the hostkey,
281+
* you can get the hostkey for a host with
282+
*
283+
* ssh-keygen -F github.com -l | tail -n 1 | cut -d ' ' -f 2 | tr -d ':'
284+
*
285+
* though GitHub's hostkey won't change anytime soon.
286+
*/
287+
Assert.Equal("1627aca576282d36631b564debdfa648",
288+
BitConverter.ToString(hostkey.HashMD5).ToLower().Replace("-", ""));
289+
checksHappy = true;
290+
return false;
291+
}
268292

269-
if (certType == typeof(CertificateSsh))
270-
{
271-
var hostkey = (CertificateSsh)cert;
272-
Assert.True(hostkey.HasMD5);
273-
/*
274-
* Once you've connected and thus your ssh has stored the hostkey,
275-
* you can get the hostkey for a host with
276-
*
277-
* ssh-keygen -F github.com -l | tail -n 1 | cut -d ' ' -f 2 | tr -d ':'
278-
*
279-
* though GitHub's hostkey won't change anytime soon.
280-
*/
281-
Assert.Equal("1627aca576282d36631b564debdfa648",
282-
BitConverter.ToString(hostkey.HashMD5).ToLower().Replace("-", ""));
283-
checksHappy = true;
284293
return false;
285294
}
286-
287-
return false;
288-
},
295+
}
289296
};
290297

291298
Assert.Throws<UserCancelledException>(() =>
@@ -432,9 +439,12 @@ public void CanRecursivelyCloneSubmodules()
432439
{
433440
RecurseSubmodules = true,
434441
OnCheckoutProgress = checkoutProgressHandler,
435-
OnUpdateTips = remoteRefUpdated,
436-
RepositoryOperationStarting = repositoryOperationStarting,
437-
RepositoryOperationCompleted = repositoryOperationCompleted,
442+
FetchOptions =
443+
{
444+
OnUpdateTips = remoteRefUpdated,
445+
RepositoryOperationStarting = repositoryOperationStarting,
446+
RepositoryOperationCompleted = repositoryOperationCompleted
447+
}
438448
};
439449

440450
string clonedRepoPath = Repository.Clone(uri.AbsolutePath, scd.DirectoryPath, options);
@@ -517,7 +527,7 @@ public void CanCancelRecursiveClone()
517527
CloneOptions options = new CloneOptions()
518528
{
519529
RecurseSubmodules = true,
520-
RepositoryOperationStarting = repositoryOperationStarting,
530+
FetchOptions = { RepositoryOperationStarting = repositoryOperationStarting }
521531
};
522532

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

559569
const string knownHeader = "User-Agent: mygit-201";
560-
var cloneOptions = new CloneOptions()
561-
{
562-
FetchOptions = new FetchOptions { CustomHeaders = new String[] { knownHeader } }
563-
};
570+
var cloneOptions = new CloneOptions();
571+
cloneOptions.FetchOptions.CustomHeaders = new string[] { knownHeader };
564572

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

575583
const string knownHeader = "hello world";
576-
var cloneOptions = new CloneOptions()
577-
{
578-
FetchOptions = new FetchOptions { CustomHeaders = new String[] { knownHeader } }
579-
};
584+
var cloneOptions = new CloneOptions();
585+
cloneOptions.FetchOptions.CustomHeaders = new string[] { knownHeader };
580586

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

591597
const string knownHeader = "X-Hello: world";
592-
var cloneOptions = new CloneOptions()
593-
{
594-
FetchOptions = new FetchOptions { CustomHeaders = new String[] { knownHeader } }
595-
};
598+
var cloneOptions = new CloneOptions();
599+
cloneOptions.FetchOptions.CustomHeaders = new string[] { knownHeader };
596600

597601
var clonedRepoPath = Repository.Clone(url, scd.DirectoryPath, cloneOptions);
598602
Assert.True(Directory.Exists(clonedRepoPath));

LibGit2Sharp.Tests/SubmoduleFixture.cs

+2-2
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,6 @@
33
using System.Linq;
44
using LibGit2Sharp.Tests.TestHelpers;
55
using Xunit;
6-
using Xunit.Extensions;
76

87
namespace LibGit2Sharp.Tests
98
{
@@ -240,9 +239,10 @@ public void CanUpdateSubmodule()
240239
OnCheckoutProgress = (x, y, z) => checkoutProgressCalled = true,
241240
OnCheckoutNotify = (x, y) => { checkoutNotifyCalled = true; return true; },
242241
CheckoutNotifyFlags = CheckoutNotifyFlags.Updated,
243-
OnUpdateTips = (x, y, z) => { updateTipsCalled = true; return true; },
244242
};
245243

244+
options.FetchOptions.OnUpdateTips = (x, y, z) => { updateTipsCalled = true; return true; };
245+
246246
repo.Submodules.Init(submodule.Name, false);
247247
repo.Submodules.Update(submodule.Name, options);
248248

LibGit2Sharp/CloneOptions.cs

+2-2
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@ namespace LibGit2Sharp
66
/// <summary>
77
/// Options to define clone behaviour
88
/// </summary>
9-
public sealed class CloneOptions : FetchOptionsBase, IConvertableToGitCheckoutOpts
9+
public sealed class CloneOptions : IConvertableToGitCheckoutOpts
1010
{
1111
/// <summary>
1212
/// Creates default <see cref="CloneOptions"/> for a non-bare clone
@@ -46,7 +46,7 @@ public CloneOptions()
4646
/// <summary>
4747
/// Gets or sets the fetch options.
4848
/// </summary>
49-
public FetchOptions FetchOptions { get; set; }
49+
public FetchOptions FetchOptions { get; } = new();
5050

5151
#region IConvertableToGitCheckoutOpts
5252

LibGit2Sharp/Commands/Fetch.cs

+1-2
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,4 @@
11
using System.Collections.Generic;
2-
using LibGit2Sharp;
32
using LibGit2Sharp.Core;
43
using LibGit2Sharp.Core.Handles;
54

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

78-
fetchOptions.ProxyOptions = new GitProxyOptions { Version = 1 };
77+
fetchOptions.ProxyOptions = options.ProxyOptions.CreateGitProxyOptions();
7978

8079
Proxy.git_remote_fetch(remoteHandle, refspecs, fetchOptions, logMessage);
8180
}

LibGit2Sharp/Core/GitFetchOptionsWrapper.cs

+5-4
Original file line numberDiff line numberDiff line change
@@ -2,16 +2,16 @@
22

33
namespace LibGit2Sharp.Core
44
{
5-
/// <summary>
6-
/// Git fetch options wrapper. Disposable wrapper for GitFetchOptions
5+
/// <summary>
6+
/// Git fetch options wrapper. Disposable wrapper for GitFetchOptions
77
/// </summary>
88
internal class GitFetchOptionsWrapper : IDisposable
99
{
1010
public GitFetchOptionsWrapper() : this(new GitFetchOptions()) { }
1111

1212
public GitFetchOptionsWrapper(GitFetchOptions fetchOptions)
1313
{
14-
this.Options = fetchOptions;
14+
Options = fetchOptions;
1515
}
1616

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

26-
this.Options.CustomHeaders.Dispose();
26+
Options.CustomHeaders.Dispose();
27+
EncodingMarshaler.Cleanup(Options.ProxyOptions.Url);
2728
disposedValue = true;
2829
}
2930

LibGit2Sharp/Core/GitProxyOptions.cs

+3-3
Original file line numberDiff line numberDiff line change
@@ -16,8 +16,8 @@ internal struct GitProxyOptions
1616
public uint Version;
1717
public GitProxyType Type;
1818
public IntPtr Url;
19-
public IntPtr CredentialsCb;
20-
public IntPtr CertificateCheck;
21-
public IntPtr CbPayload;
19+
public NativeMethods.git_cred_acquire_cb Credentials;
20+
public NativeMethods.git_transport_certificate_check_cb CertificateCheck;
21+
public IntPtr Payload;
2222
}
2323
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,32 @@
1+
using System;
2+
3+
namespace LibGit2Sharp.Core
4+
{
5+
internal class GitProxyOptionsWrapper : IDisposable
6+
{
7+
public GitProxyOptionsWrapper() : this(new GitProxyOptions()) { }
8+
9+
public GitProxyOptionsWrapper(GitProxyOptions fetchOptions)
10+
{
11+
Options = fetchOptions;
12+
}
13+
14+
public GitProxyOptions Options { get; private set; }
15+
16+
private bool disposedValue = false;
17+
18+
protected virtual void Dispose(bool disposing)
19+
{
20+
if (disposedValue)
21+
return;
22+
23+
EncodingMarshaler.Cleanup(Options.Url);
24+
disposedValue = true;
25+
}
26+
27+
public void Dispose()
28+
{
29+
Dispose(true);
30+
}
31+
}
32+
}

LibGit2Sharp/Core/GitPushOptionsWrapper.cs

+1
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,7 @@ protected virtual void Dispose(bool disposing)
2424
return;
2525

2626
this.Options.CustomHeaders.Dispose();
27+
EncodingMarshaler.Cleanup(Options.ProxyOptions.Url);
2728
disposedValue = true;
2829
}
2930

LibGit2Sharp/Core/GitSubmoduleOptions.cs

-2
Original file line numberDiff line numberDiff line change
@@ -11,8 +11,6 @@ internal struct GitSubmoduleUpdateOptions
1111

1212
public GitFetchOptions FetchOptions;
1313

14-
public CheckoutStrategy CloneCheckoutStrategy;
15-
1614
public int AllowFetch;
1715
}
1816
}

LibGit2Sharp/FetchOptions.cs

+4-4
Original file line numberDiff line numberDiff line change
@@ -28,14 +28,14 @@ public sealed class FetchOptions : FetchOptionsBase
2828

2929
/// <summary>
3030
/// Get/Set the custom headers.
31-
///
32-
/// <para>
33-
/// This allows you to set custom headers (e.g. X-Forwarded-For,
31+
///
32+
/// <para>
33+
/// This allows you to set custom headers (e.g. X-Forwarded-For,
3434
/// X-Request-Id, etc),
3535
/// </para>
3636
/// </summary>
3737
/// <remarks>
38-
/// Libgit2 sets some headers for HTTP requests (User-Agent, Host,
38+
/// Libgit2 sets some headers for HTTP requests (User-Agent, Host,
3939
/// Accept, Content-Type, Transfer-Encoding, Content-Length, Accept) that
4040
/// cannot be overriden.
4141
/// </remarks>

LibGit2Sharp/FetchOptionsBase.cs

+6-1
Original file line numberDiff line numberDiff line change
@@ -35,7 +35,7 @@ internal FetchOptionsBase()
3535

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

@@ -48,5 +48,10 @@ internal FetchOptionsBase()
4848
/// Completed operating on the current repository.
4949
/// </summary>
5050
public RepositoryOperationCompleted RepositoryOperationCompleted { get; set; }
51+
52+
/// <summary>
53+
/// Options for connecting through a proxy.
54+
/// </summary>
55+
public ProxyOptions ProxyOptions { get; } = new();
5156
}
5257
}

LibGit2Sharp/LibGit2Sharp.csproj

+1
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@
22

33
<PropertyGroup>
44
<TargetFrameworks>net472;net6.0</TargetFrameworks>
5+
<LangVersion>10.0</LangVersion>
56
<GenerateDocumentationFile>true</GenerateDocumentationFile>
67
<Description>LibGit2Sharp brings all the might and speed of libgit2, a native Git implementation, to the managed world of .NET</Description>
78
<Company>LibGit2Sharp contributors</Company>

0 commit comments

Comments
 (0)