Skip to content

Commit 91de647

Browse files
committed
Expose libgit2 fetch functionality.
1 parent 6301a50 commit 91de647

File tree

10 files changed

+220
-5
lines changed

10 files changed

+220
-5
lines changed

LibGit2Sharp.Tests/BranchFixture.cs

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -220,6 +220,19 @@ public void CanListAllBranchesIncludingRemoteRefs()
220220
}
221221
}
222222

223+
[Fact]
224+
public void CanResolveTrackedRemote()
225+
{
226+
using (var repo = new Repository(StandardTestRepoPath))
227+
{
228+
Branch master = repo.Branches["master"];
229+
Assert.Equal(repo.Remotes["origin"], master.ResolveTrackedRemote());
230+
231+
Branch test = repo.Branches["test"];
232+
Assert.Null(test);
233+
}
234+
}
235+
223236
[Fact]
224237
public void CanLookupABranchByItsCanonicalName()
225238
{

LibGit2Sharp/Branch.cs

Lines changed: 28 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -136,9 +136,31 @@ public virtual ICommitLog Commits
136136
get { return repo.Commits.QueryBy(new Filter { Since = this }); }
137137
}
138138

139+
/// <summary>
140+
/// Gets the <see cref="Remote"/> tracking this branch
141+
/// </summary>
142+
/// <returns>The <see cref="Remote"/> tracking this branch if one exists, otherwise returns null.</returns>
143+
public virtual Remote ResolveTrackedRemote()
144+
{
145+
if (IsTracking)
146+
{
147+
string trackedRemoteName = ResolveTrackedRemoteName();
148+
if (string.IsNullOrEmpty(trackedRemoteName))
149+
{
150+
return null;
151+
}
152+
153+
return repo.Remotes[trackedRemoteName];
154+
}
155+
else
156+
{
157+
return null;
158+
}
159+
}
160+
139161
private Branch ResolveTrackedBranch()
140162
{
141-
var trackedRemote = repo.Config.Get<string>("branch", Name, "remote", null);
163+
string trackedRemote = ResolveTrackedRemoteName();
142164
if (trackedRemote == null)
143165
{
144166
return null;
@@ -154,6 +176,11 @@ private Branch ResolveTrackedBranch()
154176
return repo.Branches[remoteRefName];
155177
}
156178

179+
private string ResolveTrackedRemoteName()
180+
{
181+
return repo.Config.Get<string>("branch", Name, "remote", null) as string;
182+
}
183+
157184
private static string ResolveTrackedReference(string trackedRemote, string trackedRefName)
158185
{
159186
if (trackedRemote == ".")

LibGit2Sharp/Core/GitDirection.cs

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
using System;
2+
3+
namespace LibGit2Sharp.Core
4+
{
5+
internal enum GitDirection
6+
{
7+
Fetch = 0,
8+
Push = 1
9+
}
10+
}

LibGit2Sharp/Core/GitIndexerStats.cs

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
using System;
2+
using System.Runtime.InteropServices;
3+
4+
namespace LibGit2Sharp.Core
5+
{
6+
[StructLayout(LayoutKind.Sequential)]
7+
internal struct GitIndexerStats
8+
{
9+
public uint total;
10+
public uint processed;
11+
}
12+
}

LibGit2Sharp/Core/NativeMethods.cs

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -567,6 +567,18 @@ public static extern int git_remote_new(
567567
[return : MarshalAs(UnmanagedType.CustomMarshaler, MarshalTypeRef = typeof(Utf8Marshaler))]
568568
public static extern string git_remote_url(RemoteSafeHandle remote);
569569

570+
[DllImport(libgit2)]
571+
public static extern int git_remote_connect(RemoteSafeHandle remote, GitDirection direction);
572+
573+
[DllImport(libgit2)]
574+
public static extern void git_remote_disconnect(RemoteSafeHandle remote);
575+
576+
[DllImport(libgit2)]
577+
public static extern int git_remote_download(RemoteSafeHandle remote, ref long bytes, ref GitIndexerStats stats);
578+
579+
[DllImport(libgit2)]
580+
public static extern int git_remote_update_tips(RemoteSafeHandle remote, IntPtr cb);
581+
570582
[DllImport(libgit2)]
571583
public static extern int git_remote_save(RemoteSafeHandle remote);
572584

LibGit2Sharp/FetchProgress.cs

Lines changed: 43 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,43 @@
1+
using LibGit2Sharp.Core;
2+
using System;
3+
using System.Collections.Generic;
4+
using System.Linq;
5+
using System.Text;
6+
7+
namespace LibGit2Sharp
8+
{
9+
/// <summary>
10+
/// Contains data regarding fetch progress.
11+
/// </summary>
12+
public class FetchProgress : IndexerStats
13+
{
14+
/// <summary>
15+
/// Fetch progress constructor.
16+
/// </summary>
17+
public FetchProgress()
18+
{ }
19+
20+
/// <summary>
21+
/// Bytes received.
22+
/// </summary>
23+
public long Bytes
24+
{
25+
get
26+
{
27+
return bytes;
28+
}
29+
}
30+
31+
internal override void Reset()
32+
{
33+
base.Reset();
34+
bytes = 0;
35+
}
36+
37+
#region Fields
38+
39+
internal long bytes;
40+
41+
#endregion
42+
}
43+
}

LibGit2Sharp/IndexerStats.cs

Lines changed: 57 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,57 @@
1+
using System;
2+
using System.Collections.Generic;
3+
using System.Linq;
4+
using System.Text;
5+
6+
namespace LibGit2Sharp.Core
7+
{
8+
/// <summary>
9+
/// Wrapper around git_indexer_stats
10+
/// </summary>
11+
public class IndexerStats
12+
{
13+
/// <summary>
14+
/// Constructor
15+
/// </summary>
16+
public IndexerStats()
17+
{
18+
indexerStats = new GitIndexerStats();
19+
}
20+
/// <summary>
21+
/// Total number of objects
22+
/// </summary>
23+
public long TotalObjectCount
24+
{
25+
get
26+
{
27+
return indexerStats.total;
28+
}
29+
}
30+
31+
/// <summary>
32+
/// Number of objects processed.
33+
/// </summary>
34+
public long ProcessedObjectCount
35+
{
36+
get
37+
{
38+
return indexerStats.processed;
39+
}
40+
}
41+
42+
/// <summary>
43+
/// Reset internal data
44+
/// </summary>
45+
internal virtual void Reset()
46+
{
47+
indexerStats.processed = 0;
48+
indexerStats.total = 0;
49+
}
50+
51+
#region Fields
52+
53+
internal GitIndexerStats indexerStats;
54+
55+
#endregion
56+
}
57+
}

LibGit2Sharp/LibGit2Sharp.csproj

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -66,8 +66,10 @@
6666
<Compile Include="CommitLog.cs" />
6767
<Compile Include="Configuration.cs" />
6868
<Compile Include="ContentChanges.cs" />
69+
<Compile Include="Core\GitIndexerStats.cs" />
6970
<Compile Include="TagCollectionExtensions.cs" />
7071
<Compile Include="Core\Compat\Environment.cs" />
72+
<Compile Include="FetchProgress.cs" />
7173
<Compile Include="Core\FilePath.cs" />
7274
<Compile Include="Core\FilePathExtensions.cs" />
7375
<Compile Include="Core\FilePathMarshaler.cs" />
@@ -79,6 +81,7 @@
7981
<Compile Include="Core\GitBranchType.cs" />
8082
<Compile Include="Core\GitDiff.cs" />
8183
<Compile Include="Core\GitDiffExtensions.cs" />
84+
<Compile Include="Core\GitDirection.cs" />
8285
<Compile Include="Core\GitError.cs" />
8386
<Compile Include="Core\GitErrorCategory.cs" />
8487
<Compile Include="Core\GitNoteData.cs" />
@@ -93,6 +96,7 @@
9396
<Compile Include="Core\Handles\OidSafeHandle.cs" />
9497
<Compile Include="Core\Handles\TreeBuilderSafeHandle.cs" />
9598
<Compile Include="Core\Handles\TreeEntrySafeHandle_Owned.cs" />
99+
<Compile Include="IndexerStats.cs" />
96100
<Compile Include="Core\ReferenceExtensions.cs" />
97101
<Compile Include="Core\Handles\ReferenceSafeHandle.cs" />
98102
<Compile Include="Core\Handles\SignatureSafeHandle.cs" />

LibGit2Sharp/Remote.cs

Lines changed: 38 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -12,13 +12,16 @@ public class Remote : IEquatable<Remote>
1212
private static readonly LambdaEqualityHelper<Remote> equalityHelper =
1313
new LambdaEqualityHelper<Remote>(new Func<Remote, object>[] { x => x.Name, x => x.Url });
1414

15+
private Repository repository;
16+
1517
/// <summary>
1618
/// Needed for mocking purposes.
1719
/// </summary>
1820
protected Remote()
1921
{ }
2022

21-
internal static Remote CreateFromPtr(RemoteSafeHandle handle)
23+
24+
internal static Remote CreateFromPtr(Repository repository, RemoteSafeHandle handle)
2225
{
2326
if (handle == null)
2427
{
@@ -32,6 +35,7 @@ internal static Remote CreateFromPtr(RemoteSafeHandle handle)
3235
{
3336
Name = name,
3437
Url = url,
38+
repository = repository,
3539
};
3640

3741
return remote;
@@ -47,6 +51,39 @@ internal static Remote CreateFromPtr(RemoteSafeHandle handle)
4751
/// </summary>
4852
public virtual string Url { get; private set; }
4953

54+
/// <summary>
55+
/// Fetch updates from the remote.
56+
/// </summary>
57+
/// <param name="fetchProgress">The <see cref = "FetchProgress" /> to report current fetch progress.</param>
58+
public virtual void Fetch(FetchProgress fetchProgress)
59+
{
60+
// reset the current progress object
61+
fetchProgress.Reset();
62+
63+
using (RemoteSafeHandle remoteHandle = repository.Remotes.LoadRemote(Name, true))
64+
{
65+
try
66+
{
67+
int res = NativeMethods.git_remote_connect(remoteHandle, GitDirection.Fetch);
68+
Ensure.Success(res);
69+
70+
int downloadResult = NativeMethods.git_remote_download(remoteHandle, ref fetchProgress.bytes, ref fetchProgress.indexerStats);
71+
Ensure.Success(downloadResult);
72+
}
73+
finally
74+
{
75+
if (remoteHandle != null)
76+
{
77+
NativeMethods.git_remote_disconnect(remoteHandle);
78+
}
79+
}
80+
81+
// update references
82+
int updateTipsResult = NativeMethods.git_remote_update_tips(remoteHandle, IntPtr.Zero);
83+
Ensure.Success(updateTipsResult);
84+
}
85+
}
86+
5087
/// <summary>
5188
/// Determines whether the specified <see cref = "Object" /> is equal to the current <see cref = "Remote" />.
5289
/// </summary>

LibGit2Sharp/RemoteCollection.cs

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -55,7 +55,7 @@ private Remote RemoteForName(string name)
5555
{
5656
using (RemoteSafeHandle handle = LoadRemote(name, false))
5757
{
58-
return Remote.CreateFromPtr(handle);
58+
return Remote.CreateFromPtr(repository, handle);
5959
}
6060
}
6161

@@ -100,7 +100,7 @@ public virtual Remote Add(string name, string url)
100100

101101
using (handle)
102102
{
103-
return Remote.CreateFromPtr(handle);
103+
return Remote.CreateFromPtr(repository, handle);
104104
}
105105
}
106106

@@ -142,7 +142,7 @@ public virtual Remote Add(string name, string url, string fetchRefSpec)
142142
res = NativeMethods.git_remote_save(handle);
143143
Ensure.Success(res);
144144

145-
return Remote.CreateFromPtr(handle);
145+
return Remote.CreateFromPtr(repository, handle);
146146
}
147147
}
148148

0 commit comments

Comments
 (0)