Skip to content

Commit b456277

Browse files
committed
Add Functionality to List Remote References without creating a Repository
1 parent 2c98992 commit b456277

File tree

9 files changed

+219
-44
lines changed

9 files changed

+219
-44
lines changed

LibGit2Sharp.Tests/LibGit2Sharp.Tests.csproj

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -65,6 +65,7 @@
6565
<Compile Include="PatchStatsFixture.cs" />
6666
<Compile Include="RefSpecFixture.cs" />
6767
<Compile Include="EqualityFixture.cs" />
68+
<Compile Include="RemoteRepositoryFixture.cs" />
6869
<Compile Include="RevertFixture.cs" />
6970
<Compile Include="SetErrorFixture.cs" />
7071
<Compile Include="SignatureFixture.cs" />
@@ -124,6 +125,7 @@
124125
<Compile Include="TestHelpers\SignatureExtensions.cs" />
125126
<Compile Include="TestHelpers\SkippableFactAttribute.cs" />
126127
<Compile Include="LogFixture.cs" />
128+
<Compile Include="TestHelpers\TestRemoteRefs.cs" />
127129
<Compile Include="TreeDefinitionFixture.cs" />
128130
<Compile Include="TreeFixture.cs" />
129131
<Compile Include="UnstageFixture.cs" />

LibGit2Sharp.Tests/NetworkFixture.cs

Lines changed: 12 additions & 40 deletions
Original file line numberDiff line numberDiff line change
@@ -34,11 +34,11 @@ public void CanListRemoteReferences(string url)
3434
List<Tuple<string, string>> actualRefs = references.
3535
Select(directRef => new Tuple<string, string>(directRef.CanonicalName, directRef.TargetIdentifier)).ToList();
3636

37-
Assert.Equal(ExpectedRemoteRefs.Count, actualRefs.Count);
38-
for (int i = 0; i < ExpectedRemoteRefs.Count; i++)
37+
Assert.Equal(TestRemoteRefs.ExpectedRemoteRefs.Count, actualRefs.Count);
38+
for (int i = 0; i < TestRemoteRefs.ExpectedRemoteRefs.Count; i++)
3939
{
40-
Assert.Equal(ExpectedRemoteRefs[i].Item2, actualRefs[i].Item2);
41-
Assert.Equal(ExpectedRemoteRefs[i].Item1, actualRefs[i].Item1);
40+
Assert.Equal(TestRemoteRefs.ExpectedRemoteRefs[i].Item2, actualRefs[i].Item2);
41+
Assert.Equal(TestRemoteRefs.ExpectedRemoteRefs[i].Item1, actualRefs[i].Item1);
4242
}
4343
}
4444
}
@@ -65,11 +65,11 @@ public void CanListRemoteReferencesFromUrl(string url)
6565
List<Tuple<string, string>> actualRefs = references.
6666
Select(directRef => new Tuple<string, string>(directRef.CanonicalName, directRef.TargetIdentifier)).ToList();
6767

68-
Assert.Equal(ExpectedRemoteRefs.Count, actualRefs.Count);
69-
for (int i = 0; i < ExpectedRemoteRefs.Count; i++)
68+
Assert.Equal(TestRemoteRefs.ExpectedRemoteRefs.Count, actualRefs.Count);
69+
for (int i = 0; i < TestRemoteRefs.ExpectedRemoteRefs.Count; i++)
7070
{
71-
Assert.Equal(ExpectedRemoteRefs[i].Item2, actualRefs[i].Item2);
72-
Assert.Equal(ExpectedRemoteRefs[i].Item1, actualRefs[i].Item1);
71+
Assert.Equal(TestRemoteRefs.ExpectedRemoteRefs[i].Item2, actualRefs[i].Item2);
72+
Assert.Equal(TestRemoteRefs.ExpectedRemoteRefs[i].Item1, actualRefs[i].Item1);
7373
}
7474
}
7575
}
@@ -98,11 +98,11 @@ public void CanListRemoteReferenceObjects()
9898
actualRefs.Add(new Tuple<string, string>(reference.CanonicalName, reference.Target.Id.Sha));
9999
}
100100

101-
Assert.Equal(ExpectedRemoteRefs.Count, actualRefs.Count);
102-
for (int i = 0; i < ExpectedRemoteRefs.Count; i++)
101+
Assert.Equal(TestRemoteRefs.ExpectedRemoteRefs.Count, actualRefs.Count);
102+
for (int i = 0; i < TestRemoteRefs.ExpectedRemoteRefs.Count; i++)
103103
{
104-
Assert.Equal(ExpectedRemoteRefs[i].Item1, actualRefs[i].Item1);
105-
Assert.Equal(ExpectedRemoteRefs[i].Item2, actualRefs[i].Item2);
104+
Assert.Equal(TestRemoteRefs.ExpectedRemoteRefs[i].Item1, actualRefs[i].Item1);
105+
Assert.Equal(TestRemoteRefs.ExpectedRemoteRefs[i].Item2, actualRefs[i].Item2);
106106
}
107107
}
108108
}
@@ -254,33 +254,5 @@ public void CanMergeFetchedRefs()
254254
Assert.Equal(mergeResult.Status, MergeStatus.NonFastForward);
255255
}
256256
}
257-
258-
/*
259-
* git ls-remote http://github.com/libgit2/TestGitRepository
260-
* 49322bb17d3acc9146f98c97d078513228bbf3c0 HEAD
261-
* 0966a434eb1a025db6b71485ab63a3bfbea520b6 refs/heads/first-merge
262-
* 49322bb17d3acc9146f98c97d078513228bbf3c0 refs/heads/master
263-
* 42e4e7c5e507e113ebbb7801b16b52cf867b7ce1 refs/heads/no-parent
264-
* d96c4e80345534eccee5ac7b07fc7603b56124cb refs/tags/annotated_tag
265-
* c070ad8c08840c8116da865b2d65593a6bb9cd2a refs/tags/annotated_tag^{}
266-
* 55a1a760df4b86a02094a904dfa511deb5655905 refs/tags/blob
267-
* 8f50ba15d49353813cc6e20298002c0d17b0a9ee refs/tags/commit_tree
268-
* 6e0c7bdb9b4ed93212491ee778ca1c65047cab4e refs/tags/nearly-dangling
269-
*/
270-
/// <summary>
271-
/// Expected references on http://github.com/libgit2/TestGitRepository
272-
/// </summary>
273-
private static List<Tuple<string, string>> ExpectedRemoteRefs = new List<Tuple<string, string>>()
274-
{
275-
new Tuple<string, string>("HEAD", "49322bb17d3acc9146f98c97d078513228bbf3c0"),
276-
new Tuple<string, string>("refs/heads/first-merge", "0966a434eb1a025db6b71485ab63a3bfbea520b6"),
277-
new Tuple<string, string>("refs/heads/master", "49322bb17d3acc9146f98c97d078513228bbf3c0"),
278-
new Tuple<string, string>("refs/heads/no-parent", "42e4e7c5e507e113ebbb7801b16b52cf867b7ce1"),
279-
new Tuple<string, string>("refs/tags/annotated_tag", "d96c4e80345534eccee5ac7b07fc7603b56124cb"),
280-
new Tuple<string, string>("refs/tags/annotated_tag^{}", "c070ad8c08840c8116da865b2d65593a6bb9cd2a"),
281-
new Tuple<string, string>("refs/tags/blob", "55a1a760df4b86a02094a904dfa511deb5655905"),
282-
new Tuple<string, string>("refs/tags/commit_tree", "8f50ba15d49353813cc6e20298002c0d17b0a9ee"),
283-
new Tuple<string, string>("refs/tags/nearly-dangling", "6e0c7bdb9b4ed93212491ee778ca1c65047cab4e"),
284-
};
285257
}
286258
}
Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,34 @@
1+
using System;
2+
using System.Collections.Generic;
3+
using System.Linq;
4+
using System.Text;
5+
using LibGit2Sharp.Tests.TestHelpers;
6+
using Xunit;
7+
using Xunit.Extensions;
8+
9+
namespace LibGit2Sharp.Tests
10+
{
11+
public class RemoteRepositoryFixture : BaseFixture
12+
{
13+
[Theory]
14+
[InlineData("http://github.com/libgit2/TestGitRepository")]
15+
[InlineData("https://github.com/libgit2/TestGitRepository")]
16+
[InlineData("git://github.com/libgit2/TestGitRepository.git")]
17+
public void CanListRemoteRefs(string url)
18+
{
19+
var repo = new RemoteRepository();
20+
21+
IEnumerable<RemoteHead> references = repo.ListReferences(url);
22+
23+
List<Tuple<string, string>> actualRefs = references.
24+
Select(directRef => new Tuple<string, string>(directRef.CanonicalName, directRef.Sha)).ToList();
25+
26+
Assert.Equal(TestRemoteRefs.ExpectedRemoteRefs.Count, actualRefs.Count);
27+
for (int i = 0; i < TestRemoteRefs.ExpectedRemoteRefs.Count; i++)
28+
{
29+
Assert.Equal(TestRemoteRefs.ExpectedRemoteRefs[i].Item2, actualRefs[i].Item2);
30+
Assert.Equal(TestRemoteRefs.ExpectedRemoteRefs[i].Item1, actualRefs[i].Item1);
31+
}
32+
}
33+
}
34+
}
Lines changed: 38 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,38 @@
1+
using System;
2+
using System.Collections.Generic;
3+
using System.Linq;
4+
using System.Text;
5+
6+
namespace LibGit2Sharp.Tests.TestHelpers
7+
{
8+
public class TestRemoteRefs
9+
{
10+
/*
11+
* git ls-remote http://github.com/libgit2/TestGitRepository
12+
* 49322bb17d3acc9146f98c97d078513228bbf3c0 HEAD
13+
* 0966a434eb1a025db6b71485ab63a3bfbea520b6 refs/heads/first-merge
14+
* 49322bb17d3acc9146f98c97d078513228bbf3c0 refs/heads/master
15+
* 42e4e7c5e507e113ebbb7801b16b52cf867b7ce1 refs/heads/no-parent
16+
* d96c4e80345534eccee5ac7b07fc7603b56124cb refs/tags/annotated_tag
17+
* c070ad8c08840c8116da865b2d65593a6bb9cd2a refs/tags/annotated_tag^{}
18+
* 55a1a760df4b86a02094a904dfa511deb5655905 refs/tags/blob
19+
* 8f50ba15d49353813cc6e20298002c0d17b0a9ee refs/tags/commit_tree
20+
* 6e0c7bdb9b4ed93212491ee778ca1c65047cab4e refs/tags/nearly-dangling
21+
*/
22+
/// <summary>
23+
/// Expected references on http://github.com/libgit2/TestGitRepository
24+
/// </summary>
25+
public static List<Tuple<string, string>> ExpectedRemoteRefs = new List<Tuple<string, string>>()
26+
{
27+
new Tuple<string, string>("HEAD", "49322bb17d3acc9146f98c97d078513228bbf3c0"),
28+
new Tuple<string, string>("refs/heads/first-merge", "0966a434eb1a025db6b71485ab63a3bfbea520b6"),
29+
new Tuple<string, string>("refs/heads/master", "49322bb17d3acc9146f98c97d078513228bbf3c0"),
30+
new Tuple<string, string>("refs/heads/no-parent", "42e4e7c5e507e113ebbb7801b16b52cf867b7ce1"),
31+
new Tuple<string, string>("refs/tags/annotated_tag", "d96c4e80345534eccee5ac7b07fc7603b56124cb"),
32+
new Tuple<string, string>("refs/tags/annotated_tag^{}", "c070ad8c08840c8116da865b2d65593a6bb9cd2a"),
33+
new Tuple<string, string>("refs/tags/blob", "55a1a760df4b86a02094a904dfa511deb5655905"),
34+
new Tuple<string, string>("refs/tags/commit_tree", "8f50ba15d49353813cc6e20298002c0d17b0a9ee"),
35+
new Tuple<string, string>("refs/tags/nearly-dangling", "6e0c7bdb9b4ed93212491ee778ca1c65047cab4e"),
36+
};
37+
}
38+
}

LibGit2Sharp/Core/NativeMethods.cs

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1625,6 +1625,9 @@ internal static extern int git_treebuilder_insert(
16251625

16261626
[DllImport(libgit2)]
16271627
internal static extern int git_cherrypick(RepositorySafeHandle repo, GitObjectSafeHandle commit, GitCherryPickOptions options);
1628+
1629+
[DllImport(libgit2)]
1630+
internal static extern int git_repository_new(out RepositorySafeHandle repo);
16281631
}
16291632
}
16301633
// ReSharper restore InconsistentNaming

LibGit2Sharp/Core/Proxy.cs

Lines changed: 46 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1931,7 +1931,35 @@ public static IList<string> git_remote_list(RepositorySafeHandle repo)
19311931
}
19321932
}
19331933

1934-
public static IEnumerable<DirectReference> git_remote_ls(Repository repository, RemoteSafeHandle remote)
1934+
public static IEnumerable<RemoteHead> git_remote_ls(RemoteSafeHandle remote)
1935+
{
1936+
var heads = new List<RemoteHead>();
1937+
1938+
foreach (var remoteHead in git_remote_head_ls(remote))
1939+
{
1940+
string name = LaxUtf8Marshaler.FromNative(remoteHead.NamePtr);
1941+
var objectId = new ObjectId(remoteHead.Oid);
1942+
var head = new RemoteHead(objectId, name);
1943+
heads.Add(head);
1944+
}
1945+
1946+
return heads;
1947+
}
1948+
1949+
public static IEnumerable<DirectReference> git_remote_ls(IRepository repository, RemoteSafeHandle remote)
1950+
{
1951+
var refs = new List<DirectReference>();
1952+
1953+
foreach (var remoteHead in git_remote_head_ls(remote))
1954+
{
1955+
string name = LaxUtf8Marshaler.FromNative(remoteHead.NamePtr);
1956+
refs.Add(new DirectReference(name, repository, remoteHead.Oid));
1957+
}
1958+
1959+
return refs;
1960+
}
1961+
1962+
private static IEnumerable<GitRemoteHead> git_remote_head_ls(RemoteSafeHandle remote)
19351963
{
19361964
IntPtr heads;
19371965
UIntPtr count;
@@ -1946,7 +1974,7 @@ public static IEnumerable<DirectReference> git_remote_ls(Repository repository,
19461974
throw new OverflowException();
19471975
}
19481976

1949-
var refs = new List<DirectReference>();
1977+
var refs = new List<GitRemoteHead>();
19501978
IntPtr currentHead = heads;
19511979

19521980
for (int i = 0; i < intCount; i++)
@@ -1960,8 +1988,7 @@ public static IEnumerable<DirectReference> git_remote_ls(Repository repository,
19601988
throw new InvalidOperationException("Not expecting null value for reference name.");
19611989
}
19621990

1963-
string name = LaxUtf8Marshaler.FromNative(remoteHead.NamePtr);
1964-
refs.Add(new DirectReference(name, repository, remoteHead.Oid));
1991+
refs.Add(remoteHead);
19651992

19661993
currentHead = IntPtr.Add(currentHead, IntPtr.Size);
19671994
}
@@ -2167,6 +2194,21 @@ public static RepositorySafeHandle git_repository_open(string path)
21672194
return repo;
21682195
}
21692196

2197+
public static RepositorySafeHandle git_repository_new()
2198+
{
2199+
RepositorySafeHandle repo;
2200+
int res = NativeMethods.git_repository_new(out repo);
2201+
2202+
if (res == (int)GitErrorCode.Error)
2203+
{
2204+
throw new LibGit2SharpException("Unable to create new Repository");
2205+
}
2206+
2207+
Ensure.ZeroResult(res);
2208+
2209+
return repo;
2210+
}
2211+
21702212
public static void git_repository_open_ext(string path, RepositoryOpenFlags flags, string ceilingDirs)
21712213
{
21722214
int res;

LibGit2Sharp/LibGit2Sharp.csproj

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -138,6 +138,8 @@
138138
<Compile Include="Core\GitBuf.cs" />
139139
<Compile Include="FilteringOptions.cs" />
140140
<Compile Include="MergeFetchHeadNotFoundException.cs" />
141+
<Compile Include="RemoteHead.cs" />
142+
<Compile Include="RemoteRepository.cs" />
141143
<Compile Include="RepositoryOperationContext.cs" />
142144
<Compile Include="ResetMode.cs" />
143145
<Compile Include="NoteCollectionExtensions.cs" />

LibGit2Sharp/RemoteHead.cs

Lines changed: 48 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,48 @@
1+
using System;
2+
using System.Collections.Generic;
3+
using System.Linq;
4+
using System.Text;
5+
using LibGit2Sharp.Core;
6+
7+
namespace LibGit2Sharp
8+
{
9+
/// <summary>
10+
/// Reference to a Remote Head
11+
/// </summary>
12+
public class RemoteHead
13+
{
14+
private readonly ObjectId targetOid;
15+
private readonly string canonicalName;
16+
17+
/// <summary>
18+
/// Needed for mocking purposes.
19+
/// </summary>
20+
protected RemoteHead()
21+
{ }
22+
23+
internal RemoteHead(ObjectId targetOid, string canonicalName)
24+
{
25+
Ensure.ArgumentNotNull(targetOid, "targetOid");
26+
Ensure.ArgumentNotNull(canonicalName, "canonicalName");
27+
28+
this.targetOid = targetOid;
29+
this.canonicalName = canonicalName;
30+
}
31+
32+
/// <summary>
33+
/// Gets the Remote Head sha.
34+
/// </summary>
35+
/// <value>
36+
/// The Remote Head sha.
37+
/// </value>
38+
public virtual string Sha { get { return targetOid.Sha; } }
39+
40+
/// <summary>
41+
/// Gets the Remote Head Canonical Name
42+
/// </summary>
43+
/// <value>
44+
/// The Canonical Name
45+
/// </value>
46+
public virtual string CanonicalName { get { return canonicalName; } }
47+
}
48+
}

LibGit2Sharp/RemoteRepository.cs

Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,34 @@
1+
using System;
2+
using System.Collections;
3+
using System.Collections.Generic;
4+
using System.Linq;
5+
using System.Text;
6+
using LibGit2Sharp.Core;
7+
using LibGit2Sharp.Core.Handles;
8+
9+
namespace LibGit2Sharp
10+
{
11+
/// <summary>
12+
/// Remote Only Repository
13+
/// </summary>
14+
public class RemoteRepository
15+
{
16+
/// <summary>
17+
/// Lists the Remote Repository References.
18+
/// </summary>
19+
/// <param name="url">The URL.</param>
20+
/// <returns></returns>
21+
public virtual IEnumerable<RemoteHead> ListReferences(string url)
22+
{
23+
Ensure.ArgumentNotNull(url, "url");
24+
25+
using (RepositorySafeHandle repositoryHandle = Proxy.git_repository_new())
26+
using (RemoteSafeHandle remoteHandle = Proxy.git_remote_create_anonymous(repositoryHandle, url))
27+
{
28+
GitRemoteCallbacks gitCallbacks = new GitRemoteCallbacks { version = 1 };
29+
Proxy.git_remote_connect(remoteHandle, GitDirection.Fetch, ref gitCallbacks);
30+
return Proxy.git_remote_ls(remoteHandle);
31+
}
32+
}
33+
}
34+
}

0 commit comments

Comments
 (0)