using System;
using System.Diagnostics;
using System.Globalization;
using LibGit2Sharp.Core;
using LibGit2Sharp.Core.Handles;
namespace LibGit2Sharp
{
///
/// A Reference to another git object
///
[DebuggerDisplay("{DebuggerDisplay,nq}")]
public abstract class Reference : IEquatable
{
private static readonly LambdaEqualityHelper equalityHelper =
new LambdaEqualityHelper(x => x.CanonicalName, x => x.TargetIdentifier);
private readonly string canonicalName;
private readonly string targetIdentifier;
///
/// Needed for mocking purposes.
///
protected Reference()
{ }
///
/// Initializes a new instance of the class.
///
/// The canonical name.
/// The target identifier.
protected Reference(string canonicalName, string targetIdentifier)
{
this.canonicalName = canonicalName;
this.targetIdentifier = targetIdentifier;
}
internal static T BuildFromPtr(ReferenceSafeHandle handle, Repository repo) where T : Reference
{
GitReferenceType type = Proxy.git_reference_type(handle);
string name = Proxy.git_reference_name(handle);
Reference reference;
switch (type)
{
case GitReferenceType.Symbolic:
string targetIdentifier = Proxy.git_reference_symbolic_target(handle);
using (ReferenceSafeHandle resolvedHandle = Proxy.git_reference_resolve(handle))
{
if (resolvedHandle == null)
{
reference = new SymbolicReference(name, targetIdentifier, null);
break;
}
var targetRef = BuildFromPtr(resolvedHandle, repo);
reference = new SymbolicReference(name, targetIdentifier, targetRef);
break;
}
case GitReferenceType.Oid:
ObjectId targetOid = Proxy.git_reference_target(handle);
reference = new DirectReference(name, repo, targetOid);
break;
default:
throw new LibGit2SharpException(String.Format(CultureInfo.InvariantCulture, "Unable to build a new reference from a type '{0}'.", type));
}
return reference as T;
}
///
/// Gets the full name of this reference.
///
public virtual string CanonicalName
{
get { return canonicalName; }
}
///
/// Recursively peels the target of the reference until a direct reference is encountered.
///
/// The this points to.
public abstract DirectReference ResolveToDirectReference();
///
/// Gets the target declared by the reference.
///
/// If this reference is a , returns the canonical name of the target.
/// Otherwise, if this reference is a , returns the sha of the target.
///
///
// TODO: Maybe find a better name for this property.
public virtual string TargetIdentifier
{
get { return targetIdentifier; }
}
///
/// 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 Reference);
}
///
/// 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(Reference other)
{
return equalityHelper.Equals(this, other);
}
///
/// 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 ==(Reference left, Reference 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 !=(Reference left, Reference right)
{
return !Equals(left, right);
}
///
/// Returns the , a representation of the current .
///
/// The that represents the current .
public override string ToString()
{
return CanonicalName;
}
internal static string LocalBranchPrefix
{
get { return "refs/heads/"; }
}
internal static string RemoteTrackingBranchPrefix
{
get { return "refs/remotes/"; }
}
internal static string TagPrefix
{
get { return "refs/tags/"; }
}
internal static string NotePrefix
{
get { return "refs/notes/"; }
}
private string DebuggerDisplay
{
get
{
return string.Format(CultureInfo.InvariantCulture,
"{0} => \"{1}\"", CanonicalName, TargetIdentifier);
}
}
}
}