using System;
using System.Diagnostics;
using System.Globalization;
using LibGit2Sharp.Core;
namespace LibGit2Sharp
{
///
/// A contiguous group of lines that have been traced to a single commit.
///
[DebuggerDisplay("{DebuggerDisplay,nq}")]
public class BlameHunk : IEquatable
{
private static readonly LambdaEqualityHelper equalityHelper =
new LambdaEqualityHelper(x => x.LineCount,
x => x.FinalStartLineNumber,
x => x.FinalSignature,
x => x.InitialStartLineNumber,
x => x.InitialSignature,
x => x.InitialCommit);
internal BlameHunk(IRepository repository, GitBlameHunk rawHunk)
{
finalCommit = new Lazy(() => repository.Lookup(rawHunk.FinalCommitId));
origCommit = new Lazy(() => repository.Lookup(rawHunk.OrigCommitId));
if (rawHunk.OrigPath != IntPtr.Zero)
{
InitialPath = LaxUtf8Marshaler.FromNative(rawHunk.OrigPath);
}
LineCount = rawHunk.LinesInHunk;
// Libgit2's line numbers are 1-based
FinalStartLineNumber = rawHunk.FinalStartLineNumber - 1;
InitialStartLineNumber = rawHunk.OrigStartLineNumber - 1;
// Signature objects need to have ownership of their native pointers
if (rawHunk.FinalSignature != IntPtr.Zero)
{
FinalSignature = new Signature(Proxy.git_signature_dup(rawHunk.FinalSignature));
}
if (rawHunk.OrigSignature != IntPtr.Zero)
{
InitialSignature = new Signature(Proxy.git_signature_dup(rawHunk.OrigSignature));
}
}
///
/// For easier mocking
///
protected BlameHunk() { }
///
/// Determine if this hunk contains a given line.
///
/// Line number to test
/// True if this hunk contains the given line.
public virtual bool ContainsLine(int line)
{
return FinalStartLineNumber <= line && line < FinalStartLineNumber + LineCount;
}
///
/// Number of lines in this hunk.
///
public virtual int LineCount { get; private set; }
///
/// The line number where this hunk begins, as of
///
public virtual int FinalStartLineNumber { get; private set; }
///
/// Signature of the most recent change to this hunk.
///
public virtual Signature FinalSignature { get; private set; }
///
/// Commit which most recently changed this file.
///
public virtual Commit FinalCommit { get { return finalCommit.Value; } }
///
/// Line number where this hunk begins, as of , in .
///
public virtual int InitialStartLineNumber { get; private set; }
///
/// Signature of the oldest-traced change to this hunk.
///
public virtual Signature InitialSignature { get; private set; }
///
/// Commit to which the oldest change to this hunk has been traced.
///
public virtual Commit InitialCommit { get { return origCommit.Value; } }
///
/// Path to the file where this hunk originated, as of .
///
public virtual string InitialPath { get; private set; }
private string DebuggerDisplay
{
get
{
return string.Format(CultureInfo.InvariantCulture,
"{0}-{1} ({2})",
FinalStartLineNumber,
FinalStartLineNumber+LineCount-1,
FinalCommit.ToString().Substring(0,7));
}
}
private readonly Lazy finalCommit;
private readonly Lazy origCommit;
///
/// Indicates whether the current object is equal to another object of the same type.
///
///
/// true if the current object is equal to the parameter; otherwise, false.
///
/// An object to compare with this object.
public bool Equals(BlameHunk 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 BlameHunk);
}
///
/// Returns the hash code for this instance.
///
/// A 32-bit signed integer hash code.
public override int GetHashCode()
{
return equalityHelper.GetHashCode();
}
///
/// Tests if two s are equal.
///
/// First hunk to compare.
/// Second hunk to compare.
/// True if the two objects are equal; false otherwise.
public static bool operator ==(BlameHunk left, BlameHunk right)
{
return Equals(left, right);
}
///
/// Tests if two s are unequal.
///
/// First hunk to compare.
/// Second hunk to compare.
/// True if the two objects are different; false otherwise.
public static bool operator !=(BlameHunk left, BlameHunk right)
{
return !Equals(left, right);
}
}
}