Skip to content

Add IBelongToARepository #806

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 2 commits into from
Sep 6, 2014
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions LibGit2Sharp.Tests/BranchFixture.cs
Original file line number Diff line number Diff line change
Expand Up @@ -75,6 +75,7 @@ public void CanCreateAnUnbornBranch()
// The branch now exists...
Branch orphan = repo.Branches["orphan"];
Assert.NotNull(orphan);
AssertBelongsToARepository(repo, orphan);

// ...and points to that newly created commit
Assert.Equal(c, orphan.Tip);
Expand Down Expand Up @@ -489,6 +490,7 @@ public void CanGetTrackingInformationFromBranchSharingNoHistoryWithItsTrackedBra

Assert.True(master.IsTracking);
Assert.NotNull(master.TrackedBranch);
AssertBelongsToARepository(repo, master.TrackedBranch);

Assert.NotNull(master.TrackingDetails);
Assert.Equal(9, master.TrackingDetails.AheadBy);
Expand Down
3 changes: 3 additions & 0 deletions LibGit2Sharp.Tests/CheckoutFixture.cs
Original file line number Diff line number Diff line change
Expand Up @@ -32,9 +32,11 @@ public void CanCheckoutAnExistingBranch(string branchName)

Branch branch = repo.Branches[branchName];
Assert.NotNull(branch);
AssertBelongsToARepository(repo, branch);

Branch test = repo.Checkout(branch);
Assert.False(repo.Info.IsHeadDetached);
AssertBelongsToARepository(repo, test);

Assert.False(test.IsRemote);
Assert.True(test.IsCurrentRepositoryHead);
Expand Down Expand Up @@ -114,6 +116,7 @@ public void CanCheckoutAnArbitraryCommit(string commitPointer, bool checkoutByCo
Assert.False(repo.Index.RetrieveStatus().IsDirty);

var commit = repo.Lookup<Commit>(commitPointer);
AssertBelongsToARepository(repo, commit);

Branch detachedHead = checkoutByCommitOrBranchSpec ? repo.Checkout(commitPointer) : repo.Checkout(commit);

Expand Down
25 changes: 24 additions & 1 deletion LibGit2Sharp.Tests/MetaFixture.cs
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,11 @@ namespace LibGit2Sharp.Tests
{
public class MetaFixture
{
private static readonly HashSet<Type> explicitOnlyInterfaces = new HashSet<Type>
{
typeof(IBelongToARepository),
};

[Fact]
public void PublicTestMethodsAreFactsOrTheories()
{
Expand Down Expand Up @@ -114,7 +119,7 @@ public void LibGit2SharpPublicInterfacesCoverAllPublicMembers()
var methodsMissingFromInterfaces =
from t in Assembly.GetAssembly(typeof(IRepository)).GetExportedTypes()
where !t.IsInterface
where t.GetInterfaces().Any(i => i.IsPublic && i.Namespace == typeof(IRepository).Namespace)
where t.GetInterfaces().Any(i => i.IsPublic && i.Namespace == typeof(IRepository).Namespace && !explicitOnlyInterfaces.Contains(i))
let interfaceTargetMethods = from i in t.GetInterfaces()
from im in t.GetInterfaceMap(i).TargetMethods
select im
Expand All @@ -126,6 +131,24 @@ from tm in t.GetMethods(BindingFlags.DeclaredOnly | BindingFlags.Public | Bindin
methodsMissingFromInterfaces.ToArray()));
}

[Fact]
public void LibGit2SharpExplicitOnlyInterfacesAreIndeedExplicitOnly()
{
var methodsMissingFromInterfaces =
from t in Assembly.GetAssembly(typeof(IRepository)).GetExportedTypes()
where t.GetInterfaces().Any(explicitOnlyInterfaces.Contains)
let interfaceTargetMethods = from i in t.GetInterfaces()
where explicitOnlyInterfaces.Contains(i)
from im in t.GetInterfaceMap(i).TargetMethods
select im
from tm in t.GetMethods(BindingFlags.DeclaredOnly | BindingFlags.Public | BindingFlags.Instance)
where interfaceTargetMethods.Contains(tm)
select t.Name + " has public method " + tm.Name + " which should be explicitly implemented.";

Assert.Equal("", string.Join(Environment.NewLine,
methodsMissingFromInterfaces.ToArray()));
}

[Fact]
public void EnumsWithFlagsHaveMutuallyExclusiveValues()
{
Expand Down
2 changes: 2 additions & 0 deletions LibGit2Sharp.Tests/RemoteFixture.cs
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@ public void CanGetRemoteOrigin()
{
Remote origin = repo.Network.Remotes["origin"];
Assert.NotNull(origin);
AssertBelongsToARepository(repo, origin);
Assert.Equal("origin", origin.Name);
Assert.Equal("c:/GitHub/libgit2sharp/Resources/testrepo.git", origin.Url);
}
Expand All @@ -38,6 +39,7 @@ public void CanEnumerateTheRemotes()
foreach (Remote remote in repo.Network.Remotes)
{
Assert.NotNull(remote);
AssertBelongsToARepository(repo, remote);
count++;
}

Expand Down
1 change: 1 addition & 0 deletions LibGit2Sharp.Tests/SubmoduleFixture.cs
Original file line number Diff line number Diff line change
Expand Up @@ -60,6 +60,7 @@ public void CanRetrieveTheCommitIdsOfASubmodule(string name, string headId, stri
{
var submodule = repo.Submodules[name];
Assert.NotNull(submodule);
AssertBelongsToARepository(repo, submodule);
Assert.Equal(name, submodule.Name);

Assert.Equal((ObjectId)headId, submodule.HeadCommitId);
Expand Down
6 changes: 6 additions & 0 deletions LibGit2Sharp.Tests/TestHelpers/BaseFixture.cs
Original file line number Diff line number Diff line change
Expand Up @@ -412,5 +412,11 @@ public static bool StreamEquals(Stream one, Stream two)

return true;
}

public void AssertBelongsToARepository<T>(IRepository repo, T instance)
where T : IBelongToARepository
{
Assert.Same(repo, ((IBelongToARepository)instance).Repository);
}
}
}
2 changes: 1 addition & 1 deletion LibGit2Sharp/Branch.cs
Original file line number Diff line number Diff line change
Expand Up @@ -260,7 +260,7 @@ private Branch ResolveTrackedBranch()
return branch;
}

return new Branch(repo, new VoidReference(trackedReferenceName), trackedReferenceName);
return new Branch(repo, new VoidReference(repo, trackedReferenceName), trackedReferenceName);
}

private static bool IsRemoteBranch(string canonicalName)
Expand Down
2 changes: 1 addition & 1 deletion LibGit2Sharp/DirectReference.cs
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@ protected DirectReference()
{ }

internal DirectReference(string canonicalName, IRepository repo, ObjectId targetId)
: base(canonicalName, targetId.Sha)
: base(repo, canonicalName, targetId.Sha)
{
targetBuilder = new Lazy<GitObject>(() => repo.Lookup(targetId));
}
Expand Down
4 changes: 3 additions & 1 deletion LibGit2Sharp/GitObject.cs
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ namespace LibGit2Sharp
/// A GitObject
/// </summary>
[DebuggerDisplay("{DebuggerDisplay,nq}")]
public abstract class GitObject : IEquatable<GitObject>
public abstract class GitObject : IEquatable<GitObject>, IBelongToARepository
{
internal static IDictionary<Type, ObjectType> TypeToKindMap =
new Dictionary<Type, ObjectType>
Expand Down Expand Up @@ -154,5 +154,7 @@ private string DebuggerDisplay
{
get { return Id.ToString(7); }
}

IRepository IBelongToARepository.Repository { get { return repo; } }
}
}
26 changes: 26 additions & 0 deletions LibGit2Sharp/IBelongToARepository.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
namespace LibGit2Sharp
{
/// <summary>
/// Can be used to reference the <see cref="IRepository" /> from which
/// an instance was created.
/// <para>
/// While convenient in some situations (e.g. Checkout branch bound to UI element),
/// it is important to ensure instances created from an <see cref="IRepository" />
/// are not used after it is disposed.
/// </para>
/// <para>
/// It's generally better to create <see cref="IRepository" /> and dependant instances
/// on demand, with a short lifespan.
/// </para>
/// </summary>
public interface IBelongToARepository
{
/// <summary>
/// The <see cref="IRepository" /> from which this instance was created.
/// <para>
/// The returned value should not be disposed.
/// </para>
/// </summary>
IRepository Repository { get; }
}
}
1 change: 1 addition & 0 deletions LibGit2Sharp/LibGit2Sharp.csproj
Original file line number Diff line number Diff line change
Expand Up @@ -84,6 +84,7 @@
<Compile Include="Core\Handles\IndexNameEntrySafeHandle.cs" />
<Compile Include="Core\Handles\IndexReucEntrySafeHandle.cs" />
<Compile Include="EntryExistsException.cs" />
<Compile Include="IBelongToARepository.cs" />
<Compile Include="IndexNameEntryCollection.cs" />
<Compile Include="ContentChangeStats.cs" />
<Compile Include="BuiltInFeatures.cs" />
Expand Down
18 changes: 16 additions & 2 deletions LibGit2Sharp/Reference.cs
Original file line number Diff line number Diff line change
Expand Up @@ -10,11 +10,12 @@ namespace LibGit2Sharp
/// A Reference to another git object
/// </summary>
[DebuggerDisplay("{DebuggerDisplay,nq}")]
public abstract class Reference : IEquatable<Reference>
public abstract class Reference : IEquatable<Reference>, IBelongToARepository
{
private static readonly LambdaEqualityHelper<Reference> equalityHelper =
new LambdaEqualityHelper<Reference>(x => x.CanonicalName, x => x.TargetIdentifier);

private readonly IRepository repo;
private readonly string canonicalName;
private readonly string targetIdentifier;

Expand All @@ -29,8 +30,19 @@ protected Reference()
/// </summary>
/// <param name="canonicalName">The canonical name.</param>
/// <param name="targetIdentifier">The target identifier.</param>
[Obsolete("This ctor will be removed in a future release.")]
protected Reference(string canonicalName, string targetIdentifier)
: this(null, canonicalName, targetIdentifier)
{
}

/// <remarks>
/// This would be protected+internal, were that supported by C#.
/// Do not use except in subclasses.
/// </remarks>
internal Reference(IRepository repo, string canonicalName, string targetIdentifier)
{
this.repo = repo;
this.canonicalName = canonicalName;
this.targetIdentifier = targetIdentifier;
}
Expand All @@ -48,7 +60,7 @@ internal static T BuildFromPtr<T>(ReferenceSafeHandle handle, Repository repo) w
string targetIdentifier = Proxy.git_reference_symbolic_target(handle);

var targetRef = repo.Refs[targetIdentifier];
reference = new SymbolicReference(name, targetIdentifier, targetRef);
reference = new SymbolicReference(repo, name, targetIdentifier, targetRef);
break;

case GitReferenceType.Oid:
Expand Down Expand Up @@ -197,5 +209,7 @@ private string DebuggerDisplay
"{0} => \"{1}\"", CanonicalName, TargetIdentifier);
}
}

IRepository IBelongToARepository.Repository { get { return repo; } }
}
}
4 changes: 3 additions & 1 deletion LibGit2Sharp/ReferenceWrapper.cs
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ namespace LibGit2Sharp
/// </summary>
/// <typeparam name="TObject">The type of the referenced Git object.</typeparam>
[DebuggerDisplay("{DebuggerDisplay,nq}")]
public abstract class ReferenceWrapper<TObject> : IEquatable<ReferenceWrapper<TObject>> where TObject : GitObject
public abstract class ReferenceWrapper<TObject> : IEquatable<ReferenceWrapper<TObject>>, IBelongToARepository where TObject : GitObject
{
/// <summary>
/// The repository.
Expand Down Expand Up @@ -160,5 +160,7 @@ private string DebuggerDisplay
(TargetObject != null) ? TargetObject.Id.ToString(7) : "?");
}
}

IRepository IBelongToARepository.Repository { get { return repo; } }
}
}
4 changes: 3 additions & 1 deletion LibGit2Sharp/Remote.cs
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ namespace LibGit2Sharp
/// A remote repository whose branches are tracked.
/// </summary>
[DebuggerDisplay("{DebuggerDisplay,nq}")]
public class Remote : IEquatable<Remote>
public class Remote : IEquatable<Remote>, IBelongToARepository
{
private static readonly LambdaEqualityHelper<Remote> equalityHelper =
new LambdaEqualityHelper<Remote>(x => x.Name, x => x.Url);
Expand Down Expand Up @@ -174,5 +174,7 @@ private string DebuggerDisplay
"{0} => {1}", Name, Url);
}
}

IRepository IBelongToARepository.Repository { get { return repository; } }
}
}
4 changes: 3 additions & 1 deletion LibGit2Sharp/Submodule.cs
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ namespace LibGit2Sharp
/// A Submodule.
/// </summary>
[DebuggerDisplay("{DebuggerDisplay,nq}")]
public class Submodule : IEquatable<Submodule>
public class Submodule : IEquatable<Submodule>, IBelongToARepository
{
private static readonly LambdaEqualityHelper<Submodule> equalityHelper =
new LambdaEqualityHelper<Submodule>(x => x.Name, x => x.HeadCommitId);
Expand Down Expand Up @@ -155,5 +155,7 @@ private string DebuggerDisplay
"{0} => {1}", Name, Url);
}
}

IRepository IBelongToARepository.Repository { get { return repo; } }
}
}
4 changes: 2 additions & 2 deletions LibGit2Sharp/SymbolicReference.cs
Original file line number Diff line number Diff line change
Expand Up @@ -17,8 +17,8 @@ public class SymbolicReference : Reference
protected SymbolicReference()
{ }

internal SymbolicReference(string canonicalName, string targetIdentifier, Reference target)
: base(canonicalName, targetIdentifier)
internal SymbolicReference(IRepository repo, string canonicalName, string targetIdentifier, Reference target)
: base(repo, canonicalName, targetIdentifier)
{
this.target = target;
}
Expand Down
4 changes: 2 additions & 2 deletions LibGit2Sharp/VoidReference.cs
Original file line number Diff line number Diff line change
Expand Up @@ -2,8 +2,8 @@
{
internal class VoidReference : Reference
{
internal VoidReference(string canonicalName)
: base(canonicalName, null)
internal VoidReference(IRepository repo, string canonicalName)
: base(repo, canonicalName, null)
{ }

public override DirectReference ResolveToDirectReference()
Expand Down