Skip to content

Commit 2054391

Browse files
committed
Make Diff.Compare able to handle a blob to blob comparison
1 parent 40bf30e commit 2054391

File tree

5 files changed

+135
-10
lines changed

5 files changed

+135
-10
lines changed
Lines changed: 61 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,61 @@
1+
using System.Linq;
2+
using System.Text;
3+
using LibGit2Sharp.Tests.TestHelpers;
4+
using Xunit;
5+
6+
namespace LibGit2Sharp.Tests
7+
{
8+
public class DiffBlobToBlobFixture : BaseFixture
9+
{
10+
[Fact]
11+
public void ComparingABlobAgainstItselfReturnsNoDifference()
12+
{
13+
using (var repo = new Repository(StandardTestRepoPath))
14+
{
15+
Blob blob = repo.Head.Tip.Tree.Blobs.First();
16+
17+
ContentChanges changes = repo.Diff.Compare(blob, blob);
18+
19+
Assert.Equal(0, changes.LinesAdded);
20+
Assert.Equal(0, changes.LinesDeleted);
21+
Assert.Equal(string.Empty, changes.Patch);
22+
}
23+
}
24+
25+
[Fact]
26+
public void CanCompareTwoVersionsOfABlobWithADiffOfTwoHunks()
27+
{
28+
using (var repo = new Repository(StandardTestRepoPath))
29+
{
30+
var oldblob = repo.Lookup<Blob>("7909961");
31+
var newblob = repo.Lookup<Blob>("4e935b7");
32+
33+
ContentChanges changes = repo.Diff.Compare(oldblob, newblob);
34+
35+
Assert.Equal(3, changes.LinesAdded);
36+
Assert.Equal(1, changes.LinesDeleted);
37+
38+
var expected = new StringBuilder()
39+
.Append("@@ -1,4 +1,5 @@\n")
40+
.Append(" 1\n")
41+
.Append("+2\n")
42+
.Append(" 3\n")
43+
.Append(" 4\n")
44+
.Append(" 5\n")
45+
.Append("@@ -8,8 +9,9 @@\n")
46+
.Append(" 8\n")
47+
.Append(" 9\n")
48+
.Append(" 10\n")
49+
.Append("-12\n")
50+
.Append("+11\n")
51+
.Append(" 12\n")
52+
.Append(" 13\n")
53+
.Append(" 14\n")
54+
.Append(" 15\n")
55+
.Append("+16\n");
56+
57+
Assert.Equal(expected.ToString(), changes.Patch);
58+
}
59+
}
60+
}
61+
}

LibGit2Sharp.Tests/LibGit2Sharp.Tests.csproj

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -45,6 +45,7 @@
4545
<ItemGroup>
4646
<Compile Include="ConfigurationFixture.cs" />
4747
<Compile Include="AttributesFixture.cs" />
48+
<Compile Include="DiffBlobToBlobFixture.cs" />
4849
<Compile Include="ObjectDatabaseFixture.cs" />
4950
<Compile Include="DiffTreeToTreeFixture.cs" />
5051
<Compile Include="RepositoryOptionsFixture.cs" />

LibGit2Sharp/ContentChanges.cs

Lines changed: 56 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,6 @@
1-
using System.Text;
1+
using System;
2+
using System.Text;
3+
using LibGit2Sharp.Core;
24

35
namespace LibGit2Sharp
46
{
@@ -13,6 +15,59 @@ protected ContentChanges()
1315
{
1416
}
1517

18+
internal ContentChanges(Repository repo, Blob oldBlob, Blob newBlob, GitDiffOptions options)
19+
{
20+
using (var osw1 = new ObjectSafeWrapper(oldBlob.Id, repo))
21+
using (var osw2 = new ObjectSafeWrapper(newBlob.Id, repo))
22+
{
23+
Ensure.Success(NativeMethods.git_diff_blobs(osw1.ObjectPtr, osw2.ObjectPtr, options, IntPtr.Zero, null, HunkCallback, LineCallback));
24+
}
25+
}
26+
27+
private static string NativeToString(IntPtr content, IntPtr contentlen)
28+
{
29+
return ((Utf8Marshaler)(Utf8Marshaler.GetInstance(string.Empty))).NativeToString(content, contentlen.ToInt32());
30+
}
31+
32+
private int HunkCallback(IntPtr data, GitDiffDelta delta, GitDiffRange range, IntPtr header, IntPtr headerlen)
33+
{
34+
string decodedContent = NativeToString(header, headerlen);
35+
36+
PatchBuilder.AppendFormat("{0}", decodedContent);
37+
return 0;
38+
}
39+
40+
private int LineCallback(IntPtr data, GitDiffDelta delta, GitDiffRange range, GitDiffLineOrigin lineorigin, IntPtr content, IntPtr contentlen)
41+
{
42+
string decodedContent = NativeToString(content, contentlen);
43+
44+
string prefix;
45+
46+
switch (lineorigin)
47+
{
48+
case GitDiffLineOrigin.GIT_DIFF_LINE_ADDITION:
49+
LinesAdded++;
50+
prefix = Encoding.ASCII.GetString(new[] { (byte)lineorigin });
51+
break;
52+
53+
case GitDiffLineOrigin.GIT_DIFF_LINE_DELETION:
54+
LinesDeleted++;
55+
prefix = Encoding.ASCII.GetString(new[] { (byte)lineorigin });
56+
break;
57+
58+
case GitDiffLineOrigin.GIT_DIFF_LINE_CONTEXT:
59+
prefix = Encoding.ASCII.GetString(new[] { (byte)lineorigin });
60+
break;
61+
62+
default:
63+
prefix = string.Empty;
64+
break;
65+
}
66+
67+
PatchBuilder.AppendFormat("{0}{1}", prefix, decodedContent);
68+
return 0;
69+
}
70+
1671
/// <summary>
1772
/// The number of lines added.
1873
/// </summary>

LibGit2Sharp/Core/NativeMethods.cs

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -256,7 +256,7 @@ internal delegate int git_diff_hunk_fn(
256256
IntPtr data,
257257
GitDiffDelta delta,
258258
GitDiffRange range,
259-
[MarshalAs(UnmanagedType.CustomMarshaler, MarshalTypeRef = typeof(Utf8Marshaler))] string header,
259+
IntPtr header,
260260
IntPtr headerLen);
261261

262262
[DllImport(libgit2)]
@@ -283,11 +283,11 @@ public static extern int git_diff_print_patch(
283283

284284
[DllImport(libgit2)]
285285
public static extern int git_diff_blobs(
286-
RepositorySafeHandle repository,
287-
IntPtr oldBlob,
288-
IntPtr newBlob,
286+
GitObjectSafeHandle oldBlob,
287+
GitObjectSafeHandle newBlob,
289288
GitDiffOptions options,
290-
object data,
289+
IntPtr data,
290+
git_diff_file_fn fileCallback,
291291
git_diff_hunk_fn hunkCallback,
292292
git_diff_data_fn lineCallback);
293293

LibGit2Sharp/Diff.cs

Lines changed: 12 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -12,13 +12,15 @@ public class Diff
1212
{
1313
private readonly Repository repo;
1414

15+
internal static GitDiffOptions DefaultOptions = new GitDiffOptions { InterhunkLines = 2 };
16+
1517
internal Diff(Repository repo)
1618
{
1719
this.repo = repo;
1820
}
1921

2022
/// <summary>
21-
/// Show changes between two trees.
23+
/// Show changes between two <see cref = "Tree"/>s.
2224
/// </summary>
2325
/// <param name = "oldTree">The <see cref = "Tree"/> you want to compare from.</param>
2426
/// <param name = "newTree">The <see cref = "Tree"/> you want to compare to.</param>
@@ -37,16 +39,22 @@ private DiffListSafeHandle BuildDiffListFromTrees(ObjectId oldTree, ObjectId new
3739
using (var osw2 = new ObjectSafeWrapper(newTree, repo))
3840
{
3941
DiffListSafeHandle diff;
40-
GitDiffOptions options = BuildDefaultOptions();
42+
GitDiffOptions options = DefaultOptions;
4143
Ensure.Success(NativeMethods.git_diff_tree_to_tree(repo.Handle, options, osw1.ObjectPtr, osw2.ObjectPtr, out diff));
4244

4345
return diff;
4446
}
4547
}
4648

47-
private GitDiffOptions BuildDefaultOptions()
49+
/// <summary>
50+
/// Show changes between two <see cref = "Blob"/>s.
51+
/// </summary>
52+
/// <param name = "oldBlob">The <see cref = "Blob"/> you want to compare from.</param>
53+
/// <param name = "newBlob">The <see cref = "Blob"/> you want to compare to.</param>
54+
/// <returns>A <see cref = "ContentChanges"/> containing the changes between the <paramref name = "oldBlob"/> and the <paramref name = "newBlob"/>.</returns>
55+
public ContentChanges Compare(Blob oldBlob, Blob newBlob)
4856
{
49-
return new GitDiffOptions { InterhunkLines = 2 };
57+
return new ContentChanges(repo, oldBlob, newBlob, DefaultOptions);
5058
}
5159
}
5260
}

0 commit comments

Comments
 (0)