8000 Move AheadBy/BehindBy into new TrackingDetails · gitextensions/libgit2sharp@8caf13c · GitHub
[go: up one dir, main page]

Skip to content

Commit 8caf13c

Browse files
committed
Move AheadBy/BehindBy into new TrackingDetails
Also removes common ancestor check for AheadBy/BehindBy to align with git.git behavior. Fixes libgit2#301.
1 parent 69582c4 commit 8caf13c

File tree

5 files changed

+157
-48
lines changed

5 files changed

+157
-48
lines changed

LibGit2Sharp.Tests/BranchFixture.cs

Lines changed: 44 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -355,10 +355,13 @@ public void CanGetInformationFromUnbornBranch()
355355
Assert.Null(head.Tip);
356356
Assert.Null(head["huh?"]);
357357

358-
Assert.Null(head.AheadBy);
359-
Assert.Null(head.BehindBy);
360358
Assert.False(head.IsTracking);
361359
Assert.Null(head.TrackedBranch);
360+
361+
Assert.NotNull(head.TrackingDetails);
362+
Assert.Null(head.TrackingDetails.AheadBy);
363+
Assert.Null(head.TrackingDetails.BehindBy);
364+
Assert.Null(head.TrackingDetails.CommonAncestor);
362365
}
363366
}
364367

@@ -372,9 +375,12 @@ public void CanGetTrackingInformationFromBranchSharingNoHistoryWithItsTrackedBra
372375
repo.Refs.UpdateTarget("refs/remotes/origin/master", "origin/test");
373376

374377
Assert.True(master.IsTracking);
375-
Assert.Null(master.AheadBy);
376-
Assert.Null(master.BehindBy);
377378
Assert.NotNull(master.TrackedBranch);
379+
380+
Assert.NotNull(master.TrackingDetails);
381+
Assert.Equal(9, master.TrackingDetails.AheadBy);
382+
Assert.Equal(2, master.TrackingDetails.BehindBy);
383+
Assert.Null(repo.Head.TrackingDetails.CommonAncestor);
378384
}
379385
}
380386

@@ -386,8 +392,11 @@ public void TrackingInformationIsEmptyForNonTrackingBranch()
386392
Branch branch = repo.Branches["test"];
387393
Assert.False(branch.IsTracking);
388394
Assert.Null(branch.TrackedBranch);
389-
Assert.Null(branch.AheadBy);
390-
Assert.Null(branch.BehindBy);
395+
396+
Assert.NotNull(branch.TrackingDetails);
397+
Assert.Null(branch.TrackingDetails.AheadBy);
398+
Assert.Null(branch.TrackingDetails.BehindBy);
399+
Assert.Null(branch.TrackingDetails.CommonAncestor);
391400
}
392401
}
393402

@@ -399,8 +408,11 @@ public void CanGetTrackingInformationForTrackingBranch()
399408
Branch master = repo.Branches["master"];
400409
Assert.True(master.IsTracking);
401410
Assert.Equal(repo.Branches["refs/remotes/origin/master"], master.TrackedBranch);
402-
Assert.Equal(2, master.AheadBy);
403-
Assert.Equal(2, master.BehindBy);
411+
412+
Assert.NotNull(master.TrackingDetails);
413+
Assert.Equal(2, master.TrackingDetails.AheadBy);
414+
Assert.Equal(2, master.TrackingDetails.BehindBy);
415+
Assert.Equal(repo.Lookup<Commit>("4c062a6"), master.TrackingDetails.CommonAncestor);
404416
}
405417
}
406418

@@ -412,8 +424,11 @@ public void CanGetTrackingInformationForLocalTrackingBranch()
412424
var branch = repo.Branches["track-local"];
413425
Assert.True(branch.IsTracking);
414426
Assert.Equal(repo.Branches["master"], branch.TrackedBranch);
415-
Assert.Equal(2, branch.AheadBy);
416-
Assert.Equal(2, branch.BehindBy);
427+
428+
Assert.NotNull(branch.TrackingDetails);
429+
Assert.Equal(2, branch.TrackingDetails.AheadBy);
430+
Assert.Equal(2, branch.TrackingDetails.BehindBy);
431+
Assert.Equal(repo.Lookup<Commit>("4c062a6"), branch.TrackingDetails.CommonAncestor);
417432
}
418433
}
419434

@@ -752,6 +767,11 @@ public void DetachedHeadIsNotATrackingBranch()
752767

753768
Assert.False(repo.Head.IsTracking);
754769
Assert.Null(repo.Head.TrackedBranch);
770+
771+
Assert.NotNull(repo.Head.TrackingDetails);
772+
Assert.Null(repo.Head.TrackingDetails.AheadBy);
773+
Assert.Null(repo.Head.TrackingDetails.BehindBy);
774+
Assert.Null(repo.Head.TrackingDetails.CommonAncestor);
755775
}
756776
}
757777

@@ -776,8 +796,10 @@ public void TrackedBranchExistsFromDefaultConfigInEmptyClone()
776796
Assert.NotNull(repo.Head.TrackedBranch);
777797
Assert.Null(repo.Head.TrackedBranch.Tip);
778798

779-
Assert.Null(repo.Head.AheadBy);
780-
Assert.Null(repo.Head.BehindBy);
799+
Assert.NotNull(repo.Head.TrackingDetails);
800+
Assert.Null(repo.Head.TrackingDetails.AheadBy);
801+
Assert.Null(repo.Head.TrackingDetails.BehindBy);
802+
Assert.Null(repo.Head.TrackingDetails.CommonAncestor);
781803

782804
Assert.NotNull(repo.Head.Remote);
783805
Assert.Equal("origin", repo.Head.Remote.Name);
@@ -788,9 +810,12 @@ public void TrackedBranchExistsFromDefaultConfigInEmptyClone()
788810

789811
Assert.NotNull(repo.Head.Tip);
790812
Assert.NotNull(repo.Head.TrackedBranch);
813+
Assert.Null(repo.Head.TrackedBranch.Tip);
791814

792-
Assert.Null(repo.Head.AheadBy);
793-
Assert.Null(repo.Head.BehindBy);
815+
Assert.NotNull(repo.Head.TrackingDetails);
816+
Assert.Null(repo.Head.TrackingDetails.AheadBy);
817+
Assert.Null(repo.Head.TrackingDetails.BehindBy);
818+
Assert.Null(repo.Head.TrackingDetails.CommonAncestor);
794819
}
795820
}
796821

@@ -807,8 +832,11 @@ public void RemoteBranchesDoNotTrackAnything()
807832
Assert.NotNull(branch.Remote);
808833
Assert.False(branch.IsTracking);
809834
Assert.Null(branch.TrackedBranch);
810-
Assert.Null(branch.AheadBy);
811-
Assert.Null(branch.BehindBy);
835+
836+
Assert.NotNull(branch.TrackingDetails);
837+
Assert.Null(branch.TrackingDetails.AheadBy);
838+
Assert.Null(branch.TrackingDetails.BehindBy);
839+
Assert.Null(branch.TrackingDetails.CommonAncestor);
812840
}
813841
}
814842
}

LibGit2Sharp/Branch.cs

Lines changed: 16 additions & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -94,48 +94,36 @@ public virtual bool IsTracking
9494
get { return TrackedBranch != null; }
9595
}
9696

97-
private bool ExistsPathToTrackedBranch()
98-
{
99-
if (!IsTracking)
100-
{
101-
return false;
102-
}
103-
104-
if (Tip == null || TrackedBranch.Tip == null)
105-
{
106-
return false;
107-
}
108-
109-
if (repo.Commits.FindCommonAncestor(Tip, TrackedBranch.Tip) == null)
110-
{
111-
return false;
112-
}
113-
114-
return true;
115-
}
116-
11797
/// <summary>
118-
/// 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.
98+
/// Gets the number of commits that exist in this local branch but don't exist in the tracked one.
11999
/// <para>
120-
/// 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
121-
/// not share a common ancestor.
100+
/// This property will return null if there is no tracked branch linked to this local branch.
122101
/// </para>
123102
/// </summary>
103+
[Obsolete("This property will be removed in the next release. Please use TrackingDetails.AheadBy instead.")]
124104
public virtual int? AheadBy
125105
{
126-
get { return ExistsPathToTrackedBranch() ? Proxy.git_graph_ahead_behind(repo.Handle, TrackedBranch.Tip.Id, Tip.Id).Item1 : (int?)null; }
106+
get { return TrackingDetails.AheadBy; }
127107
}
128108

129109
/// <summary>
130-
/// 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.
110+
/// Gets the number of commits that exist in the tracked branch but don't exist in this local one.
131111
/// <para>
132-
/// 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
133-
/// not share a common ancestor.
112+
/// This property will return null if there is no tracked branch linked to this local branch.
134113
/// </para>
135114
/// </summary>
115+
[Obsolete("This property will be removed in the next release. Please use TrackingDetails.BehindBy instead.")]
136116
public virtual int? BehindBy
137117
{
138-
get { return ExistsPathToTrackedBranch() ? Proxy.git_graph_ahead_behind(repo.Handle, TrackedBranch.Tip.Id, Tip.Id).Item2 : (int?)null; }
118+
get { return TrackingDetails.BehindBy; }
119+
}
120+
121+
/// <summary>
122+
/// Gets additional information about the tracked branch.
123+
/// </summary>
124+
public virtual BranchTrackingDetails TrackingDetails
125+
{
126+
get { return new BranchTrackingDetails(repo, this); }
139127
}
140128

141129
/// <summary>

LibGit2Sharp/BranchTrackingDetails.cs

Lines changed: 87 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,87 @@
1+
using LibGit2Sharp.Core;
2+
using LibGit2Sharp.Core.Compat;
3+
4+
namespace LibGit2Sharp
5+
{
6+
/// <summary>
7+
/// Tracking information for a <see cref="Branch" />
8+
/// </summary>
9+
public class BranchTrackingDetails
10+
{
11+
private readonly Repository repo;
12+
private readonly Branch branch;
13+
private readonly Lazy<Tuple<int?, int?>> aheadBehind;
14+
private readonly Lazy<Commit> commonAncestor;
15+
16+
/// <summary>
17+
/// Needed for mocking purposes.
18+
/// </summary>
19+
protected BranchTrackingDetails()
20+
{ }
21+
22+
internal BranchTrackingDetails(Repository repo, Branch branch)
23+
{
24+
this.repo = repo;
25+
this.branch = branch;
26+
27+
aheadBehind = new Lazy<Tuple<int?, int?>>(ResolveAheadBehind);
28+
commonAncestor = new Lazy<Commit>(ResolveCommonAncestor);
29+
}
30+
31+
/// <summary>
32+
/// Gets the number of commits that exist in this local branch but don't exist in the tracked one.
33+
/// <para>
34+
/// This property will return null if there is no tracked branch linked to this local branch.
35+ /// </para>
36+
/// </summary>
37+
public virtual int? AheadBy
38+
{
39+
get { return aheadBehind.Value.Item1; }
40+
}
41+
42+
/// <summary>
43+
/// Gets the number of commits that exist in the tracked branch but don't exist in this local one.
44+
/// <para>
45+
/// This property will return null if there is no tracked branch linked to this local branch.
46+
/// </para>
47+
/// </summary>
48+
public virtual int? BehindBy
49+
{
50+
get { return aheadBehind.Value.Item2; }
51+
}
52+
53+
/// <summary>
54+
/// Gets the common ancestor of the local branch and its tracked remote branch.
55+
/// <para>
56+
/// This property will return null if there is no tracked branch linked to this local branch,
57+
/// or if either branch is an orphan.
58+
/// </para>
59+
/// </summary>
60+
public virtual Commit CommonAncestor
61+
{
62+
get { return commonAncestor.Value; }
63+
}
64+
65+
private Tuple<int?, int?> ResolveAheadBehind()
66+
{
67+
return branch.IsTracking
68+
? Proxy.git_graph_ahead_behind(repo.Handle, branch.TrackedBranch.Tip, branch.Tip)
69+
: new Tuple<int?, int?>(null, null);
70+
}
71+
72+
private Commit ResolveCommonAncestor()
73+
{
74+
if (!branch.IsTracking)
75+
{
76+
return null;
77+
}
78+
79+
if (branch.Tip == null || branch.TrackedBranch.Tip == null)
80+
{
81+
return null;
82+
}
83+
84+
return repo.Commits.FindCommonAncestor(branch.Tip, branch.TrackedBranch.Tip);
85+
}
86+
}
87+
}

LibGit2Sharp/Core/Proxy.cs

Lines changed: 9 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -604,10 +604,15 @@ public static DiffListSafeHandle git_diff_tree_to_workdir(
604604

605605
#region git_graph_
606606

607-
public static Tuple<int, int> git_graph_ahead_behind(RepositorySafeHandle repo, ObjectId firstId, ObjectId secondId)
607+
public static Tuple<int?, int?> git_graph_ahead_behind(RepositorySafeHandle repo, Commit first, Commit second)
608608
{
609-
GitOid oid1 = firstId.Oid;
610-
GitOid oid2 = secondId.Oid;
609+
if (first == null || second == null)
610+
{
611+
return new Tuple<int?, int?>(null, null);
612+
}
613+
614+
GitOid oid1 = first.Id.Oid;
615+
GitOid oid2 = second.Id.Oid;
611616

612617
using (ThreadAffinity())
613618
{
@@ -618,7 +623,7 @@ public static Tuple<int, int> git_graph_ahead_behind(RepositorySafeHandle repo,
618623

619624
Ensure.ZeroResult(res);
620625

621-
return new Tuple<int, int>((int)ahead, (int)behind);
626+
return new Tuple<int?, int?>((int)ahead, (int)behind);
622627
}
623628
}
624629

LibGit2Sharp/LibGit2Sharp.csproj

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -62,6 +62,7 @@
6262
<Compile Include="Branch.cs" />
6363
<Compile Include="BranchCollection.cs" />
6464
<Compile Include="BranchCollectionExtensions.cs" />
65+
<Compile Include="BranchTrackingDetails.cs" />
6566
<Compile Include="BranchUpdater.cs" />
6667
<Compile Include="Changes.cs" />
6768
<Compile Include="CheckoutCallbacks.cs" />

0 commit comments

Comments
 (0)
0