@@ -74,6 +74,57 @@ public virtual IEnumerable<DirectReference> ListReferences(Remote remote)
7474 }
7575 }
7676
77+ /// <summary>
78+ /// List references in a remote repository.
79+ /// <para>
80+ /// When the remote tips are ahead of the local ones, the retrieved
81+ /// <see cref="DirectReference"/>s may point to non existing
82+ /// <see cref="GitObject"/>s in the local repository. In that
83+ /// case, <see cref="DirectReference.Target"/> will return <c>null</c>.
84+ /// </para>
85+ /// </summary>
86+ /// <param name="url">The url to list from.</param>
87+ /// <returns>The references in the remote repository.</returns>
88+ public virtual IEnumerable < DirectReference > ListReferences ( string url )
89+ {
90+ Ensure . ArgumentNotNull ( url , "url" ) ;
91+
92+ using ( RemoteSafeHandle remoteHandle = Proxy . git_remote_create_inmemory ( repository . Handle , null , url ) )
93+ {
94+ Proxy . git_remote_connect ( remoteHandle , GitDirection . Fetch ) ;
95+ return Proxy . git_remote_ls ( repository , remoteHandle ) ;
96+ }
97+ }
98+
99+ static void DoFetch ( RemoteSafeHandle remoteHandle , GitRemoteCallbacks gitCallbacks , TagFetchMode ? tagFetchMode )
100+ {
101+ if ( tagFetchMode . HasValue )
102+ {
103+ Proxy . git_remote_set_autotag ( remoteHandle , tagFetchMode . Value ) ;
104+ }
105+
106+ // It is OK to pass the reference to the GitCallbacks directly here because libgit2 makes a copy of
107+ // the data in the git_remote_callbacks structure. If, in the future, libgit2 changes its implementation
108+ // to store a reference to the git_remote_callbacks structure this would introduce a subtle bug
109+ // where the managed layer could move the git_remote_callbacks to a different location in memory,
110+ // but libgit2 would still reference the old address.
111+ //
112+ // Also, if GitRemoteCallbacks were a class instead of a struct, we would need to guard against
113+ // GC occuring in between setting the remote callbacks and actual usage in one of the functions afterwords.
114+ Proxy . git_remote_set_callbacks ( remoteHandle , ref gitCallbacks ) ;
115+
116+ try
117+ {
118+ Proxy . git_remote_connect ( remoteHandle , GitDirection . Fetch ) ;
119+ Proxy . git_remote_download ( remoteHandle ) ;
120+ Proxy . git_remote_update_tips ( remoteHandle ) ;
121+ }
122+ finally
123+ {
124+ Proxy . git_remote_disconnect ( remoteHandle ) ;
125+ }
126+ }
127+
77128 /// <summary>
78129 /// Fetch from the <see cref="Remote"/>.
79130 /// </summary>
@@ -99,31 +150,39 @@ public virtual void Fetch(
99150 var callbacks = new RemoteCallbacks ( onProgress , onTransferProgress , onUpdateTips , credentials ) ;
100151 GitRemoteCallbacks gitCallbacks = callbacks . GenerateCallbacks ( ) ;
101152
102- if ( tagFetchMode . HasValue )
103- {
104- Proxy . git_remote_set_autotag ( remoteHandle , tagFetchMode . Value ) ;
105- }
153+ DoFetch ( remoteHandle , gitCallbacks , tagFetchMode ) ;
154+ }
155+ }
106156
107- // It is OK to pass the reference to the GitCallbacks directly here because libgit2 makes a copy of
108- // the data in the git_remote_callbacks structure. If, in the future, libgit2 changes its implementation
109- // to store a reference to the git_remote_callbacks structure this would introduce a subtle bug
110- // where the managed layer could move the git_remote_callbacks to a different location in memory,
111- // but libgit2 would still reference the old address.
112- //
113- // Also, if GitRemoteCallbacks were a class instead of a struct, we would need to guard against
114- // GC occuring in between setting the remote callbacks and actual usage in one of the functions afterwords.
115- Proxy . git_remote_set_callbacks ( remoteHandle , ref gitCallbacks ) ;
157+ /// <summary>
158+ /// Fetch from a url with a set of fetch refspecs
159+ /// </summary>
160+ /// <param name="url">The url to fetch from</param>
161+ /// <param name="refspecs">The list of resfpecs to use</param>
162+ /// <param name="tagFetchMode">Optional parameter indicating what tags to download.</param>
163+ /// <param name="onProgress">Progress callback. Corresponds to libgit2 progress callback.</param>
164+ /// <param name="onUpdateTips">UpdateTips callback. Corresponds to libgit2 update_tips callback.</param>
165+ /// <param name="onTransferProgress">Callback method that transfer progress will be reported through.
166+ /// Reports the client's state regarding the received and processed (bytes, objects) from the server.</param>
167+ /// <param name="credentials">Credentials to use for username/password authentication.</param>
168+ public virtual void Fetch (
169+ string url ,
170+ IEnumerable < string > refspecs ,
171+ TagFetchMode ? tagFetchMode = null ,
172+ ProgressHandler onProgress = null ,
173+ UpdateTipsHandler onUpdateTips = null ,
174+ TransferProgressHandler onTransferProgress = null ,
175+ Credentials credentials = null )
176+ {
177+ Ensure . ArgumentNotNull ( url , "url" ) ;
116178
117- try
118- {
119- Proxy . git_remote_connect ( remoteHandle , GitDirection . Fetch ) ;
120- Proxy . git_remote_download ( remoteHandle ) ;
121- Proxy . git_remote_update_tips ( remoteHandle ) ;
122- }
123- finally
124- {
125- Proxy . git_remote_disconnect ( remoteHandle ) ;
126- }
179+ using ( RemoteSafeHandle remoteHandle = Proxy . git_remote_create_inmemory ( repository . Handle , null , url ) )
180+ {
181+ Proxy . git_remote_set_fetch_refspecs ( remoteHandle , refspecs ) ;
182+ var callbacks = new RemoteCallbacks ( onProgress , onTransferProgress , onUpdateTips , credentials ) ;
183+ GitRemoteCallbacks gitCallbacks = callbacks . GenerateCallbacks ( ) ;
184+
185+ DoFetch ( remoteHandle , gitCallbacks , tagFetchMode ) ;
127186 }
128187 }
129188
0 commit comments