@@ -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 }
0 commit comments