Skip to content

Commit 57b3d10

Browse files
committed
Add support for unborn branches
Fixes #216
1 parent c8f1f00 commit 57b3d10

File tree

2 files changed

+80
-12
lines changed

2 files changed

+80
-12
lines changed

LibGit2Sharp.Tests/BranchFixture.cs

Lines changed: 40 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -280,6 +280,44 @@ public void LookingOutABranchByNameWithBadParamsThrows()
280280
}
281281
}
282282

283+
public void CanGetInformationFromUnbornBranch()
284+
{
285+
SelfCleaningDirectory scd = BuildSelfCleaningDirectory();
286+
using (var repo = Repository.Init(scd.DirectoryPath, true))
287+
{
288+
var head = repo.Head;
289+
290+
Assert.Equal("refs/heads/master", head.CanonicalName);
291+
Assert.Equal(0, head.Commits.Count());
292+
Assert.True(head.IsCurrentRepositoryHead);
293+
Assert.False(head.IsRemote);
294+
Assert.Equal("master", head.Name);
295+
Assert.Null(head.Tip);
296+
Assert.Null(head["huh?"]);
297+
298+
Assert.Null(head.AheadBy);
299+
Assert.Null(head.BehindBy);
300+
Assert.False(head.IsTracking);
301+
Assert.Null(head.TrackedBranch);
302+
}
303+
}
304+
305+
[Fact]
306+
public void CanGetTrackingInformationFromBranchSharingNoHistoryWithItsTrackedBranch()
307+
{
308+
TemporaryCloneOfTestRepo path = BuildTemporaryCloneOfTestRepo(StandardTestRepoWorkingDirPath);
309+
using (var repo = new Repository(path.RepositoryPath))
310+
{
311+
Branch master = repo.Branches["master"];
312+
repo.Refs.UpdateTarget("refs/remotes/origin/master", "origin/test");
313+
314+
Assert.True(master.IsTracking);
315+
Assert.Null(master.AheadBy);
316+
Assert.Null(master.BehindBy);
317+
Assert.NotNull(master.TrackedBranch);
318+
}
319+
}
320+
283321
[Fact]
284322
public void TrackingInformationIsEmptyForNonTrackingBranch()
285323
{
@@ -288,8 +326,8 @@ public void TrackingInformationIsEmptyForNonTrackingBranch()
288326
Branch branch = repo.Branches["test"];
289327
Assert.False(branch.IsTracking);
290328
Assert.Null(branch.TrackedBranch);
291-
Assert.Equal(0, branch.AheadBy);
292-
Assert.Equal(0, branch.BehindBy);
329+
Assert.Null(branch.AheadBy);
330+
Assert.Null(branch.BehindBy);
293331
}
294332
}
295333

LibGit2Sharp/Branch.cs

Lines changed: 40 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -80,7 +80,7 @@ public virtual bool IsRemote
8080
}
8181

8282
/// <summary>
83-
/// Gets the remote branch which is connected to this local one.
83+
/// Gets the remote branch which is connected to this local one, or null if there is none.
8484
/// </summary>
8585
public virtual Branch TrackedBranch
8686
{
@@ -95,20 +95,43 @@ public virtual bool IsTracking
9595
get { return TrackedBranch != null; }
9696
}
9797

98+
private bool ExistsPathToTrackedBranch()
99+
{
100+
if (!IsTracking)
101+
{
102+
return false;
103+
}
104+
105+
if (repo.Commits.FindCommonAncestor(Tip, TrackedBranch.Tip) == null)
106+
{
107+
return false;
108+
}
109+
110+
return true;
111+
}
112+
98113
/// <summary>
99114
/// Gets the number of commits, starting from the <see cref="Tip"/>, that have been performed on this local branch and aren't known from the remote one.
115+
/// <para>
116+
/// This property will return null if there is no remote branch linked to this local branch, or if the remote branch and the local branch do
117+
/// not share a common ancestor.
118+
/// </para>
100119
/// </summary>
101-
public virtual int AheadBy
120+
public virtual int? AheadBy
102121
{
103-
get { return IsTracking ? repo.Commits.QueryBy(new Filter { Since = Tip, Until = TrackedBranch }).Count() : 0; }
122+
get { return ExistsPathToTrackedBranch() ? repo.Commits.QueryBy(new Filter { Since = Tip, Until = TrackedBranch }).Count() : (int?)null; }
104123
}
105124

106125
/// <summary>
107126
/// Gets the number of commits that exist in the remote branch, on top of <see cref="Tip"/>, and aren't known from the local one.
127+
/// <para>
128+
/// This property will return null if there is no remote branch linked to this local branch, or if the remote branch and the local branch do
129+
/// not share a common ancestor.
130+
/// </para>
108131
/// </summary>
109-
public virtual int BehindBy
132+
public virtual int? BehindBy
110133
{
111-
get { return IsTracking ? repo.Commits.QueryBy(new Filter { Since = TrackedBranch, Until = Tip }).Count() : 0; }
134+
get { return ExistsPathToTrackedBranch() ? repo.Commits.QueryBy(new Filter { Since = TrackedBranch, Until = Tip }).Count() : (int?)null; }
112135
}
113136

114137
/// <summary>
@@ -140,16 +163,23 @@ public virtual ICommitLog Commits
140163

141164
private Branch ResolveTrackedBranch()
142165
{
143-
using (ReferenceSafeHandle branchPtr = repo.Refs.RetrieveReferencePtr(CanonicalName))
144-
using (ReferenceSafeHandle referencePtr = Proxy.git_branch_tracking(branchPtr))
166+
using (ReferenceSafeHandle branchPtr = repo.Refs.RetrieveReferencePtr(CanonicalName, false))
145167
{
146-
if (referencePtr == null)
168+
if (branchPtr == null)
147169
{
148170
return null;
149171
}
150172

151-
var reference = Reference.BuildFromPtr<Reference>(referencePtr, repo);
152-
return repo.Branches[reference.CanonicalName];
173+
using (ReferenceSafeHandle referencePtr = Proxy.git_branch_tracking(branchPtr))
174+
{
175+
if (referencePtr == null)
176+
{
177+
return null;
178+
}
179+
180+
var reference = Reference.BuildFromPtr<Reference>(referencePtr, repo);
181+
return repo.Branches[reference.CanonicalName];
182+
}
153183
}
154184
}
155185

0 commit comments

Comments
 (0)