Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions LibGit2Sharp.Tests/LibGit2Sharp.Tests.csproj
Original file line number Diff line number Diff line change
Expand Up @@ -69,6 +69,7 @@
<Compile Include="ConfigurationFixture.cs" />
<Compile Include="AttributesFixture.cs" />
<Compile Include="CommitAncestorFixture.cs" />
<Compile Include="NetworkFixture.cs" />
<Compile Include="NoteFixture.cs" />
<Compile Include="DiffBlobToBlobFixture.cs" />
<Compile Include="DiffTreeToTargetFixture.cs" />
Expand Down
96 changes: 96 additions & 0 deletions LibGit2Sharp.Tests/NetworkFixture.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,96 @@
using System.Collections.Generic;
using System.Linq;
using LibGit2Sharp.Core.Compat;
using LibGit2Sharp.Tests.TestHelpers;
using Xunit;
using Xunit.Extensions;

namespace LibGit2Sharp.Tests
{
public class NetworkFixture : BaseFixture
{
[Theory]
[InlineData("https://github.com/libgit2/TestGitRepository")]
[InlineData("https://github.com/libgit2/TestGitRepository")]
[InlineData("git://github.com/libgit2/TestGitRepository.git")]
public void CanListRemoteReferences(string url)
{
string remoteName = "testRemote";

var scd = BuildSelfCleaningDirectory();
using (var repo = Repository.Init(scd.RootedDirectoryPath))
{
Remote remote = repo.Network.Remotes.Add(remoteName, url);
IEnumerable<DirectReference> references = repo.Network.ListReferences(remote);

List<Tuple<string, string>> actualRefs = references.
Select(directRef => new Tuple<string, string>(directRef.CanonicalName, directRef.TargetIdentifier)).ToList();

Assert.Equal(ExpectedRemoteRefs.Count, actualRefs.Count);
for (int i = 0; i < ExpectedRemoteRefs.Count; i++)
{
Assert.Equal(ExpectedRemoteRefs[i].Item2, actualRefs[i].Item2);
Assert.Equal(ExpectedRemoteRefs[i].Item1, actualRefs[i].Item1);
}
}
}

[Fact]
public void CanListRemoteReferenceObjects()
{
string url = "https://github.com/libgit2/TestGitRepository";
string remoteName = "origin";

var scd = BuildSelfCleaningDirectory();
using (Repository repo = Repository.Clone(url, scd.RootedDirectoryPath))
{
Remote remote = repo.Network.Remotes[remoteName];
IEnumerable<DirectReference> references = repo.Network.ListReferences(remote);

List<Tuple<string, string>> actualRefs = new List<Tuple<string,string>>();

foreach(DirectReference reference in references)
{
Assert.NotNull(reference.CanonicalName);
Assert.NotNull(reference.Target);
actualRefs.Add(new Tuple<string, string>(reference.CanonicalName, reference.Target.Id.Sha));
}

Assert.Equal(ExpectedRemoteRefs.Count, actualRefs.Count);
for (int i = 0; i < ExpectedRemoteRefs.Count; i++)
{
Assert.Equal(ExpectedRemoteRefs[i].Item1, actualRefs[i].Item1);
Assert.Equal(ExpectedRemoteRefs[i].Item2, actualRefs[i].Item2);
}
}
}

/*
* git ls-remote https://github.com/libgit2/TestGitRepository
* 49322bb17d3acc9146f98c97d078513228bbf3c0 HEAD
* 0966a434eb1a025db6b71485ab63a3bfbea520b6 refs/heads/first-merge
* 49322bb17d3acc9146f98c97d078513228bbf3c0 refs/heads/master
* 42e4e7c5e507e113ebbb7801b16b52cf867b7ce1 refs/heads/no-parent
* d96c4e80345534eccee5ac7b07fc7603b56124cb refs/tags/annotated_tag
* c070ad8c08840c8116da865b2d65593a6bb9cd2a refs/tags/annotated_tag^{}
* 55a1a760df4b86a02094a904dfa511deb5655905 refs/tags/blob
* 8f50ba15d49353813cc6e20298002c0d17b0a9ee refs/tags/commit_tree
* 6e0c7bdb9b4ed93212491ee778ca1c65047cab4e refs/tags/nearly-dangling
*/
/// <summary>
/// Expected references on https://github.com/libgit2/TestGitRepository
/// </summary>
private static List<Tuple<string, string>> ExpectedRemoteRefs = new List<Tuple<string, string>>()
{
new Tuple<string, string>("HEAD", "49322bb17d3acc9146f98c97d078513228bbf3c0"),
new Tuple<string, string>("refs/heads/first-merge", "0966a434eb1a025db6b71485ab63a3bfbea520b6"),
new Tuple<string, string>("refs/heads/master", "49322bb17d3acc9146f98c97d078513228bbf3c0"),
new Tuple<string, string>("refs/heads/no-parent", "42e4e7c5e507e113ebbb7801b16b52cf867b7ce1"),
new Tuple<string, string>("refs/tags/annotated_tag", "d96c4e80345534eccee5ac7b07fc7603b56124cb"),
new Tuple<string, string>("refs/tags/annotated_tag^{}", "c070ad8c08840c8116da865b2d65593a6bb9cd2a"),
new Tuple<string, string>("refs/tags/blob", "55a1a760df4b86a02094a904dfa511deb5655905"),
new Tuple<string, string>("refs/tags/commit_tree", "8f50ba15d49353813cc6e20298002c0d17b0a9ee"),
new Tuple<string, string>("refs/tags/nearly-dangling", "6e0c7bdb9b4ed93212491ee778ca1c65047cab4e"),
};
}
}
14 changes: 14 additions & 0 deletions LibGit2Sharp/Core/GitRemoteHead.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
using System;
using System.Runtime.InteropServices;

namespace LibGit2Sharp.Core
{
[StructLayout(LayoutKind.Sequential)]
internal struct GitRemoteHead
{
public bool Local;
public GitOid Oid;
public GitOid Loid;
public IntPtr NamePtr;
}
}
5 changes: 5 additions & 0 deletions LibGit2Sharp/Core/NativeMethods.cs
Original file line number Diff line number Diff line change
Expand Up @@ -690,6 +690,11 @@ internal static extern void git_remote_set_cred_acquire_cb(
[DllImport(libgit2)]
internal static extern void git_remote_disconnect(RemoteSafeHandle remote);

[DllImport(libgit2)]
internal static extern int git_remote_ls(RemoteSafeHandle remote, git_headlist_cb headlist_cb, IntPtr payload);

internal delegate int git_headlist_cb(ref GitRemoteHead remoteHeadPtr, IntPtr payload);

[DllImport(libgit2)]
internal static extern int git_remote_download(
RemoteSafeHandle remote,
Expand Down
9 changes: 9 additions & 0 deletions LibGit2Sharp/Core/Proxy.cs
Original file line number Diff line number Diff line change
Expand Up @@ -1270,6 +1270,15 @@ public static IList<string> git_remote_list(RepositorySafeHandle repo)
}
}

public static void git_remote_ls(RemoteSafeHandle remote, NativeMethods.git_headlist_cb headlist_cb)
{
using (ThreadAffinity())
{
int res = NativeMethods.git_remote_ls(remote, headlist_cb, IntPtr.Zero);
Ensure.ZeroResult(res);
}
}

public static RemoteSafeHandle git_remote_load(RepositorySafeHandle repo, string name, bool throwsIfNotFound)
{
using (ThreadAffinity())
Expand Down
1 change: 1 addition & 0 deletions LibGit2Sharp/LibGit2Sharp.csproj
Original file line number Diff line number Diff line change
Expand Up @@ -66,6 +66,7 @@
<Compile Include="CheckoutCallbacks.cs" />
<Compile Include="CheckoutOptions.cs" />
<Compile Include="Network.cs" />
<Compile Include="Core\GitRemoteHead.cs" />
<Compile Include="OrphanedHeadException.cs" />
<Compile Include="UnmergedIndexEntriesException.cs" />
<Compile Include="Commit.cs" />
Expand Down
37 changes: 37 additions & 0 deletions LibGit2Sharp/Network.cs
Original file line number Diff line number Diff line change
Expand Up @@ -52,6 +52,43 @@ public virtual RemoteCollection Remotes
get { return remotes.Value; }
}

/// <summary>
/// List references in a <see cref = "Remote" /> repository.
/// </summary>
/// <param name="remote">The <see cref = "Remote" /> to list from.</param>
/// <returns>The references in the <see cref = "Remote" /> repository.</returns>
public virtual IEnumerable<DirectReference> ListReferences(Remote remote)
{
Ensure.ArgumentNotNull(remote, "remote");

List<DirectReference> directReferences = new List<DirectReference>();
using (RemoteSafeHandle remoteHandle = Proxy.git_remote_load(repository.Handle, remote.Name, true))
{
Proxy.git_remote_connect(remoteHandle, GitDirection.Fetch);

NativeMethods.git_headlist_cb cb = (ref GitRemoteHead remoteHead, IntPtr payload) =>
{
// The name pointer should never be null - if it is,
// this indicates a bug somewhere (libgit2, server, etc).
if (remoteHead.NamePtr == IntPtr.Zero)
{
Proxy.giterr_set_str(GitErrorCategory.Invalid, "Not expecting null value for reference name.");
return -1;
}

ObjectId oid = new ObjectId(remoteHead.Oid);
string name = Utf8Marshaler.FromNative(remoteHead.NamePtr);
directReferences.Add(new DirectReference(name, this.repository, oid));

return 0;
};

Proxy.git_remote_ls(remoteHandle, cb);
}

return directReferences;
}

/// <summary>
/// Push the objectish to the destination reference on the <see cref = "Remote" />.
/// </summary>
Expand Down