Skip to content

Commit 1b820a5

Browse files
committed
Branch.Remote property should not throw
The Branch.Remote property can throw when it attempts to resolve a remote for a remote-tracking branch, and the remote cannot be found or is ambiguous. In those situations, Branch.Remote should return null. If there is a need for the specific exception to be returned, we can look at transitioning to a method for this functionality.
1 parent bf93cba commit 1b820a5

File tree

4 files changed

+80
-10
lines changed

4 files changed

+80
-10
lines changed

LibGit2Sharp.Tests/BranchFixture.cs

Lines changed: 58 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -391,6 +391,64 @@ public void QueryUpstreamBranchCanonicalNameForLocalTrackingBranch()
391391
}
392392
}
393393

394+
[Fact]
395+
public void QueryRemoteForRemoteBranch()
396+
{
397+
using (var repo = new Repository(StandardTestRepoPath))
398+
{
399+
var master = repo.Branches["origin/master"];
400+
Assert.Equal(repo.Network.Remotes["origin"], master.Remote);
401+
}
402+
}
403+
404+
[Fact]
405+
public void QueryUnresolvableRemoteForRemoteBranch()
406+
{
407+
var path = CloneStandardTestRepo();
408+
409+
var fetchRefSpecs = new string[] { "+refs/heads/notfound/*:refs/remotes/origin/notfound/*" };
410+
411+
using (var repo = InitIsolatedRepository(path))
412+
{
413+
// Update the remote config such that the remote for a
414+
// remote branch cannot be resolved
415+
Remote remote = repo.Network.Remotes["origin"];
416+
Assert.NotNull(remote);
417+
418+
repo.Network.Remotes.Update(remote, r => r.FetchRefSpecs = fetchRefSpecs);
419+
420+
Branch branch = repo.Branches["refs/remotes/origin/master"];
421+
422+
Assert.NotNull(branch);
423+
Assert.True(branch.IsRemote);
424+
425+
Assert.Null(branch.Remote);
426+
}
427+
}
428+
429+
[Fact]
430+
public void QueryAmbigousRemoteForRemoteBranch()
431+
{
432+
var path = CloneStandardTestRepo();
433+
434+
var fetchRefSpec = "+refs/heads/*:refs/remotes/origin/*";
435+
var url = "http://github.com/libgit2/TestGitRepository";
436+
437+
using (var repo = InitIsolatedRepository(path))
438+
{
439+
// Add a second remote so that it is ambiguous which remote
440+
// the remote-tracking branch tracks.
441+
repo.Network.Remotes.Add("ambiguous", url, fetchRefSpec);
442+
443+
Branch branch = repo.Branches["refs/remotes/origin/master"];
444+
445+
Assert.NotNull(branch);
446+
Assert.True(branch.IsRemote);
447+
448+
Assert.Null(branch.Remote);
449+
}
450+
}
451+
394452
[Fact]
395453
public void CanLookupABranchByItsCanonicalName()
396454
{

LibGit2Sharp/Branch.cs

Lines changed: 12 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -149,7 +149,13 @@ public virtual string UpstreamBranchCanonicalName
149149
}
150150

151151
/// <summary>
152-
/// Gets the configured <see cref="Remote"/> to fetch from and push to.
152+
/// Get the remote for the branch.
153+
/// <para>
154+
/// If this is a local branch, this will return the configured
155+
/// <see cref="Remote"/> to fetch from and push to. If this is a
156+
/// remote-tracking branch, this will return the remote containing
157+
/// the tracked branch.
158+
/// </para>
153159
/// </summary>
154160
public virtual Remote Remote
155161
{
@@ -164,11 +170,11 @@ public virtual Remote Remote
164170
else
165171
{
166172
remoteName = RemoteNameFromLocalBranch();
173+
}
167174

168-
if (remoteName == null)
169-
{
170-
return null;
171-
}
175+
if (remoteName == null)
176+
{
177+
return null;
172178
}
173179

174180
return repo.Network.Remotes[remoteName];
@@ -210,7 +216,7 @@ private string RemoteNameFromLocalBranch()
210216

211217
private string RemoteNameFromRemoteTrackingBranch()
212218
{
213-
return Proxy.git_branch_remote_name(repo.Handle, CanonicalName);
219+
return Proxy.git_branch_remote_name(repo.Handle, CanonicalName, false);
214220
}
215221

216222
/// <summary>

LibGit2Sharp/BranchUpdater.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -181,7 +181,7 @@ private void GetUpstreamInformation(string canonicalName, out string remoteName,
181181
}
182182
else if (canonicalName.LooksLikeRemoteTrackingBranch())
183183
{
184-
remoteName = Proxy.git_branch_remote_name(repo.Handle, canonicalName);
184+
remoteName = Proxy.git_branch_remote_name(repo.Handle, canonicalName, true);
185185

186186
Remote remote = repo.Network.Remotes.RemoteForName(remoteName);
187187
mergeBranchName = remote.FetchSpecTransformToSource(canonicalName);

LibGit2Sharp/Core/Proxy.cs

Lines changed: 9 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -203,15 +203,21 @@ public static ReferenceSafeHandle git_branch_move(ReferenceSafeHandle reference,
203203
}
204204
}
205205

206-
public static string git_branch_remote_name(RepositorySafeHandle repo, string canonical_branch_name)
206+
public static string git_branch_remote_name(RepositorySafeHandle repo, string canonical_branch_name, bool shouldThrowIfNotFound)
207207
{
208208
using (ThreadAffinity())
209209
using (var buf = new GitBuf())
210210
{
211211
int res = NativeMethods.git_branch_remote_name(buf, repo, canonical_branch_name);
212-
Ensure.Int32Result(res);
213212

214-
return LaxUtf8Marshaler.FromNative(buf.ptr) ?? string.Empty;
213+
if (!shouldThrowIfNotFound &&
214+
(res == (int) GitErrorCode.NotFound || res == (int) GitErrorCode.Ambiguous))
215+
{
216+
return null;
217+
}
218+
219+
Ensure.ZeroResult(res);
220+
return LaxUtf8Marshaler.FromNative(buf.ptr);
215221
}
216222
}
217223

0 commit comments

Comments
 (0)