Skip to content

Commit

Permalink
Merge pull request libgit2#1132 from psawey/remotels-symref
Browse files Browse the repository at this point in the history
Remote LS able to handle Symbolic References
  • Loading branch information
nulltoken committed Jul 17, 2015
2 parents c7f10bb + f68697b commit f4a6001
Show file tree
Hide file tree
Showing 6 changed files with 97 additions and 34 deletions.
37 changes: 23 additions & 14 deletions LibGit2Sharp.Tests/NetworkFixture.cs
Original file line number Diff line number Diff line change
Expand Up @@ -22,19 +22,22 @@ public void CanListRemoteReferences(string url)
using (var repo = new Repository(repoPath))
{
Remote remote = repo.Network.Remotes.Add(remoteName, url);
IList<DirectReference> references = repo.Network.ListReferences(remote).ToList();
IList<Reference> references = repo.Network.ListReferences(remote).ToList();

foreach (var directReference in references)

foreach (var reference in references)
{
// None of those references point to an existing
// object in this brand new repository
Assert.Null(directReference.Target);
Assert.Null(reference.ResolveToDirectReference().Target);
}

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

Assert.Equal(TestRemoteRefs.ExpectedRemoteRefs.Count, actualRefs.Count);
Assert.True(references.Single(reference => reference.CanonicalName == "HEAD") is SymbolicReference);
for (int i = 0; i < TestRemoteRefs.ExpectedRemoteRefs.Count; i++)
{
Assert.Equal(TestRemoteRefs.ExpectedRemoteRefs[i].Item2, actualRefs[i].Item2);
Expand All @@ -53,19 +56,21 @@ public void CanListRemoteReferencesFromUrl(string url)

using (var repo = new Repository(repoPath))
{
IList<DirectReference> references = repo.Network.ListReferences(url).ToList();
IList<Reference> references = repo.Network.ListReferences(url).ToList();

foreach (var directReference in references)
foreach (var reference in references)
{
// None of those references point to an existing
// object in this brand new repository
Assert.Null(directReference.Target);
Assert.Null(reference.ResolveToDirectReference().Target);
}

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

Assert.Equal(TestRemoteRefs.ExpectedRemoteRefs.Count, actualRefs.Count);
Assert.True(references.Single(reference => reference.CanonicalName == "HEAD") is SymbolicReference);
for (int i = 0; i < TestRemoteRefs.ExpectedRemoteRefs.Count; i++)
{
Assert.Equal(TestRemoteRefs.ExpectedRemoteRefs[i].Item2, actualRefs[i].Item2);
Expand All @@ -87,18 +92,22 @@ public void CanListRemoteReferenceObjects()
using (var repo = new Repository(clonedRepoPath))
{
Remote remote = repo.Network.Remotes[remoteName];
IEnumerable<DirectReference> references = repo.Network.ListReferences(remote);
IEnumerable<Reference> references = repo.Network.ListReferences(remote).ToList();

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

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

var directReference = reference.ResolveToDirectReference();

Assert.NotNull(directReference.Target);
actualRefs.Add(new Tuple<string, string>(reference.CanonicalName, directReference.Target.Id.Sha));
}

Assert.Equal(TestRemoteRefs.ExpectedRemoteRefs.Count, actualRefs.Count);
Assert.True(references.Single(reference => reference.CanonicalName == "HEAD") is SymbolicReference);
for (int i = 0; i < TestRemoteRefs.ExpectedRemoteRefs.Count; i++)
{
Assert.Equal(TestRemoteRefs.ExpectedRemoteRefs[i].Item1, actualRefs[i].Item1);
Expand All @@ -123,9 +132,9 @@ public void CanListRemoteReferencesWithCredentials()

var references = repo.Network.ListReferences(remote, Constants.PrivateRepoCredentials);

foreach (var directReference in references)
foreach (var reference in references)
{
Assert.NotNull(directReference);
Assert.NotNull(reference);
}
}
}
Expand Down
4 changes: 2 additions & 2 deletions LibGit2Sharp.Tests/PushFixture.cs
Original file line number Diff line number Diff line change
Expand Up @@ -199,9 +199,9 @@ public void CanForcePush()
private static void AssertRemoteHeadTipEquals(IRepository localRepo, string sha)
{
var remoteReferences = localRepo.Network.ListReferences(localRepo.Network.Remotes.Single());
DirectReference remoteHead = remoteReferences.Single(r => r.CanonicalName == "HEAD");
Reference remoteHead = remoteReferences.Single(r => r.CanonicalName == "HEAD");

Assert.Equal(sha, remoteHead.TargetIdentifier);
Assert.Equal(sha, remoteHead.ResolveToDirectReference().TargetIdentifier);
}

private void UpdateTheRemoteRepositoryWithANewCommit(string remoteRepoPath)
Expand Down
40 changes: 34 additions & 6 deletions LibGit2Sharp.Tests/RepositoryFixture.cs
Original file line number Diff line number Diff line change
Expand Up @@ -679,7 +679,7 @@ public void CanListRemoteReferencesWithCredentials()
InconclusiveIf(() => string.IsNullOrEmpty(Constants.PrivateRepoUrl),
"Populate Constants.PrivateRepo* to run this test");

IEnumerable<DirectReference> references = Repository.ListRemoteReferences(Constants.PrivateRepoUrl,
IEnumerable<Reference> references = Repository.ListRemoteReferences(Constants.PrivateRepoUrl,
Constants.PrivateRepoCredentials);

foreach (var reference in references)
Expand All @@ -694,24 +694,49 @@ public void CanListRemoteReferencesWithCredentials()
[InlineData("git:https://github.com/libgit2/TestGitRepository.git")]
public void CanListRemoteReferences(string url)
{
IEnumerable<DirectReference> references = Repository.ListRemoteReferences(url);
IEnumerable<Reference> references = Repository.ListRemoteReferences(url).ToList();

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

Assert.Equal(TestRemoteRefs.ExpectedRemoteRefs.Count, actualRefs.Count);
Assert.True(references.Single(reference => reference.CanonicalName == "HEAD") is SymbolicReference);
for (int i = 0; i < TestRemoteRefs.ExpectedRemoteRefs.Count; i++)
{
Assert.Equal(TestRemoteRefs.ExpectedRemoteRefs[i].Item2, actualRefs[i].Item2);
Assert.Equal(TestRemoteRefs.ExpectedRemoteRefs[i].Item1, actualRefs[i].Item1);
}
}

[Fact]
public void CanListRemoteReferencesWithDetachedRemoteHead()
{
string originalRepoPath = SandboxStandardTestRepo();

string detachedHeadSha;

using (var originalRepo = new Repository(originalRepoPath))
{
detachedHeadSha = originalRepo.Head.Tip.Sha;
originalRepo.Checkout(detachedHeadSha);

Assert.True(originalRepo.Info.IsHeadDetached);
}

IEnumerable<Reference> references = Repository.ListRemoteReferences(originalRepoPath);

Reference head = references.SingleOrDefault(reference => reference.CanonicalName == "HEAD");

Assert.NotNull(head);
Assert.True(head is DirectReference);
Assert.Equal(detachedHeadSha, head.TargetIdentifier);
}

[Theory]
[InlineData("http:https://github.com/libgit2/TestGitRepository")]
public void ReadingReferenceRepositoryThroughListRemoteReferencesThrows(string url)
{
IEnumerable<DirectReference> references = Repository.ListRemoteReferences(url);
IEnumerable<Reference> references = Repository.ListRemoteReferences(url);

foreach (var reference in references)
{
Expand All @@ -724,11 +749,14 @@ public void ReadingReferenceRepositoryThroughListRemoteReferencesThrows(string u
[InlineData("http:https://github.com/libgit2/TestGitRepository")]
public void ReadingReferenceTargetFromListRemoteReferencesThrows(string url)
{
IEnumerable<DirectReference> references = Repository.ListRemoteReferences(url);
IEnumerable<Reference> references = Repository.ListRemoteReferences(url);

foreach (var reference in references)
{
Assert.Throws<InvalidOperationException>(() => reference.Target);
Assert.Throws<InvalidOperationException>(() =>
{
var target = reference.ResolveToDirectReference().Target;
});
}
}
}
Expand Down
36 changes: 31 additions & 5 deletions LibGit2Sharp/Core/Proxy.cs
Original file line number Diff line number Diff line change
Expand Up @@ -2147,7 +2147,7 @@ public static IList<string> git_remote_list(RepositorySafeHandle repo)
}
}

public static IEnumerable<DirectReference> git_remote_ls(Repository repository, RemoteSafeHandle remote)
public static IEnumerable<Reference> git_remote_ls(Repository repository, RemoteSafeHandle remote)
{
IntPtr heads;
UIntPtr count;
Expand All @@ -2162,26 +2162,52 @@ public static IEnumerable<DirectReference> git_remote_ls(Repository repository,
throw new OverflowException();
}

var refs = new List<DirectReference>();
var directRefs = new Dictionary<string, Reference>();
var symRefs = new Dictionary<string, string>();

IntPtr currentHead = heads;

for (int i = 0; i < intCount; i++)
{
var remoteHead = Marshal.ReadIntPtr(currentHead).MarshalAs<GitRemoteHead>();

string name = LaxUtf8Marshaler.FromNative(remoteHead.NamePtr);
string symRefTarget = LaxUtf8Marshaler.FromNative(remoteHead.SymRefTargetPtr);

// The name pointer should never be null - if it is,
// this indicates a bug somewhere (libgit2, server, etc).
if (remoteHead.NamePtr == IntPtr.Zero)
if (string.IsNullOrEmpty(name))
{
throw new InvalidOperationException("Not expecting null value for reference name.");
}

string name = LaxUtf8Marshaler.FromNative(remoteHead.NamePtr);
refs.Add(new DirectReference(name, repository, remoteHead.Oid));
if (!string.IsNullOrEmpty(symRefTarget))
{
symRefs.Add(name, symRefTarget);
}
else
{
directRefs.Add(name, new DirectReference(name, repository, remoteHead.Oid));
}

currentHead = IntPtr.Add(currentHead, IntPtr.Size);
}

for (int i = 0; i < symRefs.Count; i++)
{
var symRef = symRefs.ElementAt(i);

if (!directRefs.ContainsKey(symRef.Value))
{
throw new InvalidOperationException("Symbolic reference target not found in direct reference results.");
}

directRefs.Add(symRef.Key, new SymbolicReference(repository, symRef.Key, symRef.Value, directRefs[symRef.Value]));
}

var refs = directRefs.Values.ToList();
refs.Sort((r1, r2) => String.CompareOrdinal(r1.CanonicalName, r2.CanonicalName));

return refs;
}

Expand Down
10 changes: 5 additions & 5 deletions LibGit2Sharp/Network.cs
Original file line number Diff line number Diff line change
Expand Up @@ -48,7 +48,7 @@ public virtual RemoteCollection Remotes
/// </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)
public virtual IEnumerable<Reference> ListReferences(Remote remote)
{
Ensure.ArgumentNotNull(remote, "remote");

Expand All @@ -67,7 +67,7 @@ public virtual IEnumerable<DirectReference> ListReferences(Remote remote)
/// <param name="remote">The <see cref="Remote"/> to list from.</param>
/// <param name="credentialsProvider">The <see cref="Func{Credentials}"/> used to connect to remote repository.</param>
/// <returns>The references in the <see cref="Remote"/> repository.</returns>
public virtual IEnumerable<DirectReference> ListReferences(Remote remote, CredentialsHandler credentialsProvider)
public virtual IEnumerable<Reference> ListReferences(Remote remote, CredentialsHandler credentialsProvider)
{
Ensure.ArgumentNotNull(remote, "remote");
Ensure.ArgumentNotNull(credentialsProvider, "credentialsProvider");
Expand All @@ -86,7 +86,7 @@ public virtual IEnumerable<DirectReference> ListReferences(Remote remote, Creden
/// </summary>
/// <param name="url">The url to list from.</param>
/// <returns>The references in the remote repository.</returns>
public virtual IEnumerable<DirectReference> ListReferences(string url)
public virtual IEnumerable<Reference> ListReferences(string url)
{
Ensure.ArgumentNotNull(url, "url");

Expand All @@ -105,15 +105,15 @@ public virtual IEnumerable<DirectReference> ListReferences(string url)
/// <param name="url">The url to list from.</param>
/// <param name="credentialsProvider">The <see cref="Func{Credentials}"/> used to connect to remote repository.</param>
/// <returns>The references in the remote repository.</returns>
public virtual IEnumerable<DirectReference> ListReferences(string url, CredentialsHandler credentialsProvider)
public virtual IEnumerable<Reference> ListReferences(string url, CredentialsHandler credentialsProvider)
{
Ensure.ArgumentNotNull(url, "url");
Ensure.ArgumentNotNull(credentialsProvider, "credentialsProvider");

return ListReferencesInternal(url, credentialsProvider);
}

private IEnumerable<DirectReference> ListReferencesInternal(string url, CredentialsHandler credentialsProvider)
private IEnumerable<Reference> ListReferencesInternal(string url, CredentialsHandler credentialsProvider)
{
using (RemoteSafeHandle remoteHandle = BuildRemoteSafeHandle(repository.Handle, url))
{
Expand Down
4 changes: 2 additions & 2 deletions LibGit2Sharp/Repository.cs
Original file line number Diff line number Diff line change
Expand Up @@ -563,7 +563,7 @@ internal Commit LookupCommit(string committish)
/// </para>
/// <param name="url">The url to list from.</param>
/// <returns>The references in the remote repository.</returns>
public static IEnumerable<DirectReference> ListRemoteReferences(string url)
public static IEnumerable<Reference> ListRemoteReferences(string url)
{
return ListRemoteReferences(url, null);
}
Expand All @@ -579,7 +579,7 @@ public static IEnumerable<DirectReference> ListRemoteReferences(string url)
/// <param name="url">The url to list from.</param>
/// <param name="credentialsProvider">The <see cref="Func{Credentials}"/> used to connect to remote repository.</param>
/// <returns>The references in the remote repository.</returns>
public static IEnumerable<DirectReference> ListRemoteReferences(string url, CredentialsHandler credentialsProvider)
public static IEnumerable<Reference> ListRemoteReferences(string url, CredentialsHandler credentialsProvider)
{
Ensure.ArgumentNotNull(url, "url");

Expand Down

0 comments on commit f4a6001

Please sign in to comment.