diff --git a/LibGit2Sharp.Tests/NetworkFixture.cs b/LibGit2Sharp.Tests/NetworkFixture.cs
index 3a3517432..5e25bc12b 100644
--- a/LibGit2Sharp.Tests/NetworkFixture.cs
+++ b/LibGit2Sharp.Tests/NetworkFixture.cs
@@ -8,6 +8,44 @@ namespace LibGit2Sharp.Tests
{
public class NetworkFixture : BaseFixture
{
+ [Theory]
+ [InlineData("http://github.com/libgit2/TestGitRepository")]
+ [InlineData("https://github.com/libgit2/TestGitRepository")]
+ public void CanFetchDefaultBranchName(string url)
+ {
+ string remoteName = "testRemote";
+
+ string expectedDefaultBranchName = TestRemoteRefs.ExpectedRemoteRefs
+ .First(remoteRef => remoteRef.Item3).Item1;
+
+ string repoPath = InitNewRepository();
+
+ using (var repo = new Repository(repoPath))
+ {
+ Remote remote = repo.Network.Remotes.Add(remoteName, url);
+
+ string defaultBranchName = repo.Network.DefaultBranchName(remote);
+ Assert.Equal(expectedDefaultBranchName, defaultBranchName);
+ }
+ }
+
+ [Theory]
+ [InlineData("http://github.com/libgit2/TestGitRepository")]
+ [InlineData("https://github.com/libgit2/TestGitRepository")]
+ public void CanFetchDefaultBranchNameFromUrl(string url)
+ {
+ string expectedDefaultBranchName = TestRemoteRefs.ExpectedRemoteRefs
+ .First(remoteRef => remoteRef.Item3).Item1;
+
+ string repoPath = InitNewRepository();
+
+ using (var repo = new Repository(repoPath))
+ {
+ string defaultBranchName = repo.Network.DefaultBranchName(url);
+ Assert.Equal(expectedDefaultBranchName, defaultBranchName);
+ }
+ }
+
[Theory]
[InlineData("http://github.com/libgit2/TestGitRepository")]
[InlineData("https://github.com/libgit2/TestGitRepository")]
diff --git a/LibGit2Sharp.Tests/TestHelpers/TestRemoteRefs.cs b/LibGit2Sharp.Tests/TestHelpers/TestRemoteRefs.cs
index a3e1e58c4..a2aa34029 100644
--- a/LibGit2Sharp.Tests/TestHelpers/TestRemoteRefs.cs
+++ b/LibGit2Sharp.Tests/TestHelpers/TestRemoteRefs.cs
@@ -20,17 +20,17 @@ public class TestRemoteRefs
///
/// Expected references on http://github.com/libgit2/TestGitRepository
///
- public static List> ExpectedRemoteRefs = new List>()
+ 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"),
+ new Tuple("HEAD", "49322bb17d3acc9146f98c97d078513228bbf3c0", false),
+ new Tuple("refs/heads/first-merge", "0966a434eb1a025db6b71485ab63a3bfbea520b6", false),
+ new Tuple("refs/heads/master", "49322bb17d3acc9146f98c97d078513228bbf3c0", true),
+ new Tuple("refs/heads/no-parent", "42e4e7c5e507e113ebbb7801b16b52cf867b7ce1", false),
+ new Tuple("refs/tags/annotated_tag", "d96c4e80345534eccee5ac7b07fc7603b56124cb", false),
+ new Tuple("refs/tags/annotated_tag^{}", "c070ad8c08840c8116da865b2d65593a6bb9cd2a", false),
+ new Tuple("refs/tags/blob", "55a1a760df4b86a02094a904dfa511deb5655905", false),
+ new Tuple("refs/tags/commit_tree", "8f50ba15d49353813cc6e20298002c0d17b0a9ee", false),
+ new Tuple("refs/tags/nearly-dangling", "6e0c7bdb9b4ed93212491ee778ca1c65047cab4e", false),
};
}
}
diff --git a/LibGit2Sharp/Core/NativeMethods.cs b/LibGit2Sharp/Core/NativeMethods.cs
index f5d45f3cf..567ef4ccb 100644
--- a/LibGit2Sharp/Core/NativeMethods.cs
+++ b/LibGit2Sharp/Core/NativeMethods.cs
@@ -1391,6 +1391,9 @@ internal static extern unsafe int git_remote_create_with_fetchspec(
[MarshalAs(UnmanagedType.CustomMarshaler, MarshalCookie = UniqueId.UniqueIdentifier, MarshalTypeRef = typeof(StrictUtf8Marshaler))] string url,
[MarshalAs(UnmanagedType.CustomMarshaler, MarshalCookie = UniqueId.UniqueIdentifier, MarshalTypeRef = typeof(StrictUtf8Marshaler))] string refspec);
+ [DllImport(libgit2, CallingConvention = CallingConvention.Cdecl)]
+ internal static extern unsafe int git_remote_default_branch(GitBuf buf, git_remote* remote);
+
[DllImport(libgit2, CallingConvention = CallingConvention.Cdecl)]
internal static extern unsafe int git_remote_delete(
git_repository* repo,
diff --git a/LibGit2Sharp/Core/Proxy.cs b/LibGit2Sharp/Core/Proxy.cs
index 50cefc0df..2fa0150cd 100644
--- a/LibGit2Sharp/Core/Proxy.cs
+++ b/LibGit2Sharp/Core/Proxy.cs
@@ -2179,6 +2179,23 @@ public static unsafe void git_remote_connect(RemoteHandle remote, GitDirection d
}
}
+ public static unsafe string git_remote_default_branch(RemoteHandle remote)
+ {
+ using (var buf = new GitBuf())
+ {
+ int res = NativeMethods.git_remote_default_branch(buf, remote);
+
+ if (res == (int)GitErrorCode.NotFound)
+ {
+ return null;
+ }
+
+ Ensure.ZeroResult(res);
+
+ return LaxUtf8Marshaler.FromNative(buf.ptr) ?? string.Empty;
+ }
+ }
+
public static unsafe void git_remote_delete(RepositoryHandle repo, string name)
{
int res = NativeMethods.git_remote_delete(repo, name);
diff --git a/LibGit2Sharp/Network.cs b/LibGit2Sharp/Network.cs
index d5f032058..718e8a098 100644
--- a/LibGit2Sharp/Network.cs
+++ b/LibGit2Sharp/Network.cs
@@ -37,6 +37,76 @@ public virtual RemoteCollection Remotes
get { return remotes.Value; }
}
+ ///
+ /// Lookup the default branch name in a Remote repository
+ ///
+ /// to get the default branch from.
+ /// The canonical name of the Remote repository's default branch.
+ public virtual string DefaultBranchName(Remote remote)
+ {
+ Ensure.ArgumentNotNull(remote, "remote");
+
+ return DefaultBranchNameInternal(remote.Url, null);
+ }
+
+ ///
+ /// Lookup the default branch name in a Remote repository
+ ///
+ /// to get the default branch from.
+ /// used to connect to the remote repository.
+ /// The canonical name of the Remote repository's default branch.
+ public virtual string DefaultBranchName(Remote remote, CredentialsHandler credentialsProvider)
+ {
+ Ensure.ArgumentNotNull(remote, "remote");
+ Ensure.ArgumentNotNull(credentialsProvider, "credentialsProvider");
+
+ return DefaultBranchNameInternal(remote.Url, credentialsProvider);
+ }
+
+ ///
+ /// Lookup the default branch name in a Remote repository
+ ///
+ ///
+ /// The canonical name of the Remote repository's default branch.
+ public virtual string DefaultBranchName(string url)
+ {
+ Ensure.ArgumentNotNull(url, "url");
+
+ return DefaultBranchNameInternal(url, null);
+ }
+
+ ///
+ /// Lookup the default branch name in a Remote repository
+ ///
+ ///
+ /// used to connect to the remote repository.
+ /// The canonical name of the Remote repository's default branch.
+ public virtual string DefaultBranchName(string url, CredentialsHandler credentialsProvider)
+ {
+ Ensure.ArgumentNotNull(url, "url");
+ Ensure.ArgumentNotNull(credentialsProvider, "credentialsProvider");
+
+ return DefaultBranchNameInternal(url, credentialsProvider);
+ }
+
+ private string DefaultBranchNameInternal(string url, CredentialsHandler credentialsProvider)
+ {
+ using (RemoteHandle remoteHandle = BuildRemoteHandle(repository.Handle, url))
+ {
+ GitRemoteCallbacks gitCallbacks = new GitRemoteCallbacks { version = 1 };
+ GitProxyOptions proxyOptions = new GitProxyOptions { Version = 1 };
+
+ if (credentialsProvider != null)
+ {
+ var callbacks = new RemoteCallbacks(credentialsProvider);
+ gitCallbacks = callbacks.GenerateCallbacks();
+ }
+
+ Proxy.git_remote_connect(remoteHandle, GitDirection.Fetch, ref gitCallbacks, ref proxyOptions);
+ return Proxy.git_remote_default_branch(remoteHandle);
+ }
+ }
+
///
/// List references in a repository.
///