@@ -28,6 +28,7 @@ internal RemoteCallbacks(PushOptions pushOptions)
2828 PackBuilderProgress = pushOptions . OnPackBuilderProgress ;
2929 CredentialsProvider = pushOptions . CredentialsProvider ;
3030 PushStatusError = pushOptions . OnPushStatusError ;
31+ PrePushCallback = pushOptions . OnNegotiationCompletedBeforePush ;
3132 }
3233
3334 internal RemoteCallbacks ( FetchOptionsBase fetchOptions )
@@ -77,6 +78,11 @@ internal RemoteCallbacks(FetchOptionsBase fetchOptions)
7778 /// </summary>
7879 private readonly PackBuilderProgressHandler PackBuilderProgress ;
7980
81+ /// <summary>
82+ /// Called during remote push operation after negotiation, before upload
83+ /// </summary>
84+ private readonly PrePushHandler PrePushCallback ;
85+
8086 #endregion
8187
8288 /// <summary>
@@ -86,7 +92,7 @@ internal RemoteCallbacks(FetchOptionsBase fetchOptions)
8692
8793 internal GitRemoteCallbacks GenerateCallbacks ( )
8894 {
89- var callbacks = new GitRemoteCallbacks { version = 1 } ;
95+ var callbacks = new GitRemoteCallbacks { version = 1 } ;
9096
9197 if ( Progress != null )
9298 {
@@ -123,6 +129,11 @@ internal GitRemoteCallbacks GenerateCallbacks()
123129 callbacks . pack_progress = GitPackbuilderProgressHandler ;
124130 }
125131
132+ if ( PrePushCallback != null )
133+ {
134+ callbacks . push_negotiation = GitPushNegotiationHandler ;
135+ }
136+
126137 return callbacks ;
127138 }
128139
@@ -185,7 +196,7 @@ private int GitUpdateTipsHandler(IntPtr str, ref GitOid oldId, ref GitOid newId,
185196 /// <returns>0 on success; a negative value to abort the process.</returns>
186197 private int GitPushUpdateReference ( IntPtr str , IntPtr status , IntPtr data )
187198 {
188- PushStatusErrorHandler onPushError = PushStatusError ;
199+ PushStatusErrorHandler onPushError = PushStatusError ;
189200
190201 if ( onPushError != null )
191202 {
@@ -262,6 +273,49 @@ private int GitCredentialHandler(out IntPtr ptr, IntPtr cUrl, IntPtr usernameFro
262273 return cred . GitCredentialHandler ( out ptr ) ;
263274 }
264275
276+ private int GitPushNegotiationHandler ( IntPtr updates , UIntPtr len , IntPtr payload )
277+ {
278+ if ( updates == IntPtr . Zero )
279+ {
280+ return ( int ) GitErrorCode . Error ;
281+ }
282+
283+ bool result = false ;
284+ try
285+ {
286+
287+ int length = len . ConvertToInt ( ) ;
288+ PushUpdate [ ] pushUpdates = new PushUpdate [ length ] ;
289+
290+ unsafe
291+ {
292+ IntPtr * ptr = ( IntPtr * ) updates . ToPointer ( ) ;
293+
294+ for ( int i = 0 ; i < length ; i ++ )
295+ {
296+ if ( ptr [ i ] == IntPtr . Zero )
297+ {
298+ throw new NullReferenceException ( "Unexpected null git_push_update pointer was encountered" ) ;
299+ }
300+
301+ GitPushUpdate gitPushUpdate = ptr [ i ] . MarshalAs < GitPushUpdate > ( ) ;
302+ PushUpdate pushUpdate = new PushUpdate ( gitPushUpdate ) ;
303+ pushUpdates [ i ] = pushUpdate ;
304+ }
305+
306+ result = PrePushCallback ( pushUpdates ) ;
307+ }
308+ }
309+ catch ( Exception exception )
310+ {
311+ Log . Write ( LogLevel . Error , exception . ToString ( ) ) ;
312+ Proxy . giterr_set_str ( GitErrorCategory . Callback , exception ) ;
313+ result = false ;
314+ }
315+
316+ return Proxy . ConvertResultToCancelFlag ( result ) ;
317+ }
318+
265319 #endregion
266320 }
267321}
0 commit comments