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); } } }