Skip to content

Commit 0d46470

Browse files
committed
Managed HTTP transport: allow custom transport
Continue to allow a custom subtransport to override our own.
1 parent df8a9ba commit 0d46470

File tree

5 files changed

+150
-15
lines changed

5 files changed

+150
-15
lines changed

LibGit2Sharp/Core/NativeMethods.cs

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -85,8 +85,8 @@ private static void InitializeNativeLibrary()
8585
// Configure the .NET HTTP(S) mechanism on the first initialization of the library in the current process.
8686
if (initCounter == 1)
8787
{
88-
httpSubtransportRegistration = GlobalSettings.RegisterSmartSubtransport<ManagedHttpSmartSubtransport>("http");
89-
httpsSubtransportRegistration = GlobalSettings.RegisterSmartSubtransport<ManagedHttpSmartSubtransport>("https");
88+
httpSubtransportRegistration = GlobalSettings.RegisterDefaultSmartSubtransport<ManagedHttpSmartSubtransport>("http");
89+
httpsSubtransportRegistration = GlobalSettings.RegisterDefaultSmartSubtransport<ManagedHttpSmartSubtransport>("https");
9090
}
9191
}
9292

@@ -97,12 +97,12 @@ private sealed class NativeShutdownObject : CriticalFinalizerObject
9797
{
9898
if (httpSubtransportRegistration != null)
9999
{
100-
GlobalSettings.UnregisterSmartSubtransport(httpSubtransportRegistration);
100+
GlobalSettings.UnregisterDefaultSmartSubtransport(httpSubtransportRegistration);
101101
}
102102

103103
if (httpsSubtransportRegistration != null)
104104
{
105-
GlobalSettings.UnregisterSmartSubtransport(httpsSubtransportRegistration);
105+
GlobalSettings.UnregisterDefaultSmartSubtransport(httpsSubtransportRegistration);
106106
}
107107

108108
git_libgit2_shutdown();

LibGit2Sharp/GlobalSettings.cs

Lines changed: 123 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,14 @@ public static class GlobalSettings
2222
private static bool nativeLibraryPathLocked;
2323
private static string nativeLibraryDefaultPath;
2424

25+
internal class SmartSubtransportData
26+
{
27+
internal bool isCustom;
28+
internal SmartSubtransportRegistrationData defaultSubtransport;
29+
}
30+
31+
private static readonly Dictionary<string, SmartSubtransportData> smartSubtransportData = new Dictionary<string, SmartSubtransportData>();
32+
2533
static GlobalSettings()
2634
{
2735
bool netFX = Platform.IsRunningOnNetFramework();
@@ -79,6 +87,42 @@ public static Version Version
7987
}
8088
}
8189

90+
private static SmartSubtransportData GetOrCreateSmartSubtransportData(string scheme)
91+
{
92+
Ensure.ArgumentNotNull(scheme, "scheme");
93+
94+
lock (smartSubtransportData)
95+
{
96+
if (!smartSubtransportData.ContainsKey(scheme))
97+
{
98+
smartSubtransportData[scheme] = new SmartSubtransportData();
99+
}
100+
101+
return smartSubtransportData[scheme];
102+
}
103+
}
104+
105+
internal static SmartSubtransportRegistration<T> RegisterDefaultSmartSubtransport<T>(string scheme)
106+
where T : SmartSubtransport, new()
107+
{
108+
Ensure.ArgumentNotNull(scheme, "scheme");
109+
110+
lock (smartSubtransportData)
111+
{
112+
var data = GetOrCreateSmartSubtransportData(scheme);
113+
114+
if (data.defaultSubtransport != null)
115+
{
116+
throw new Exception(string.Format("A default subtransport is already configured for {0}", scheme));
117+
}
118+
119+
var registration = RegisterSmartSubtransportInternal<T>(scheme);
120+
121+
data.defaultSubtransport = registration;
122+
return registration;
123+
}
124+
}
125+
82126
/// <summary>
83127
/// Registers a new <see cref="SmartSubtransport"/> as a custom
84128
/// smart-protocol transport with libgit2. Any Git remote with
@@ -96,8 +140,34 @@ public static Version Version
96140
public static SmartSubtransportRegistration<T> RegisterSmartSubtransport<T>(string scheme)
97141
where T : SmartSubtransport, new()
98142
{
143+
SmartSubtransportRegistration<T> registration;
144+
99145
Ensure.ArgumentNotNull(scheme, "scheme");
100146

147+
lock (smartSubtransportData)
148+
{
149+
var data = GetOrCreateSmartSubtransportData(scheme);
150+
151+
if (data.isCustom)
152+
{
153+
throw new EntryExistsException(string.Format("A smart subtransport is already registered for {0}", scheme));
154+
}
155+
156+
if (data.defaultSubtransport != null)
157+
{
158+
Proxy.git_transport_unregister(scheme);
159+
}
160+
161+
registration = RegisterSmartSubtransportInternal<T>(scheme);
162+
data.isCustom = true;
163+
}
164+
165+
return registration;
166+
}
167+
168+
private static SmartSubtransportRegistration<T> RegisterSmartSubtransportInternal<T>(string scheme)
169+
where T : SmartSubtransport, new()
170+
{
101171
var registration = new SmartSubtransportRegistration<T>(scheme);
102172

103173
try
@@ -126,6 +196,59 @@ public static void UnregisterSmartSubtransport<T>(SmartSubtransportRegistration<
126196
{
127197
Ensure.ArgumentNotNull(registration, "registration");
128198

199+
var scheme = registration.Scheme;
200+
201+
lock (smartSubtransportData)
202+
{
203+
var data = GetOrCreateSmartSubtransportData(scheme);
204+
205+
if (!data.isCustom)
206+
{
207+
throw new NotFoundException(string.Format("No smart subtransport has been registered for {0}", scheme));
208+
}
209+
210+
UnregisterSmartSubtransportInternal(registration);
211+
212+
data.isCustom = false;
213+
214+
if (data.defaultSubtransport != null)
215+
{
216+
var defaultRegistration = data.defaultSubtransport;
217+
218+
Proxy.git_transport_register(defaultRegistration.Scheme,
219+
defaultRegistration.FunctionPointer,
220+
defaultRegistration.RegistrationPointer);
221+
}
222+
}
223+
}
224+
225+
internal static void UnregisterDefaultSmartSubtransport<T>(SmartSubtransportRegistration<T> registration)
226+
where T : SmartSubtransport, new()
227+
{
228+
Ensure.ArgumentNotNull(registration, "registration");
229+
230+
var scheme = registration.Scheme;
231+
232+
lock (smartSubtransportData)
233+
{
234+
if (!smartSubtransportData.ContainsKey(scheme))
235+
{
236+
throw new Exception(string.Format("No default smart subtransport has been registered for {0}", scheme));
237+
}
238+
239+
if (registration != smartSubtransportData[scheme].defaultSubtransport)
240+
{
241+
throw new Exception(string.Format("The given smart subtransport is not the default for {0}", scheme));
242+
}
243+
244+
smartSubtransportData.Remove(scheme);
245+
UnregisterSmartSubtransportInternal(registration);
246+
}
247+
}
248+
249+
private static void UnregisterSmartSubtransportInternal<T>(SmartSubtransportRegistration<T> registration)
250+
where T : SmartSubtransport, new()
251+
{
129252
Proxy.git_transport_unregister(registration.Scheme);
130253
registration.Free();
131254
}

LibGit2Sharp/SmartSubtransport.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -110,7 +110,7 @@ public int AcquireCredentials(out Credentials cred, string user, params Type[] m
110110

111111
if (credHandle == IntPtr.Zero)
112112
{
113-
throw new InvalidOperationException("creditals callback indicated success but returned no credentials");
113+
throw new InvalidOperationException("credentials callback indicated success but returned no credentials");
114114
}
115115

116116
unsafe

LibGit2Sharp/SmartSubtransportRegistration.cs

Lines changed: 1 addition & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,7 @@ namespace LibGit2Sharp
1111
/// under a particular scheme (eg "http").
1212
/// </summary>
1313
/// <typeparam name="T">The type of SmartSubtransport to register</typeparam>
14-
public sealed class SmartSubtransportRegistration<T>
14+
public sealed class SmartSubtransportRegistration<T> : SmartSubtransportRegistrationData
1515
where T : SmartSubtransport, new()
1616
{
1717
/// <summary>
@@ -26,15 +26,6 @@ internal SmartSubtransportRegistration(string scheme)
2626
FunctionPointer = CreateFunctionPointer();
2727
}
2828

29-
/// <summary>
30-
/// The URI scheme (eg "http") for this transport.
31-
/// </summary>
32-
public string Scheme { get; private set; }
33-
34-
internal IntPtr RegistrationPointer { get; private set; }
35-
36-
internal IntPtr FunctionPointer { get; private set; }
37-
3829
private IntPtr CreateRegistrationPointer()
3930
{
4031
var registration = new GitSmartSubtransportRegistration();
Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
using System;
2+
using System.Collections.Generic;
3+
using System.Text;
4+
5+
namespace LibGit2Sharp
6+
{
7+
/// <summary>
8+
/// Information about a smart subtransport registration.
9+
/// </summary>
10+
public abstract class SmartSubtransportRegistrationData
11+
{
12+
/// <summary>
13+
/// The URI scheme for this transport, for example "http" or "ssh".
14+
/// </summary>
15+
public string Scheme { get; internal set; }
16+
17+
internal IntPtr RegistrationPointer { get; set; }
18+
19+
internal IntPtr FunctionPointer { get; set; }
20+
}
21+
}

0 commit comments

Comments
 (0)