@@ -89,6 +89,78 @@ public virtual IEnumerable<DirectReference> ListReferences(Remote remote)
89
89
return directReferences ;
90
90
}
91
91
92
+ /// <summary>
93
+ /// Fetch from the <see cref = "Remote" />.
94
+ /// </summary>
95
+ /// <param name="remote">The remote to fetch</param>
96
+ /// <param name="tagFetchMode">Optional parameter indicating what tags to download.</param>
97
+ /// <param name="onProgress">Progress callback. Corresponds to libgit2 progress callback.</param>
98
+ /// <param name="onCompletion">Completion callback. Corresponds to libgit2 completion callback.</param>
99
+ /// <param name="onUpdateTips">UpdateTips callback. Corresponds to libgit2 update_tips callback.</param>
100
+ /// <param name="onTransferProgress">Callback method that transfer progress will be reported through.
101
+ /// Reports the client's state regarding the received and processed (bytes, objects) from the server.</param>
102
+ /// <param name="credentials">Credentials to use for username/password authentication.</param>
103
+ public virtual void Fetch (
104
+ Remote remote ,
105
+ TagFetchMode tagFetchMode = TagFetchMode . Auto ,
106
+ ProgressHandler onProgress = null ,
107
+ CompletionHandler onCompletion = null ,
108
+ UpdateTipsHandler onUpdateTips = null ,
109
+ TransferProgressHandler onTransferProgress = null ,
110
+ Credentials credentials = null )
111
+ {
112
+ Ensure . ArgumentNotNull ( remote , "remote" ) ;
113
+
114
+ // We need to keep a reference to the git_cred_acquire_cb callback around
115
+ // so it will not be garbage collected before we are done with it.
116
+ // Note that we also have a GC.KeepAlive call at the end of the method.
117
+ NativeMethods . git_cred_acquire_cb credentialCallback = null ;
118
+
119
+ using ( RemoteSafeHandle remoteHandle = Proxy . git_remote_load ( repository . Handle , remote . Name , true ) )
120
+ {
121
+ var callbacks = new RemoteCallbacks ( onProgress , onCompletion , onUpdateTips ) ;
122
+ GitRemoteCallbacks gitCallbacks = callbacks . GenerateCallbacks ( ) ;
123
+
124
+ Proxy . git_remote_set_autotag ( remoteHandle , tagFetchMode ) ;
125
+
126
+ if ( credentials != null )
127
+ {
128
+ credentialCallback = ( out IntPtr cred , IntPtr url , IntPtr username_from_url , uint types , IntPtr payload ) =>
129
+ NativeMethods. git_cred_userpass_plaintext_new ( out cred , credentials . Username , credentials . Password ) ;
130
+
131
+ Proxy . git_remote_set_cred_acquire_cb (
132
+ remoteHandle ,
133
+ credentialCallback ,
134
+ IntPtr . Zero ) ;
135
+ }
136
+
137
+ // It is OK to pass the reference to the GitCallbacks directly here because libgit2 makes a copy of
138
+ // the data in the git_remote_callbacks structure. If, in the future, libgit2 changes its implementation
139
+ // to store a reference to the git_remote_callbacks structure this would introduce a subtle bug
140
+ // where the managed layer could move the git_remote_callbacks to a different location in memory,
141
+ // but libgit2 would still reference the old address.
142
+ //
143
+ // Also, if GitRemoteCallbacks were a class instead of a struct, we would need to guard against
144
+ // GC occuring in between setting the remote callbacks and actual usage in one of the functions afterwords.
145
+ Proxy . git_remote_set_callbacks ( remoteHandle , ref gitCallbacks ) ;
146
+
147
+ try
148
+ {
149
+ Proxy . git_remote_connect ( remoteHandle , GitDirection . Fetch ) ;
150
+ Proxy . git_remote_download ( remoteHandle , onTransferProgress ) ;
151
+ Proxy . git_remote_update_tips ( remoteHandle ) ;
152
+ }
153
+ finally
154
+ {
155
+ Proxy . git_remote_disconnect ( remoteHandle ) ;
156
+ }
157
+ }
158
+
159
+ // To be safe, make sure the credential callback is kept until
160
+ // alive until at least this point.
161
+ GC . KeepAlive ( credentialCallback ) ;
162
+ }
163
+
92
164
/// <summary>
93
165
/// Push the objectish to the destination reference on the <see cref = "Remote" />.
94
166
/// </summary>
@@ -205,7 +277,7 @@ public virtual void Push(
205
277
}
206
278
}
207
279
208
- // To be safe, make sure the credential callback is kept until
280
+ // To be safe, make sure the credential callback is kept
209
281
// alive until at least this point.
210
282
GC . KeepAlive ( credentialCallback ) ;
211
283
}
0 commit comments