using System;
using System.Diagnostics;
using System.Globalization;
using LibGit2Sharp.Core;
namespace LibGit2Sharp
{
///
/// A base class for things that wrap a (branch, tag, etc).
///
/// The type of the referenced Git object.
[DebuggerDisplay("{DebuggerDisplay,nq}")]
public abstract class ReferenceWrapper : IEquatable>, IBelongToARepository where TObject : GitObject
{
///
/// The repository.
///
protected readonly Repository repo;
private readonly Lazy objectBuilder;
private static readonly LambdaEqualityHelper> equalityHelper =
new LambdaEqualityHelper>(x => x.CanonicalName, x => x.TargetObject);
private readonly string canonicalName;
///
/// Needed for mocking purposes.
///
protected ReferenceWrapper()
{ }
/// The repository.
/// The reference.
/// A function to construct the reference's canonical name.
protected internal ReferenceWrapper(Repository repo, Reference reference, Func canonicalNameSelector)
{
Ensure.ArgumentNotNull(repo, "repo");
Ensure.ArgumentNotNull(reference, "reference");
Ensure.ArgumentNotNull(canonicalNameSelector, "canonicalNameSelector");
this.repo = repo;
canonicalName = canonicalNameSelector(reference);
objectBuilder = new Lazy(() => RetrieveTargetObject(reference));
}
///
/// Gets the full name of this reference.
///
public virtual string CanonicalName
{
get { return canonicalName; }
}
///
/// Gets the name of this reference.
///
public virtual string Name
{
get { return Shorten(); }
}
///
/// Returns the , a representation of the current reference.
///
/// The that represents the current reference.
public override string ToString()
{
return CanonicalName;
}
///
/// Gets the this points to.
///
protected TObject TargetObject
{
get { return objectBuilder.Value; }
}
///
/// Removes redundent leading namespaces (regarding the kind of
/// reference being wrapped) from the canonical name.
///
/// The friendly shortened name
protected abstract string Shorten();
private TObject RetrieveTargetObject(Reference reference)
{
var directReference = reference.ResolveToDirectReference();
if (directReference == null)
{
return null;
}
var target = directReference.Target;
if (target == null)
{
return null;
}
return repo.Lookup(target.Id);
}
///
/// Determines whether the specified is equal to the current .
///
/// The to compare with the current .
/// True if the specified is equal to the current ; otherwise, false.
public bool Equals(ReferenceWrapper other)
{
return equalityHelper.Equals(this, other);
}
///
/// Determines whether the specified is equal to the current .
///
/// The to compare with the current .
/// True if the specified is equal to the current ; otherwise, false.
public override bool Equals(object obj)
{
return Equals(obj as ReferenceWrapper);
}
///
/// Returns the hash code for this instance.
///
/// A 32-bit signed integer hash code.
public override int GetHashCode()
{
return equalityHelper.GetHashCode(this);
}
///
/// Tests if two are equal.
///
/// First to compare.
/// Second to compare.
/// True if the two objects are equal; false otherwise.
public static bool operator ==(ReferenceWrapper left, ReferenceWrapper right)
{
return Equals(left, right);
}
///
/// Tests if two are different.
///
/// First to compare.
/// Second to compare.
/// True if the two objects are different; false otherwise.
public static bool operator !=(ReferenceWrapper left, ReferenceWrapper right)
{
return !Equals(left, right);
}
private string DebuggerDisplay
{
get
{
return string.Format(CultureInfo.InvariantCulture,
"{0} => \"{1}\"", CanonicalName,
(TargetObject != null) ? TargetObject.Id.ToString(7) : "?");
}
}
IRepository IBelongToARepository.Repository { get { return repo; } }
}
}