diff options
author | Ben Straub <bs@github.com> | 2013-11-24 23:34:59 +0400 |
---|---|---|
committer | Ben Straub <bs@github.com> | 2013-11-24 23:34:59 +0400 |
commit | 4f4819ed9df526e67e103615699a282a75364f59 (patch) | |
tree | 03f6d03fd84c28067fe0c9da8693f873ac1be3de /LibGit2Sharp/BlameHunk.cs | |
parent | a3f95fc9e92aa4bec32f4c4a535b0316ec2ea470 (diff) |
Introduce Repository.Blame
Diffstat (limited to 'LibGit2Sharp/BlameHunk.cs')
-rw-r--r-- | LibGit2Sharp/BlameHunk.cs | 177 |
1 files changed, 177 insertions, 0 deletions
diff --git a/LibGit2Sharp/BlameHunk.cs b/LibGit2Sharp/BlameHunk.cs new file mode 100644 index 00000000..1142ad1c --- /dev/null +++ b/LibGit2Sharp/BlameHunk.cs @@ -0,0 +1,177 @@ +using System; +using System.Diagnostics; +using System.Globalization; +using LibGit2Sharp.Core; +using LibGit2Sharp.Core.Compat; + +namespace LibGit2Sharp +{ + /// <summary> + /// A contiguous group of lines that have been traced to a single commit. + /// </summary> + [DebuggerDisplay("{DebuggerDisplay,nq}")] + public class BlameHunk : IEquatable<BlameHunk> + { + private readonly IRepository repository; + + private static readonly LambdaEqualityHelper<BlameHunk> equalityHelper = + new LambdaEqualityHelper<BlameHunk>(x => x.LineCount, + x => x.FinalStartLineNumber, + x => x.FinalSignature, + x => x.InitialStartLineNumber, + x => x.InitialSignature, + x => x.InitialCommit); + + + internal BlameHunk(IRepository repository, GitBlameHunk rawHunk) + { + this.repository = repository; + + finalCommit = new Lazy<Commit>(() => repository.Lookup<Commit>(rawHunk.FinalCommitId)); + origCommit = new Lazy<Commit>(() => repository.Lookup<Commit>(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(NativeMethods.git_signature_dup(rawHunk.FinalSignature)); + } + if (rawHunk.OrigSignature != IntPtr.Zero) + { + InitialSignature = new Signature(NativeMethods.git_signature_dup(rawHunk.OrigSignature)); + } + } + + /// <summary> + /// For easier mocking + /// </summary> + protected BlameHunk() { } + + /// <summary> + /// Determine if this hunk contains a given line. + /// </summary> + /// <param name="line">Line number to test</param> + /// <returns>True if this hunk contains the given line.</returns> + public virtual bool ContainsLine(int line) + { + return FinalStartLineNumber <= line && line < FinalStartLineNumber + LineCount; + } + + /// <summary> + /// Number of lines in this hunk. + /// </summary> + public virtual int LineCount { get; private set; } + + /// <summary> + /// The line number where this hunk begins, as of <see cref="FinalCommit"/> + /// </summary> + public virtual int FinalStartLineNumber { get; private set; } + + /// <summary> + /// Signature of the most recent change to this hunk. + /// </summary> + public virtual Signature FinalSignature { get; private set; } + + /// <summary> + /// Commit which most recently changed this file. + /// </summary> + public virtual Commit FinalCommit { get { return finalCommit.Value; } } + + /// <summary> + /// Line number where this hunk begins, as of <see cref="FinalCommit"/>, in <see cref="InitialPath"/>. + /// </summary> + public virtual int InitialStartLineNumber { get; private set; } + + /// <summary> + /// Signature of the oldest-traced change to this hunk. + /// </summary> + public virtual Signature InitialSignature { get; private set; } + + /// <summary> + /// Commit to which the oldest change to this hunk has been traced. + /// </summary> + public virtual Commit InitialCommit { get { return origCommit.Value; } } + + /// <summary> + /// Path to the file where this hunk originated, as of <see cref="InitialCommit"/>. + /// </summary> + public virtual string InitialPath { get; private set; } + + private string DebuggerDisplay + { + get + { + return string.Format(CultureInfo.InvariantCulture, + "{0}-{1} ({2})", + FinalStartLineNumber, + FinalStartLineNumber+LineCount, + FinalCommit.ToString().Substring(0,7)); + } + } + + private readonly Lazy<Commit> finalCommit; + private readonly Lazy<Commit> origCommit; + + /// <summary> + /// Indicates whether the current object is equal to another object of the same type. + /// </summary> + /// <returns> + /// true if the current object is equal to the <paramref name="other"/> parameter; otherwise, false. + /// </returns> + /// <param name="other">An object to compare with this object.</param> + public bool Equals(BlameHunk other) + { + return equalityHelper.Equals(this, other); + } + + /// <summary> + /// Determines whether the specified <see cref="Object"/> is equal to the current <see cref="BlameHunk"/>. + /// </summary> + /// <param name="obj">The <see cref="Object"/> to compare with the current <see cref="BlameHunk"/>.</param> + /// <returns>True if the specified <see cref="Object"/> is equal to the current <see cref="BlameHunk"/>; otherwise, false.</returns> + public override bool Equals(object obj) + { + return Equals(obj as BlameHunk); + } + + /// <summary> + /// Returns the hash code for this instance. + /// </summary> + /// <returns>A 32-bit signed integer hash code.</returns> + public override int GetHashCode() + { + return equalityHelper.GetHashCode(); + } + + /// <summary> + /// Tests if two <see cref="BlameHunk"/>s are equal. + /// </summary> + /// <param name="left">First hunk to compare.</param> + /// <param name="right">Second hunk to compare.</param> + /// <returns>True if the two objects are equal; false otherwise.</returns> + public static bool operator ==(BlameHunk left, BlameHunk right) + { + return Equals(left, right); + } + + /// <summary> + /// Tests if two <see cref="BlameHunk"/>s are unequal. + /// </summary> + /// <param name="left">First hunk to compare.</param> + /// <param name="right">Second hunk to compare.</param> + /// <returns>True if the two objects are different; false otherwise.</returns> + public static bool operator !=(BlameHunk left, BlameHunk right) + { + return !Equals(left, right); + } + } +} |