diff --git a/LibGit2Sharp/BlameHunkCollection.cs b/LibGit2Sharp/BlameHunkCollection.cs
index 869daf527..6176c3730 100644
--- a/LibGit2Sharp/BlameHunkCollection.cs
+++ b/LibGit2Sharp/BlameHunkCollection.cs
@@ -11,10 +11,13 @@ namespace LibGit2Sharp
///
/// The result of a blame operation.
///
- public class BlameHunkCollection : IEnumerable
+ public class BlameHunkCollection : IEnumerable, IDisposable
{
private readonly IRepository repo;
private readonly List hunks = new List();
+ private readonly RepositoryHandle repoHandle;
+ private readonly BlameHandle referenceHandle;
+ private readonly bool shouldDisposeHandle;
///
/// For easy mocking
@@ -49,17 +52,29 @@ internal unsafe BlameHunkCollection(Repository repo, RepositoryHandle repoHandle
}
}
- using (var blameHandle = Proxy.git_blame_file(repoHandle, path, rawopts))
+ referenceHandle = Proxy.git_blame_file(repoHandle, path, rawopts);
+ shouldDisposeHandle = true;
+ this.PopulateHunks(this.referenceHandle);
+ }
+
+ private unsafe BlameHunkCollection(IRepository repo, RepositoryHandle repoHandle, BlameHandle reference, byte[] buffer)
+ {
+ this.repo = repo;
+ this.repoHandle = repoHandle;
+ this.referenceHandle = reference;
+ this.shouldDisposeHandle = false;
+
+ using (var blameHandle = Proxy.git_blame_buffer(repoHandle, reference, buffer))
{
- var numHunks = NativeMethods.git_blame_get_hunk_count(blameHandle);
- for (uint i = 0; i < numHunks; ++i)
- {
- var rawHunk = Proxy.git_blame_get_hunk_byindex(blameHandle, i);
- hunks.Add(new BlameHunk(this.repo, rawHunk));
- }
+ this.PopulateHunks(blameHandle);
}
}
+ public BlameHunkCollection FromBuffer(byte[] buffer)
+ {
+ return new BlameHunkCollection(repo, repoHandle, this.referenceHandle, buffer);
+ }
+
///
/// Access blame hunks by index.
///
@@ -100,5 +115,23 @@ IEnumerator IEnumerable.GetEnumerator()
{
return GetEnumerator();
}
+
+ private unsafe void PopulateHunks(BlameHandle blameHandle)
+ {
+ var numHunks = NativeMethods.git_blame_get_hunk_count(blameHandle);
+ for (uint i = 0; i < numHunks; ++i)
+ {
+ var rawHunk = Proxy.git_blame_get_hunk_byindex(blameHandle, i);
+ hunks.Add(new BlameHunk(this.repo, rawHunk));
+ }
+ }
+
+ public void Dispose()
+ {
+ if (shouldDisposeHandle)
+ {
+ this.referenceHandle.Dispose();
+ }
+ }
}
}
diff --git a/LibGit2Sharp/Core/NativeMethods.cs b/LibGit2Sharp/Core/NativeMethods.cs
index f5d45f3cf..44ecc9599 100644
--- a/LibGit2Sharp/Core/NativeMethods.cs
+++ b/LibGit2Sharp/Core/NativeMethods.cs
@@ -190,6 +190,13 @@ internal static extern unsafe int git_blame_file(
[MarshalAs(UnmanagedType.CustomMarshaler, MarshalCookie = UniqueId.UniqueIdentifier, MarshalTypeRef = typeof(StrictUtf8Marshaler))] string path,
git_blame_options options);
+ [DllImport(libgit2, CallingConvention = CallingConvention.Cdecl)]
+ internal static extern unsafe int git_blame_buffer(
+ out git_blame* blame,
+ git_blame* reference,
+ IntPtr buffer,
+ UIntPtr len);
+
[DllImport(libgit2, CallingConvention = CallingConvention.Cdecl)]
internal static extern unsafe void git_blame_free(git_blame* blame);
diff --git a/LibGit2Sharp/Core/Proxy.cs b/LibGit2Sharp/Core/Proxy.cs
index 50cefc0df..050dfe305 100644
--- a/LibGit2Sharp/Core/Proxy.cs
+++ b/LibGit2Sharp/Core/Proxy.cs
@@ -35,6 +35,27 @@ public static unsafe BlameHandle git_blame_file(
return NativeMethods.git_blame_get_hunk_byindex(blame, idx);
}
+ public static unsafe BlameHandle git_blame_buffer(
+ RepositoryHandle repo,
+ BlameHandle reference,
+ byte[] buffer)
+ {
+ git_blame* ptr;
+ int res;
+
+ unsafe
+ {
+ fixed (byte* p = buffer)
+ {
+ res = NativeMethods.git_blame_buffer(out ptr, reference, (IntPtr)p, (UIntPtr)buffer.Length);
+ }
+ }
+
+ Ensure.ZeroResult(res);
+
+ return new BlameHandle(ptr, true);
+ }
+
#endregion
#region git_blob_