diff options
-rw-r--r-- | LibGit2Sharp.Tests/DiffBlobToBlobFixture.cs | 61 | ||||
-rw-r--r-- | LibGit2Sharp.Tests/LibGit2Sharp.Tests.csproj | 1 | ||||
-rw-r--r-- | LibGit2Sharp/ContentChanges.cs | 57 | ||||
-rw-r--r-- | LibGit2Sharp/Core/NativeMethods.cs | 10 | ||||
-rw-r--r-- | LibGit2Sharp/Diff.cs | 16 |
5 files changed, 135 insertions, 10 deletions
diff --git a/LibGit2Sharp.Tests/DiffBlobToBlobFixture.cs b/LibGit2Sharp.Tests/DiffBlobToBlobFixture.cs new file mode 100644 index 00000000..15f36460 --- /dev/null +++ b/LibGit2Sharp.Tests/DiffBlobToBlobFixture.cs @@ -0,0 +1,61 @@ +using System.Linq; +using System.Text; +using LibGit2Sharp.Tests.TestHelpers; +using Xunit; + +namespace LibGit2Sharp.Tests +{ + public class DiffBlobToBlobFixture : BaseFixture + { + [Fact] + public void ComparingABlobAgainstItselfReturnsNoDifference() + { + using (var repo = new Repository(StandardTestRepoPath)) + { + Blob blob = repo.Head.Tip.Tree.Blobs.First(); + + ContentChanges changes = repo.Diff.Compare(blob, blob); + + Assert.Equal(0, changes.LinesAdded); + Assert.Equal(0, changes.LinesDeleted); + Assert.Equal(string.Empty, changes.Patch); + } + } + + [Fact] + public void CanCompareTwoVersionsOfABlobWithADiffOfTwoHunks() + { + using (var repo = new Repository(StandardTestRepoPath)) + { + var oldblob = repo.Lookup<Blob>("7909961"); + var newblob = repo.Lookup<Blob>("4e935b7"); + + ContentChanges changes = repo.Diff.Compare(oldblob, newblob); + + Assert.Equal(3, changes.LinesAdded); + Assert.Equal(1, changes.LinesDeleted); + + var expected = new StringBuilder() + .Append("@@ -1,4 +1,5 @@\n") + .Append(" 1\n") + .Append("+2\n") + .Append(" 3\n") + .Append(" 4\n") + .Append(" 5\n") + .Append("@@ -8,8 +9,9 @@\n") + .Append(" 8\n") + .Append(" 9\n") + .Append(" 10\n") + .Append("-12\n") + .Append("+11\n") + .Append(" 12\n") + .Append(" 13\n") + .Append(" 14\n") + .Append(" 15\n") + .Append("+16\n"); + + Assert.Equal(expected.ToString(), changes.Patch); + } + } + } +} diff --git a/LibGit2Sharp.Tests/LibGit2Sharp.Tests.csproj b/LibGit2Sharp.Tests/LibGit2Sharp.Tests.csproj index 8187f89e..52b8cbe7 100644 --- a/LibGit2Sharp.Tests/LibGit2Sharp.Tests.csproj +++ b/LibGit2Sharp.Tests/LibGit2Sharp.Tests.csproj @@ -45,6 +45,7 @@ <ItemGroup> <Compile Include="ConfigurationFixture.cs" /> <Compile Include="AttributesFixture.cs" /> + <Compile Include="DiffBlobToBlobFixture.cs" /> <Compile Include="ObjectDatabaseFixture.cs" /> <Compile Include="DiffTreeToTreeFixture.cs" /> <Compile Include="RepositoryOptionsFixture.cs" /> diff --git a/LibGit2Sharp/ContentChanges.cs b/LibGit2Sharp/ContentChanges.cs index cd16a99c..23a90c56 100644 --- a/LibGit2Sharp/ContentChanges.cs +++ b/LibGit2Sharp/ContentChanges.cs @@ -1,4 +1,6 @@ -using System.Text; +using System; +using System.Text; +using LibGit2Sharp.Core; namespace LibGit2Sharp { @@ -13,6 +15,59 @@ namespace LibGit2Sharp { } + internal ContentChanges(Repository repo, Blob oldBlob, Blob newBlob, GitDiffOptions options) + { + using (var osw1 = new ObjectSafeWrapper(oldBlob.Id, repo)) + using (var osw2 = new ObjectSafeWrapper(newBlob.Id, repo)) + { + Ensure.Success(NativeMethods.git_diff_blobs(osw1.ObjectPtr, osw2.ObjectPtr, options, IntPtr.Zero, null, HunkCallback, LineCallback)); + } + } + + private static string NativeToString(IntPtr content, IntPtr contentlen) + { + return ((Utf8Marshaler)(Utf8Marshaler.GetInstance(string.Empty))).NativeToString(content, contentlen.ToInt32()); + } + + private int HunkCallback(IntPtr data, GitDiffDelta delta, GitDiffRange range, IntPtr header, IntPtr headerlen) + { + string decodedContent = NativeToString(header, headerlen); + + PatchBuilder.AppendFormat("{0}", decodedContent); + return 0; + } + + private int LineCallback(IntPtr data, GitDiffDelta delta, GitDiffRange range, GitDiffLineOrigin lineorigin, IntPtr content, IntPtr contentlen) + { + string decodedContent = NativeToString(content, contentlen); + + string prefix; + + switch (lineorigin) + { + case GitDiffLineOrigin.GIT_DIFF_LINE_ADDITION: + LinesAdded++; + prefix = Encoding.ASCII.GetString(new[] { (byte)lineorigin }); + break; + + case GitDiffLineOrigin.GIT_DIFF_LINE_DELETION: + LinesDeleted++; + prefix = Encoding.ASCII.GetString(new[] { (byte)lineorigin }); + break; + + case GitDiffLineOrigin.GIT_DIFF_LINE_CONTEXT: + prefix = Encoding.ASCII.GetString(new[] { (byte)lineorigin }); + break; + + default: + prefix = string.Empty; + break; + } + + PatchBuilder.AppendFormat("{0}{1}", prefix, decodedContent); + return 0; + } + /// <summary> /// The number of lines added. /// </summary> diff --git a/LibGit2Sharp/Core/NativeMethods.cs b/LibGit2Sharp/Core/NativeMethods.cs index 1940c9b1..845e147f 100644 --- a/LibGit2Sharp/Core/NativeMethods.cs +++ b/LibGit2Sharp/Core/NativeMethods.cs @@ -256,7 +256,7 @@ namespace LibGit2Sharp.Core IntPtr data, GitDiffDelta delta, GitDiffRange range, - [MarshalAs(UnmanagedType.CustomMarshaler, MarshalTypeRef = typeof(Utf8Marshaler))] string header, + IntPtr header, IntPtr headerLen); [DllImport(libgit2)] @@ -283,11 +283,11 @@ namespace LibGit2Sharp.Core [DllImport(libgit2)] public static extern int git_diff_blobs( - RepositorySafeHandle repository, - IntPtr oldBlob, - IntPtr newBlob, + GitObjectSafeHandle oldBlob, + GitObjectSafeHandle newBlob, GitDiffOptions options, - object data, + IntPtr data, + git_diff_file_fn fileCallback, git_diff_hunk_fn hunkCallback, git_diff_data_fn lineCallback); diff --git a/LibGit2Sharp/Diff.cs b/LibGit2Sharp/Diff.cs index 9c4dbc18..c216fdcc 100644 --- a/LibGit2Sharp/Diff.cs +++ b/LibGit2Sharp/Diff.cs @@ -12,13 +12,15 @@ namespace LibGit2Sharp { private readonly Repository repo; + internal static GitDiffOptions DefaultOptions = new GitDiffOptions { InterhunkLines = 2 }; + internal Diff(Repository repo) { this.repo = repo; } /// <summary> - /// Show changes between two trees. + /// Show changes between two <see cref = "Tree"/>s. /// </summary> /// <param name = "oldTree">The <see cref = "Tree"/> you want to compare from.</param> /// <param name = "newTree">The <see cref = "Tree"/> you want to compare to.</param> @@ -37,16 +39,22 @@ namespace LibGit2Sharp using (var osw2 = new ObjectSafeWrapper(newTree, repo)) { DiffListSafeHandle diff; - GitDiffOptions options = BuildDefaultOptions(); + GitDiffOptions options = DefaultOptions; Ensure.Success(NativeMethods.git_diff_tree_to_tree(repo.Handle, options, osw1.ObjectPtr, osw2.ObjectPtr, out diff)); return diff; } } - private GitDiffOptions BuildDefaultOptions() + /// <summary> + /// Show changes between two <see cref = "Blob"/>s. + /// </summary> + /// <param name = "oldBlob">The <see cref = "Blob"/> you want to compare from.</param> + /// <param name = "newBlob">The <see cref = "Blob"/> you want to compare to.</param> + /// <returns>A <see cref = "ContentChanges"/> containing the changes between the <paramref name = "oldBlob"/> and the <paramref name = "newBlob"/>.</returns> + public ContentChanges Compare(Blob oldBlob, Blob newBlob) { - return new GitDiffOptions { InterhunkLines = 2 }; + return new ContentChanges(repo, oldBlob, newBlob, DefaultOptions); } } } |