Skip to content

Commit 1c23443

Browse files
committed
Make Diff.Compare able to cope with binary content
1 parent 2054391 commit 1c23443

File tree

5 files changed

+63
-4
lines changed

5 files changed

+63
-4
lines changed

LibGit2Sharp.Tests/DiffBlobToBlobFixture.cs

Lines changed: 32 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
1-
using System.Linq;
1+
using System.IO;
2+
using System.Linq;
23
using System.Text;
34
using LibGit2Sharp.Tests.TestHelpers;
45
using Xunit;
@@ -32,6 +33,8 @@ public void CanCompareTwoVersionsOfABlobWithADiffOfTwoHunks()
3233

3334
ContentChanges changes = repo.Diff.Compare(oldblob, newblob);
3435

36+
Assert.False(changes.IsBinaryComparison);
37+
3538
Assert.Equal(3, changes.LinesAdded);
3639
Assert.Equal(1, changes.LinesDeleted);
3740

@@ -57,5 +60,33 @@ public void CanCompareTwoVersionsOfABlobWithADiffOfTwoHunks()
5760
Assert.Equal(expected.ToString(), changes.Patch);
5861
}
5962
}
63+
64+
Blob CreateBinaryBlob(Repository repo)
65+
{
66+
var scd = BuildSelfCleaningDirectory();
67+
Directory.CreateDirectory(scd.RootedDirectoryPath);
68+
string fullpath = Path.Combine(scd.RootedDirectoryPath, "binary.bin");
69+
File.WriteAllBytes(fullpath, new byte[] { 17, 16, 0, 4, 65 });
70+
71+
return repo.ObjectDatabase.CreateBlob(fullpath);
72+
}
73+
74+
[Fact]
75+
public void CanCompareATextualBlobAgainstABinaryBlob()
76+
{
77+
using (var repo = new Repository(StandardTestRepoPath))
78+
{
79+
Blob binBlob = CreateBinaryBlob(repo);
80+
81+
Blob blob = repo.Head.Tip.Tree.Blobs.First();
82+
83+
ContentChanges changes = repo.Diff.Compare(blob, binBlob);
84+
85+
Assert.True(changes.IsBinaryComparison);
86+
87+
Assert.Equal(0, changes.LinesAdded);
88+
Assert.Equal(0, changes.LinesDeleted);
89+
}
90+
}
6091
}
6192
}

LibGit2Sharp.Tests/DiffTreeToTreeFixture.cs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -57,6 +57,7 @@ public void CanCompareACommitTreeAgainstItsParent()
5757
Assert.Equal(1, changes.Added.Count());
5858

5959
TreeEntryChanges treeEntryChanges = changes["1.txt"];
60+
Assert.False(treeEntryChanges.IsBinaryComparison);
6061

6162
Assert.Equal("1.txt", treeEntryChanges.Path);
6263
Assert.Equal(ChangeKind.Added, treeEntryChanges.Status);

LibGit2Sharp/ContentChanges.cs

Lines changed: 27 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
using System;
2+
using System.Runtime.InteropServices;
23
using System.Text;
34
using LibGit2Sharp.Core;
45

@@ -20,10 +21,30 @@ internal ContentChanges(Repository repo, Blob oldBlob, Blob newBlob, GitDiffOpti
2021
using (var osw1 = new ObjectSafeWrapper(oldBlob.Id, repo))
2122
using (var osw2 = new ObjectSafeWrapper(newBlob.Id, repo))
2223
{
23-
Ensure.Success(NativeMethods.git_diff_blobs(osw1.ObjectPtr, osw2.ObjectPtr, options, IntPtr.Zero, null, HunkCallback, LineCallback));
24+
Ensure.Success(NativeMethods.git_diff_blobs(osw1.ObjectPtr, osw2.ObjectPtr, options, IntPtr.Zero, FileCallback, HunkCallback, LineCallback));
2425
}
2526
}
2627

28+
private int FileCallback(IntPtr data, GitDiffDelta delta, float progress)
29+
{
30+
IsBinaryComparison = IsBinaryDelta(delta);
31+
32+
if (!IsBinaryComparison)
33+
{
34+
return 0;
35+
}
36+
37+
PatchBuilder.Append("Binary content differ\n");
38+
39+
return 0;
40+
}
41+
42+
internal static bool IsBinaryDelta(GitDiffDelta delta)
43+
{
44+
//TODO Fix the interop issue on amd64 and use GitDiffDelta.Binary
45+
return delta.OldFile.Flags.Has(GitDiffFileFlags.GIT_DIFF_FILE_BINARY) || delta.NewFile.Flags.Has(GitDiffFileFlags.GIT_DIFF_FILE_BINARY);
46+
}
47+
2748
private static string NativeToString(IntPtr content, IntPtr contentlen)
2849
{
2950
return ((Utf8Marshaler)(Utf8Marshaler.GetInstance(string.Empty))).NativeToString(content, contentlen.ToInt32());
@@ -68,6 +89,11 @@ private int LineCallback(IntPtr data, GitDiffDelta delta, GitDiffRange range, Gi
6889
return 0;
6990
}
7091

92+
/// <summary>
93+
/// Determines if at least one of the compared <see cref="Blob"/>s holds some binary content.
94+
/// </summary>
95+
public bool IsBinaryComparison { get; protected set; }
96+
7197
/// <summary>
7298
/// The number of lines added.
7399
/// </summary>

LibGit2Sharp/TreeChanges.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -89,7 +89,7 @@ private void AddFileChange(GitDiffDelta delta)
8989
var newMode = (Mode)delta.NewFile.Mode;
9090
var oldMode = (Mode)delta.OldFile.Mode;
9191

92-
var diffFile = new TreeEntryChanges(newFilePath, newMode, delta.Status, oldFilePath, oldMode);
92+
var diffFile = new TreeEntryChanges(newFilePath, newMode, delta.Status, oldFilePath, oldMode, ContentChanges.IsBinaryDelta(delta));
9393

9494
fileDispatcher[delta.Status](this, diffFile);
9595
changes.Add(diffFile.Path, diffFile);

LibGit2Sharp/TreeEntryChanges.cs

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,13 +7,14 @@ namespace LibGit2Sharp
77
/// </summary>
88
public class TreeEntryChanges : ContentChanges
99
{
10-
internal TreeEntryChanges(string path, Mode mode, ChangeKind status, string oldPath, Mode oldMode)
10+
internal TreeEntryChanges(string path, Mode mode, ChangeKind status, string oldPath, Mode oldMode, bool isBinaryComparison)
1111
{
1212
Path = path;
1313
Mode = mode;
1414
Status = status;
1515
OldPath = oldPath;
1616
OldMode = oldMode;
17+
IsBinaryComparison = isBinaryComparison;
1718
}
1819

1920
/// <summary>

0 commit comments

Comments
 (0)