Thanks to visit codestin.com
Credit goes to github.com

Skip to content

Commit 040a950

Browse files
committed
Let Diff.Compare take a blob and a buffer
This is a wrapper around `git_diff_buffers` that avoids having us copy the old blob's contents into managed memory, so we instead let the caller give us a blob which we'll look up and pass the C buffer straight back.
1 parent 8daef23 commit 040a950

File tree

7 files changed

+148
-8
lines changed

7 files changed

+148
-8
lines changed

LibGit2Sharp.Tests/DiffBlobToBlobFixture.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -104,7 +104,7 @@ public void CanCompareABlobAgainstANullBlob()
104104
Assert.Equal(0, changes.LinesDeleted);
105105
Assert.NotEqual(string.Empty, changes.Patch);
106106

107-
changes = repo.Diff.Compare(blob, null);
107+
changes = repo.Diff.Compare(blob, (Blob)null);
108108

109109
Assert.Equal(0, changes.LinesAdded);
110110
Assert.NotEqual(0, changes.LinesDeleted);
Lines changed: 55 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,55 @@
1+
using System.IO;
2+
using System.Text;
3+
using LibGit2Sharp.Tests.TestHelpers;
4+
using Xunit;
5+
6+
namespace LibGit2Sharp.Tests
7+
{
8+
public class DiffBlobToBufferFixture : BaseFixture
9+
{
10+
[Fact]
11+
public void CompareABlobAndAString()
12+
{
13+
var path = SandboxStandardTestRepoGitDir();
14+
using (var repo = new Repository(path))
15+
{
16+
// This is CanCompareTwoVersionsOfABlobWithADiffOfTwoHunks() but we read the second
17+
// one into memory and pretend we read it from disk or our editor.
18+
var oldblob = repo.Lookup<Blob>("7909961");
19+
var newblob = repo.Lookup<Blob>("4e935b7");
20+
21+
var newContent = newblob.GetContentText();
22+
23+
ContentChanges changes = repo.Diff.Compare(oldblob, newContent);
24+
25+
Assert.False(changes.IsBinaryComparison);
26+
27+
Assert.Equal(3, changes.LinesAdded);
28+
Assert.Equal(1, changes.LinesDeleted);
29+
30+
var expected = new StringBuilder()
31+
.Append("@@ -1,4 +1,5 @@\n")
32+
.Append(" 1\n")
33+
.Append("+2\n")
34+
.Append(" 3\n")
35+
.Append(" 4\n")
36+
.Append(" 5\n")
37+
.Append("@@ -8,8 +9,9 @@\n")
38+
.Append(" 8\n")
39+
.Append(" 9\n")
40+
.Append(" 10\n")
41+
.Append("-12\n")
42+
.Append("+11\n")
43+
.Append(" 12\n")
44+
.Append(" 13\n")
45+
.Append(" 14\n")
46+
.Append(" 15\n")
47+
.Append("+16\n");
48+
49+
Assert.Equal(expected.ToString(), changes.Patch);
50+
51+
}
52+
}
53+
}
54+
}
55+

LibGit2Sharp.Tests/LibGit2Sharp.Tests.csproj

Lines changed: 7 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -35,19 +35,18 @@
3535
<AllowUnsafeBlocks>true</AllowUnsafeBlocks>
3636
</PropertyGroup>
3737
<ItemGroup>
38-
<Reference Include="Moq, Version=4.2.1507.118, Culture=neutral, PublicKeyToken=69f491c39445e920, processorArchitecture=MSIL">
39-
<HintPath>..\packages\Moq.4.2.1507.0118\lib\net40\Moq.dll</HintPath>
40-
</Reference>
4138
<Reference Include="System" />
4239
<Reference Include="System.Core" />
4340
<Reference Include="System.Xml" />
44-
<Reference Include="xunit, Version=1.9.2.1705, Culture=neutral, PublicKeyToken=8d05b1bb7a6fdb6c, processorArchitecture=MSIL">
45-
<SpecificVersion>False</SpecificVersion>
46-
<HintPath>..\packages\xunit.1.9.2\lib\net20\xunit.dll</HintPath>
47-
</Reference>
4841
<Reference Include="xunit.extensions">
4942
<HintPath>..\packages\xunit.extensions.1.9.2\lib\net20\xunit.extensions.dll</HintPath>
5043
</Reference>
44+
<Reference Include="Moq, Version=4.2.1507.118, Culture=neutral, PublicKeyToken=69f491c39445e920">
45+
<HintPath>..\packages\Moq.4.2.1507.0118\lib\net40\Moq.dll</HintPath>
46+
</Reference>
47+
<Reference Include="xunit">
48+
<HintPath>..\packages\xunit.1.9.2\lib\net20\xunit.dll</HintPath>
49+
</Reference>
5150
</ItemGroup>
5251
<ItemGroup>
5352
<Compile Include="..\LibGit2Sharp\Core\Epoch.cs">
@@ -136,6 +135,7 @@
136135
<Compile Include="TreeDefinitionFixture.cs" />
137136
<Compile Include="TreeFixture.cs" />
138137
<Compile Include="UnstageFixture.cs" />
138+
<Compile Include="DiffBlobToBufferFixture.cs" />
139139
</ItemGroup>
140140
<ItemGroup>
141141
<ProjectReference Include="..\LibGit2Sharp\LibGit2Sharp.csproj">

LibGit2Sharp/ContentChanges.cs

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -31,6 +31,17 @@ internal ContentChanges(Repository repo, Blob oldBlob, Blob newBlob, GitDiffOpti
3131
LineCallback);
3232
}
3333

34+
internal ContentChanges(Repository repo, Blob oldBlob, string newContent, GitDiffOptions options)
35+
{
36+
Proxy.git_diff_blob_to_buffer(repo.Handle,
37+
oldBlob != null ? oldBlob.Id : null,
38+
newContent,
39+
options,
40+
FileCallback,
41+
HunkCallback,
42+
LineCallback);
43+
}
44+
3445
internal ContentChanges(bool isBinaryComparison)
3546
{
3647
this.IsBinaryComparison = isBinaryComparison;

LibGit2Sharp/Core/NativeMethods.cs

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -549,6 +549,22 @@ internal static extern int git_diff_blobs(
549549
git_diff_line_cb lineCallback,
550550
IntPtr payload);
551551

552+
[DllImport(libgit2)]
553+
internal static extern int git_diff_buffers(
554+
IntPtr old_buffer, // this comes from git_blob_rawcontent() so we can avoid copying the memory
555+
IntPtr old_len,
556+
[MarshalAs(UnmanagedType.CustomMarshaler, MarshalCookie = UniqueId.UniqueIdentifier, MarshalTypeRef = typeof(StrictFilePathMarshaler))] FilePath old_as_path,
557+
[MarshalAs(UnmanagedType.CustomMarshaler, MarshalCookie = UniqueId.UniqueIdentifier, MarshalTypeRef = typeof(StrictUtf8Marshaler))] string new_buffer,
558+
IntPtr new_len,
559+
[MarshalAs(UnmanagedType.CustomMarshaler, MarshalCookie = UniqueId.UniqueIdentifier, MarshalTypeRef = typeof(StrictFilePathMarshaler))] FilePath new_as_path,
560+
GitDiffOptions options,
561+
git_diff_file_cb fileCallback,
562+
git_diff_binary_cb binaryCallback,
563+
git_diff_hunk_cb hunkCallback,
564+
git_diff_line_cb lineCallback,
565+
IntPtr payload);
566+
567+
552568
[DllImport(libgit2)]
553569
internal static extern int git_diff_foreach(
554570
DiffSafeHandle diff,

LibGit2Sharp/Core/Proxy.cs

Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -726,6 +726,37 @@ public static void git_diff_blobs(
726726
}
727727
}
728728

729+
public static void git_diff_blob_to_buffer(
730+
RepositorySafeHandle repo,
731+
ObjectId oldBlob,
732+
string newContent,
733+
GitDiffOptions options,
734+
NativeMethods.git_diff_file_cb fileCallback,
735+
NativeMethods.git_diff_hunk_cb hunkCallback,
736+
NativeMethods.git_diff_line_cb lineCallback)
737+
{
738+
using (var osw = new ObjectSafeWrapper(oldBlob, repo, true))
739+
{
740+
var oldContent = NativeMethods.git_blob_rawcontent(osw.ObjectPtr);
741+
var oldSize = NativeMethods.git_blob_rawsize(osw.ObjectPtr);
742+
int res = NativeMethods.git_diff_buffers(oldContent,
743+
new IntPtr(oldSize),
744+
null,
745+
newContent,
746+
new IntPtr(newContent.Length),
747+
null,
748+
options,
749+
fileCallback,
750+
null,
751+
hunkCallback,
752+
lineCallback,
753+
IntPtr.Zero);
754+
755+
Ensure.ZeroResult(res);
756+
}
757+
}
758+
759+
729760
public static void git_diff_foreach(
730761
DiffSafeHandle diff,
731762
NativeMethods.git_diff_file_cb fileCallback,

LibGit2Sharp/Diff.cs

Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -146,6 +146,33 @@ public virtual ContentChanges Compare(Blob oldBlob, Blob newBlob, CompareOptions
146146
}
147147
}
148148

149+
/// <summary>
150+
/// Show changes between <see cref="Blob"/> and a string.
151+
/// </summary>
152+
/// <param name="oldBlob">The <see cref="Blob"/> you want to compare from.</param>
153+
/// <param name="newContent">The <see cref="string"/> you want to compare to.</param>
154+
/// <returns>A <see cref="ContentChanges"/> containing the changes between the <paramref name="oldBlob"/> and the <paramref name="newBlob"/>.</returns>
155+
public virtual ContentChanges Compare(Blob oldBlob, string newContent)
156+
{
157+
return Compare(oldBlob, newContent, null);
158+
}
159+
160+
/// <summary>
161+
/// Show changes between <see cref="Blob"/> and a string.
162+
/// </summary>
163+
/// <param name="oldBlob">The <see cref="Blob"/> you want to compare from.</param>
164+
/// <param name="newContent">The <see cref="string"/> you want to compare to.</param>
165+
/// <param name="compareOptions">Additional options to define comparison behavior.</param>
166+
/// <returns>A <see cref="ContentChanges"/> containing the changes between the <paramref name="oldBlob"/> and the <paramref name="newBlob"/>.</returns>
167+
public virtual ContentChanges Compare(Blob oldBlob, string newContent, CompareOptions compareOptions)
168+
{
169+
using (GitDiffOptions options = BuildOptions(DiffModifiers.None, compareOptions: compareOptions))
170+
{
171+
return new ContentChanges(repo, oldBlob, newContent, options);
172+
}
173+
}
174+
175+
149176
/// <summary>
150177
/// Show changes between two <see cref="Tree"/>s.
151178
/// </summary>

0 commit comments

Comments
 (0)