Skip to content

Commit f68697b

Browse files
committed
Functionality to correctly handle Symbolic References
returned by remote ls
1 parent c7f10bb commit f68697b

File tree

6 files changed

+97
-34
lines changed

6 files changed

+97
-34
lines changed

‎LibGit2Sharp.Tests/NetworkFixture.cs‎

Lines changed: 23 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -22,19 +22,22 @@ public void CanListRemoteReferences(string url)
2222
using(varrepo=newRepository(repoPath))
2323
{
2424
Remoteremote=repo.Network.Remotes.Add(remoteName,url);
25-
IList<DirectReference>references=repo.Network.ListReferences(remote).ToList();
25+
IList<Reference>references=repo.Network.ListReferences(remote).ToList();
2626

27-
foreach(vardirectReferenceinreferences)
27+
28+
foreach(varreferenceinreferences)
2829
{
2930
// None of those references point to an existing
3031
// object in this brand new repository
31-
Assert.Null(directReference.Target);
32+
Assert.Null(reference.ResolveToDirectReference().Target);
3233
}
3334

3435
List<Tuple<string,string>>actualRefs=references.
35-
Select(directRef =>newTuple<string,string>(directRef.CanonicalName,directRef.TargetIdentifier)).ToList();
36+
Select(directRef =>newTuple<string,string>(directRef.CanonicalName,directRef.ResolveToDirectReference()
37+
.TargetIdentifier)).ToList();
3638

3739
Assert.Equal(TestRemoteRefs.ExpectedRemoteRefs.Count,actualRefs.Count);
40+
Assert.True(references.Single(reference =>reference.CanonicalName=="HEAD")isSymbolicReference);
3841
for(inti=0;i<TestRemoteRefs.ExpectedRemoteRefs.Count;i++)
3942
{
4043
Assert.Equal(TestRemoteRefs.ExpectedRemoteRefs[i].Item2,actualRefs[i].Item2);
@@ -53,19 +56,21 @@ public void CanListRemoteReferencesFromUrl(string url)
5356

5457
using(varrepo=newRepository(repoPath))
5558
{
56-
IList<DirectReference>references=repo.Network.ListReferences(url).ToList();
59+
IList<Reference>references=repo.Network.ListReferences(url).ToList();
5760

58-
foreach(vardirectReferenceinreferences)
61+
foreach(varreferenceinreferences)
5962
{
6063
// None of those references point to an existing
6164
// object in this brand new repository
62-
Assert.Null(directReference.Target);
65+
Assert.Null(reference.ResolveToDirectReference().Target);
6366
}
6467

6568
List<Tuple<string,string>>actualRefs=references.
66-
Select(directRef =>newTuple<string,string>(directRef.CanonicalName,directRef.TargetIdentifier)).ToList();
69+
Select(directRef =>newTuple<string,string>(directRef.CanonicalName,directRef.ResolveToDirectReference()
70+
.TargetIdentifier)).ToList();
6771

6872
Assert.Equal(TestRemoteRefs.ExpectedRemoteRefs.Count,actualRefs.Count);
73+
Assert.True(references.Single(reference =>reference.CanonicalName=="HEAD")isSymbolicReference);
6974
for(inti=0;i<TestRemoteRefs.ExpectedRemoteRefs.Count;i++)
7075
{
7176
Assert.Equal(TestRemoteRefs.ExpectedRemoteRefs[i].Item2,actualRefs[i].Item2);
@@ -87,18 +92,22 @@ public void CanListRemoteReferenceObjects()
8792
using(varrepo=newRepository(clonedRepoPath))
8893
{
8994
Remoteremote=repo.Network.Remotes[remoteName];
90-
IEnumerable<DirectReference>references=repo.Network.ListReferences(remote);
95+
IEnumerable<Reference>references=repo.Network.ListReferences(remote).ToList();
9196

9297
varactualRefs=newList<Tuple<string,string>>();
9398

94-
foreach(DirectReferencereferenceinreferences)
99+
foreach(Referencereferenceinreferences)
95100
{
96101
Assert.NotNull(reference.CanonicalName);
97-
Assert.NotNull(reference.Target);
98-
actualRefs.Add(newTuple<string,string>(reference.CanonicalName,reference.Target.Id.Sha));
102+
103+
vardirectReference=reference.ResolveToDirectReference();
104+
105+
Assert.NotNull(directReference.Target);
106+
actualRefs.Add(newTuple<string,string>(reference.CanonicalName,directReference.Target.Id.Sha));
99107
}
100108

101109
Assert.Equal(TestRemoteRefs.ExpectedRemoteRefs.Count,actualRefs.Count);
110+
Assert.True(references.Single(reference =>reference.CanonicalName=="HEAD")isSymbolicReference);
102111
for(inti=0;i<TestRemoteRefs.ExpectedRemoteRefs.Count;i++)
103112
{
104113
Assert.Equal(TestRemoteRefs.ExpectedRemoteRefs[i].Item1,actualRefs[i].Item1);
@@ -123,9 +132,9 @@ public void CanListRemoteReferencesWithCredentials()
123132

124133
varreferences=repo.Network.ListReferences(remote,Constants.PrivateRepoCredentials);
125134

126-
foreach(vardirectReferenceinreferences)
135+
foreach(varreferenceinreferences)
127136
{
128-
Assert.NotNull(directReference);
137+
Assert.NotNull(reference);
129138
}
130139
}
131140
}

‎LibGit2Sharp.Tests/PushFixture.cs‎

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -199,9 +199,9 @@ public void CanForcePush()
199199
privatestaticvoidAssertRemoteHeadTipEquals(IRepositorylocalRepo,stringsha)
200200
{
201201
varremoteReferences=localRepo.Network.ListReferences(localRepo.Network.Remotes.Single());
202-
DirectReferenceremoteHead=remoteReferences.Single(r =>r.CanonicalName=="HEAD");
202+
ReferenceremoteHead=remoteReferences.Single(r =>r.CanonicalName=="HEAD");
203203

204-
Assert.Equal(sha,remoteHead.TargetIdentifier);
204+
Assert.Equal(sha,remoteHead.ResolveToDirectReference().TargetIdentifier);
205205
}
206206

207207
privatevoidUpdateTheRemoteRepositoryWithANewCommit(stringremoteRepoPath)

‎LibGit2Sharp.Tests/RepositoryFixture.cs‎

Lines changed: 34 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -679,7 +679,7 @@ public void CanListRemoteReferencesWithCredentials()
679679
InconclusiveIf(()=>string.IsNullOrEmpty(Constants.PrivateRepoUrl),
680680
"Populate Constants.PrivateRepo* to run this test");
681681

682-
IEnumerable<DirectReference>references=Repository.ListRemoteReferences(Constants.PrivateRepoUrl,
682+
IEnumerable<Reference>references=Repository.ListRemoteReferences(Constants.PrivateRepoUrl,
683683
Constants.PrivateRepoCredentials);
684684

685685
foreach(varreferenceinreferences)
@@ -694,24 +694,49 @@ public void CanListRemoteReferencesWithCredentials()
694694
[InlineData("git://github.com/libgit2/TestGitRepository.git")]
695695
publicvoidCanListRemoteReferences(stringurl)
696696
{
697-
IEnumerable<DirectReference>references=Repository.ListRemoteReferences(url);
697+
IEnumerable<Reference>references=Repository.ListRemoteReferences(url).ToList();
698698

699699
List<Tuple<string,string>>actualRefs=references.
700-
Select(directRef=>newTuple<string,string>(directRef.CanonicalName,directRef.TargetIdentifier)).ToList();
700+
Select(reference=>newTuple<string,string>(reference.CanonicalName,reference.ResolveToDirectReference().TargetIdentifier)).ToList();
701701

702702
Assert.Equal(TestRemoteRefs.ExpectedRemoteRefs.Count,actualRefs.Count);
703+
Assert.True(references.Single(reference =>reference.CanonicalName=="HEAD")isSymbolicReference);
703704
for(inti=0;i<TestRemoteRefs.ExpectedRemoteRefs.Count;i++)
704705
{
705706
Assert.Equal(TestRemoteRefs.ExpectedRemoteRefs[i].Item2,actualRefs[i].Item2);
706707
Assert.Equal(TestRemoteRefs.ExpectedRemoteRefs[i].Item1,actualRefs[i].Item1);
707708
}
708709
}
709710

711+
[Fact]
712+
publicvoidCanListRemoteReferencesWithDetachedRemoteHead()
713+
{
714+
stringoriginalRepoPath=SandboxStandardTestRepo();
715+
716+
stringdetachedHeadSha;
717+
718+
using(varoriginalRepo=newRepository(originalRepoPath))
719+
{
720+
detachedHeadSha=originalRepo.Head.Tip.Sha;
721+
originalRepo.Checkout(detachedHeadSha);
722+
723+
Assert.True(originalRepo.Info.IsHeadDetached);
724+
}
725+
726+
IEnumerable<Reference>references=Repository.ListRemoteReferences(originalRepoPath);
727+
728+
Referencehead=references.SingleOrDefault(reference =>reference.CanonicalName=="HEAD");
729+
730+
Assert.NotNull(head);
731+
Assert.True(headisDirectReference);
732+
Assert.Equal(detachedHeadSha,head.TargetIdentifier);
733+
}
734+
710735
[Theory]
711736
[InlineData("http://github.com/libgit2/TestGitRepository")]
712737
publicvoidReadingReferenceRepositoryThroughListRemoteReferencesThrows(stringurl)
713738
{
714-
IEnumerable<DirectReference>references=Repository.ListRemoteReferences(url);
739+
IEnumerable<Reference>references=Repository.ListRemoteReferences(url);
715740

716741
foreach(varreferenceinreferences)
717742
{
@@ -724,11 +749,14 @@ public void ReadingReferenceRepositoryThroughListRemoteReferencesThrows(string u
724749
[InlineData("http://github.com/libgit2/TestGitRepository")]
725750
publicvoidReadingReferenceTargetFromListRemoteReferencesThrows(stringurl)
726751
{
727-
IEnumerable<DirectReference>references=Repository.ListRemoteReferences(url);
752+
IEnumerable<Reference>references=Repository.ListRemoteReferences(url);
728753

729754
foreach(varreferenceinreferences)
730755
{
731-
Assert.Throws<InvalidOperationException>(()=>reference.Target);
756+
Assert.Throws<InvalidOperationException>(()=>
757+
{
758+
vartarget=reference.ResolveToDirectReference().Target;
759+
});
732760
}
733761
}
734762
}

‎LibGit2Sharp/Core/Proxy.cs‎

Lines changed: 31 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -2147,7 +2147,7 @@ public static IList<string> git_remote_list(RepositorySafeHandle repo)
21472147
}
21482148
}
21492149

2150-
publicstaticIEnumerable<DirectReference>git_remote_ls(Repositoryrepository,RemoteSafeHandleremote)
2150+
publicstaticIEnumerable<Reference>git_remote_ls(Repositoryrepository,RemoteSafeHandleremote)
21512151
{
21522152
IntPtrheads;
21532153
UIntPtrcount;
@@ -2162,26 +2162,52 @@ public static IEnumerable<DirectReference> git_remote_ls(Repository repository,
21622162
thrownewOverflowException();
21632163
}
21642164

2165-
varrefs=newList<DirectReference>();
2165+
vardirectRefs=newDictionary<string,Reference>();
2166+
varsymRefs=newDictionary<string,string>();
2167+
21662168
IntPtrcurrentHead=heads;
21672169

21682170
for(inti=0;i<intCount;i++)
21692171
{
21702172
varremoteHead=Marshal.ReadIntPtr(currentHead).MarshalAs<GitRemoteHead>();
21712173

2174+
stringname=LaxUtf8Marshaler.FromNative(remoteHead.NamePtr);
2175+
stringsymRefTarget=LaxUtf8Marshaler.FromNative(remoteHead.SymRefTargetPtr);
2176+
21722177
// The name pointer should never be null - if it is,
21732178
// this indicates a bug somewhere (libgit2, server, etc).
2174-
if(remoteHead.NamePtr==IntPtr.Zero)
2179+
if(string.IsNullOrEmpty(name))
21752180
{
21762181
thrownewInvalidOperationException("Not expecting null value for reference name.");
21772182
}
21782183

2179-
stringname=LaxUtf8Marshaler.FromNative(remoteHead.NamePtr);
2180-
refs.Add(newDirectReference(name,repository,remoteHead.Oid));
2184+
if(!string.IsNullOrEmpty(symRefTarget))
2185+
{
2186+
symRefs.Add(name,symRefTarget);
2187+
}
2188+
else
2189+
{
2190+
directRefs.Add(name,newDirectReference(name,repository,remoteHead.Oid));
2191+
}
21812192

21822193
currentHead=IntPtr.Add(currentHead,IntPtr.Size);
21832194
}
21842195

2196+
for(inti=0;i<symRefs.Count;i++)
2197+
{
2198+
varsymRef=symRefs.ElementAt(i);
2199+
2200+
if(!directRefs.ContainsKey(symRef.Value))
2201+
{
2202+
thrownewInvalidOperationException("Symbolic reference target not found in direct reference results.");
2203+
}
2204+
2205+
directRefs.Add(symRef.Key,newSymbolicReference(repository,symRef.Key,symRef.Value,directRefs[symRef.Value]));
2206+
}
2207+
2208+
varrefs=directRefs.Values.ToList();
2209+
refs.Sort((r1,r2)=>String.CompareOrdinal(r1.CanonicalName,r2.CanonicalName));
2210+
21852211
returnrefs;
21862212
}
21872213

‎LibGit2Sharp/Network.cs‎

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -48,7 +48,7 @@ public virtual RemoteCollection Remotes
4848
/// </summary>
4949
/// <param name="remote">The <see cref="Remote"/> to list from.</param>
5050
/// <returns>The references in the <see cref="Remote"/> repository.</returns>
51-
publicvirtualIEnumerable<DirectReference>ListReferences(Remoteremote)
51+
publicvirtualIEnumerable<Reference>ListReferences(Remoteremote)
5252
{
5353
Ensure.ArgumentNotNull(remote,"remote");
5454

@@ -67,7 +67,7 @@ public virtual IEnumerable<DirectReference> ListReferences(Remote remote)
6767
/// <param name="remote">The <see cref="Remote"/> to list from.</param>
6868
/// <param name="credentialsProvider">The <see cref="Func{Credentials}"/> used to connect to remote repository.</param>
6969
/// <returns>The references in the <see cref="Remote"/> repository.</returns>
70-
publicvirtualIEnumerable<DirectReference>ListReferences(Remoteremote,CredentialsHandlercredentialsProvider)
70+
publicvirtualIEnumerable<Reference>ListReferences(Remoteremote,CredentialsHandlercredentialsProvider)
7171
{
7272
Ensure.ArgumentNotNull(remote,"remote");
7373
Ensure.ArgumentNotNull(credentialsProvider,"credentialsProvider");
@@ -86,7 +86,7 @@ public virtual IEnumerable<DirectReference> ListReferences(Remote remote, Creden
8686
/// </summary>
8787
/// <param name="url">The url to list from.</param>
8888
/// <returns>The references in the remote repository.</returns>
89-
publicvirtualIEnumerable<DirectReference>ListReferences(stringurl)
89+
publicvirtualIEnumerable<Reference>ListReferences(stringurl)
9090
{
9191
Ensure.ArgumentNotNull(url,"url");
9292

@@ -105,15 +105,15 @@ public virtual IEnumerable<DirectReference> ListReferences(string url)
105105
/// <param name="url">The url to list from.</param>
106106
/// <param name="credentialsProvider">The <see cref="Func{Credentials}"/> used to connect to remote repository.</param>
107107
/// <returns>The references in the remote repository.</returns>
108-
publicvirtualIEnumerable<DirectReference>ListReferences(stringurl,CredentialsHandlercredentialsProvider)
108+
publicvirtualIEnumerable<Reference>ListReferences(stringurl,CredentialsHandlercredentialsProvider)
109109
{
110110
Ensure.ArgumentNotNull(url,"url");
111111
Ensure.ArgumentNotNull(credentialsProvider,"credentialsProvider");
112112

113113
returnListReferencesInternal(url,credentialsProvider);
114114
}
115115

116-
privateIEnumerable<DirectReference>ListReferencesInternal(stringurl,CredentialsHandlercredentialsProvider)
116+
privateIEnumerable<Reference>ListReferencesInternal(stringurl,CredentialsHandlercredentialsProvider)
117117
{
118118
using(RemoteSafeHandleremoteHandle=BuildRemoteSafeHandle(repository.Handle,url))
119119
{

‎LibGit2Sharp/Repository.cs‎

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -563,7 +563,7 @@ internal Commit LookupCommit(string committish)
563563
/// </para>
564564
/// <param name="url">The url to list from.</param>
565565
/// <returns>The references in the remote repository.</returns>
566-
publicstaticIEnumerable<DirectReference>ListRemoteReferences(stringurl)
566+
publicstaticIEnumerable<Reference>ListRemoteReferences(stringurl)
567567
{
568568
returnListRemoteReferences(url,null);
569569
}
@@ -579,7 +579,7 @@ public static IEnumerable<DirectReference> ListRemoteReferences(string url)
579579
/// <param name="url">The url to list from.</param>
580580
/// <param name="credentialsProvider">The <see cref="Func{Credentials}"/> used to connect to remote repository.</param>
581581
/// <returns>The references in the remote repository.</returns>
582-
publicstaticIEnumerable<DirectReference>ListRemoteReferences(stringurl,CredentialsHandlercredentialsProvider)
582+
publicstaticIEnumerable<Reference>ListRemoteReferences(stringurl,CredentialsHandlercredentialsProvider)
583583
{
584584
Ensure.ArgumentNotNull(url,"url");
585585

0 commit comments

Comments
(0)