diff --git a/LibGit2Sharp.Tests/LibGit2Sharp.Tests.csproj b/LibGit2Sharp.Tests/LibGit2Sharp.Tests.csproj
index 6a700f01c..a92d7ff41 100644
--- a/LibGit2Sharp.Tests/LibGit2Sharp.Tests.csproj
+++ b/LibGit2Sharp.Tests/LibGit2Sharp.Tests.csproj
@@ -124,6 +124,7 @@
+
diff --git a/LibGit2Sharp.Tests/NetworkFixture.cs b/LibGit2Sharp.Tests/NetworkFixture.cs
index f146a0678..d93273d1c 100644
--- a/LibGit2Sharp.Tests/NetworkFixture.cs
+++ b/LibGit2Sharp.Tests/NetworkFixture.cs
@@ -34,11 +34,11 @@ public void CanListRemoteReferences(string url)
List> actualRefs = references.
Select(directRef => new Tuple(directRef.CanonicalName, directRef.TargetIdentifier)).ToList();
- Assert.Equal(ExpectedRemoteRefs.Count, actualRefs.Count);
- for (int i = 0; i < ExpectedRemoteRefs.Count; i++)
+ Assert.Equal(TestRemoteRefs.ExpectedRemoteRefs.Count, actualRefs.Count);
+ for (int i = 0; i < TestRemoteRefs.ExpectedRemoteRefs.Count; i++)
{
- Assert.Equal(ExpectedRemoteRefs[i].Item2, actualRefs[i].Item2);
- Assert.Equal(ExpectedRemoteRefs[i].Item1, actualRefs[i].Item1);
+ Assert.Equal(TestRemoteRefs.ExpectedRemoteRefs[i].Item2, actualRefs[i].Item2);
+ Assert.Equal(TestRemoteRefs.ExpectedRemoteRefs[i].Item1, actualRefs[i].Item1);
}
}
}
@@ -65,11 +65,11 @@ public void CanListRemoteReferencesFromUrl(string url)
List> actualRefs = references.
Select(directRef => new Tuple(directRef.CanonicalName, directRef.TargetIdentifier)).ToList();
- Assert.Equal(ExpectedRemoteRefs.Count, actualRefs.Count);
- for (int i = 0; i < ExpectedRemoteRefs.Count; i++)
+ Assert.Equal(TestRemoteRefs.ExpectedRemoteRefs.Count, actualRefs.Count);
+ for (int i = 0; i < TestRemoteRefs.ExpectedRemoteRefs.Count; i++)
{
- Assert.Equal(ExpectedRemoteRefs[i].Item2, actualRefs[i].Item2);
- Assert.Equal(ExpectedRemoteRefs[i].Item1, actualRefs[i].Item1);
+ Assert.Equal(TestRemoteRefs.ExpectedRemoteRefs[i].Item2, actualRefs[i].Item2);
+ Assert.Equal(TestRemoteRefs.ExpectedRemoteRefs[i].Item1, actualRefs[i].Item1);
}
}
}
@@ -98,11 +98,11 @@ public void CanListRemoteReferenceObjects()
actualRefs.Add(new Tuple(reference.CanonicalName, reference.Target.Id.Sha));
}
- Assert.Equal(ExpectedRemoteRefs.Count, actualRefs.Count);
- for (int i = 0; i < ExpectedRemoteRefs.Count; i++)
+ Assert.Equal(TestRemoteRefs.ExpectedRemoteRefs.Count, actualRefs.Count);
+ for (int i = 0; i < TestRemoteRefs.ExpectedRemoteRefs.Count; i++)
{
- Assert.Equal(ExpectedRemoteRefs[i].Item1, actualRefs[i].Item1);
- Assert.Equal(ExpectedRemoteRefs[i].Item2, actualRefs[i].Item2);
+ Assert.Equal(TestRemoteRefs.ExpectedRemoteRefs[i].Item1, actualRefs[i].Item1);
+ Assert.Equal(TestRemoteRefs.ExpectedRemoteRefs[i].Item2, actualRefs[i].Item2);
}
}
}
@@ -254,33 +254,5 @@ public void CanMergeFetchedRefs()
Assert.Equal(mergeResult.Status, MergeStatus.NonFastForward);
}
}
-
- /*
- * git ls-remote http://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
- */
- ///
- /// Expected references on http://github.com/libgit2/TestGitRepository
- ///
- private static List> ExpectedRemoteRefs = new List>()
- {
- new Tuple("HEAD", "49322bb17d3acc9146f98c97d078513228bbf3c0"),
- new Tuple("refs/heads/first-merge", "0966a434eb1a025db6b71485ab63a3bfbea520b6"),
- new Tuple("refs/heads/master", "49322bb17d3acc9146f98c97d078513228bbf3c0"),
- new Tuple("refs/heads/no-parent", "42e4e7c5e507e113ebbb7801b16b52cf867b7ce1"),
- new Tuple("refs/tags/annotated_tag", "d96c4e80345534eccee5ac7b07fc7603b56124cb"),
- new Tuple("refs/tags/annotated_tag^{}", "c070ad8c08840c8116da865b2d65593a6bb9cd2a"),
- new Tuple("refs/tags/blob", "55a1a760df4b86a02094a904dfa511deb5655905"),
- new Tuple("refs/tags/commit_tree", "8f50ba15d49353813cc6e20298002c0d17b0a9ee"),
- new Tuple("refs/tags/nearly-dangling", "6e0c7bdb9b4ed93212491ee778ca1c65047cab4e"),
- };
}
}
diff --git a/LibGit2Sharp.Tests/RepositoryFixture.cs b/LibGit2Sharp.Tests/RepositoryFixture.cs
index 381973348..6f05029de 100644
--- a/LibGit2Sharp.Tests/RepositoryFixture.cs
+++ b/LibGit2Sharp.Tests/RepositoryFixture.cs
@@ -4,6 +4,7 @@
using System.Linq;
using LibGit2Sharp.Tests.TestHelpers;
using Xunit;
+using Xunit.Extensions;
namespace LibGit2Sharp.Tests
{
@@ -651,5 +652,64 @@ public void CanDetectShallowness()
Assert.False(repo.Info.IsShallow);
}
}
+
+ [SkippableFact]
+ public void CanListRemoteReferencesWithCredentials()
+ {
+ InconclusiveIf(() => string.IsNullOrEmpty(Constants.PrivateRepoUrl),
+ "Populate Constants.PrivateRepo* to run this test");
+
+ IEnumerable references = Repository.ListRemoteReferences(Constants.PrivateRepoUrl,
+ Constants.PrivateRepoCredentials);
+
+ foreach (var reference in references)
+ {
+ Assert.NotNull(reference);
+ }
+ }
+
+ [Theory]
+ [InlineData("http://github.com/libgit2/TestGitRepository")]
+ [InlineData("https://github.com/libgit2/TestGitRepository")]
+ [InlineData("git://github.com/libgit2/TestGitRepository.git")]
+ public void CanListRemoteReferences(string url)
+ {
+ IEnumerable references = Repository.ListRemoteReferences(url);
+
+ List> actualRefs = references.
+ Select(directRef => new Tuple(directRef.CanonicalName, directRef.TargetIdentifier)).ToList();
+
+ Assert.Equal(TestRemoteRefs.ExpectedRemoteRefs.Count, actualRefs.Count);
+ 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);
+ }
+ }
+
+ [Theory]
+ [InlineData("http://github.com/libgit2/TestGitRepository")]
+ public void ReadingReferenceRepositoryThroughListRemoteReferencesThrows(string url)
+ {
+ IEnumerable references = Repository.ListRemoteReferences(url);
+
+ foreach (var reference in references)
+ {
+ IBelongToARepository repositoryReference = reference;
+ Assert.Throws(() => repositoryReference.Repository);
+ }
+ }
+
+ [Theory]
+ [InlineData("http://github.com/libgit2/TestGitRepository")]
+ public void ReadingReferenceTargetFromListRemoteReferencesThrows(string url)
+ {
+ IEnumerable references = Repository.ListRemoteReferences(url);
+
+ foreach (var reference in references)
+ {
+ Assert.Throws(() => reference.Target);
+ }
+ }
}
}
diff --git a/LibGit2Sharp.Tests/TestHelpers/TestRemoteRefs.cs b/LibGit2Sharp.Tests/TestHelpers/TestRemoteRefs.cs
new file mode 100644
index 000000000..aafdd5f34
--- /dev/null
+++ b/LibGit2Sharp.Tests/TestHelpers/TestRemoteRefs.cs
@@ -0,0 +1,38 @@
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+
+namespace LibGit2Sharp.Tests.TestHelpers
+{
+ public class TestRemoteRefs
+ {
+ /*
+ * git ls-remote http://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
+ */
+ ///
+ /// Expected references on http://github.com/libgit2/TestGitRepository
+ ///
+ public static List> ExpectedRemoteRefs = new List>()
+ {
+ new Tuple("HEAD", "49322bb17d3acc9146f98c97d078513228bbf3c0"),
+ new Tuple("refs/heads/first-merge", "0966a434eb1a025db6b71485ab63a3bfbea520b6"),
+ new Tuple("refs/heads/master", "49322bb17d3acc9146f98c97d078513228bbf3c0"),
+ new Tuple("refs/heads/no-parent", "42e4e7c5e507e113ebbb7801b16b52cf867b7ce1"),
+ new Tuple("refs/tags/annotated_tag", "d96c4e80345534eccee5ac7b07fc7603b56124cb"),
+ new Tuple("refs/tags/annotated_tag^{}", "c070ad8c08840c8116da865b2d65593a6bb9cd2a"),
+ new Tuple("refs/tags/blob", "55a1a760df4b86a02094a904dfa511deb5655905"),
+ new Tuple("refs/tags/commit_tree", "8f50ba15d49353813cc6e20298002c0d17b0a9ee"),
+ new Tuple("refs/tags/nearly-dangling", "6e0c7bdb9b4ed93212491ee778ca1c65047cab4e"),
+ };
+ }
+}
diff --git a/LibGit2Sharp/Core/NativeMethods.cs b/LibGit2Sharp/Core/NativeMethods.cs
index 9b4e818f3..d7ccd749e 100644
--- a/LibGit2Sharp/Core/NativeMethods.cs
+++ b/LibGit2Sharp/Core/NativeMethods.cs
@@ -1285,6 +1285,9 @@ internal static extern int git_repository_state(
[return: MarshalAs(UnmanagedType.CustomMarshaler, MarshalCookie = UniqueId.UniqueIdentifier, MarshalTypeRef = typeof(LaxFilePathNoCleanupMarshaler))]
internal static extern FilePath git_repository_workdir(RepositorySafeHandle repository);
+ [DllImport(libgit2)]
+ internal static extern int git_repository_new(out RepositorySafeHandle repo);
+
[DllImport(libgit2)]
internal static extern int git_reset(
RepositorySafeHandle repo,
diff --git a/LibGit2Sharp/Core/Proxy.cs b/LibGit2Sharp/Core/Proxy.cs
index 65a389a08..e107dbb53 100644
--- a/LibGit2Sharp/Core/Proxy.cs
+++ b/LibGit2Sharp/Core/Proxy.cs
@@ -2167,6 +2167,16 @@ public static RepositorySafeHandle git_repository_open(string path)
return repo;
}
+ public static RepositorySafeHandle git_repository_new()
+ {
+ RepositorySafeHandle repo;
+ int res = NativeMethods.git_repository_new(out repo);
+
+ Ensure.ZeroResult(res);
+
+ return repo;
+ }
+
public static void git_repository_open_ext(string path, RepositoryOpenFlags flags, string ceilingDirs)
{
int res;
diff --git a/LibGit2Sharp/DirectReference.cs b/LibGit2Sharp/DirectReference.cs
index 00de258a6..b9cc304b3 100644
--- a/LibGit2Sharp/DirectReference.cs
+++ b/LibGit2Sharp/DirectReference.cs
@@ -18,12 +18,21 @@ protected DirectReference()
internal DirectReference(string canonicalName, IRepository repo, ObjectId targetId)
: base(repo, canonicalName, targetId.Sha)
{
- targetBuilder = new Lazy(() => repo.Lookup(targetId));
+ targetBuilder = new Lazy(() =>
+ {
+ if (repo == null)
+ {
+ throw new InvalidOperationException("Target requires a local repository");
+ }
+
+ return repo.Lookup(targetId);
+ });
}
///
/// Gets the target of this
///
+ /// Throws if Local Repository is not set.
public virtual GitObject Target
{
get { return targetBuilder.Value; }
diff --git a/LibGit2Sharp/Reference.cs b/LibGit2Sharp/Reference.cs
index 5b0787ede..35cf7b286 100644
--- a/LibGit2Sharp/Reference.cs
+++ b/LibGit2Sharp/Reference.cs
@@ -199,6 +199,17 @@ private string DebuggerDisplay
}
}
- IRepository IBelongToARepository.Repository { get { return repo; } }
+ IRepository IBelongToARepository.Repository
+ {
+ get
+ {
+ if (repo == null)
+ {
+ throw new InvalidOperationException("Repository requires a local repository");
+ }
+
+ return repo;
+ }
+ }
}
}
diff --git a/LibGit2Sharp/Repository.cs b/LibGit2Sharp/Repository.cs
index 79c9077bc..e269113cf 100644
--- a/LibGit2Sharp/Repository.cs
+++ b/LibGit2Sharp/Repository.cs
@@ -545,6 +545,52 @@ internal Commit LookupCommit(string committish)
LookUpOptions.ThrowWhenCanNotBeDereferencedToACommit);
}
+ ///
+ /// Lists the Remote Repository References.
+ ///
+ ///
+ /// Does not require a local Repository. The retrieved
+ ///
+ /// throws in this case.
+ ///
+ /// The url to list from.
+ /// The references in the remote repository.
+ public static IEnumerable ListRemoteReferences(string url)
+ {
+ return ListRemoteReferences(url, null);
+ }
+
+ ///
+ /// Lists the Remote Repository References.
+ ///
+ ///
+ /// Does not require a local Repository. The retrieved
+ ///
+ /// throws in this case.
+ ///
+ /// The url to list from.
+ /// The used to connect to remote repository.
+ /// The references in the remote repository.
+ public static IEnumerable ListRemoteReferences(string url, CredentialsHandler credentialsProvider)
+ {
+ Ensure.ArgumentNotNull(url, "url");
+
+ using (RepositorySafeHandle repositoryHandle = Proxy.git_repository_new())
+ using (RemoteSafeHandle remoteHandle = Proxy.git_remote_create_anonymous(repositoryHandle, url))
+ {
+ var gitCallbacks = new GitRemoteCallbacks { version = 1 };
+
+ if (credentialsProvider != null)
+ {
+ var callbacks = new RemoteCallbacks(credentialsProvider);
+ gitCallbacks = callbacks.GenerateCallbacks();
+ }
+
+ Proxy.git_remote_connect(remoteHandle, GitDirection.Fetch, ref gitCallbacks);
+ return Proxy.git_remote_ls(null, remoteHandle);
+ }
+ }
+
///
/// Probe for a git repository.
/// The lookup start from and walk upward parent directories if nothing has been found.