8000 Merge pull request #1652 from jcansdale/fixes/git-diff-indent-heuristic · admdev8/libgit2sharp@ac599f4 · GitHub
[go: up one dir, main page]

Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Appearance settings

Commit ac599f4

Browse files
authored
Merge pull request libgit2#1652 from jcansdale/fixes/git-diff-indent-heuristic
Add support for git diff --indent-heuristic option
2 parents e5fdf1b + 2f583cb commit ac599f4

File tree

4 files changed

+104
-5
lines changed

4 files changed

+104
-5
lines changed

LibGit2Sharp.Tests/DiffBlobToBlobFixture.cs

Lines changed: 81 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
using System.IO;
2+
using System.Linq;
23
using System.Text;
34
using LibGit2Sharp.Tests.TestHelpers;
45
using Xunit;
@@ -126,5 +127,85 @@ public void ComparingTwoNullBlobsReturnsAnEmptyContentChanges()
126127
Assert.Equal(0, changes.LinesDeleted);
127128
}
128129
}
130+
131+
[Fact]
132+
public void ComparingBlobsWithNoSpacesAndIndentHeuristicOptionMakesADifference()
133+
{
134+
var path = SandboxStandardTestRepoGitDir();
135+
using (var repo = new Repository(path))
136+
{
137+
// Based on test diff indent heuristic from:
138+
// https://github.com/git/git/blob/433860f3d0beb0c6f205290bd16cda413148f098/t/t4061-diff-indent.sh#L17
139+
var oldContent =
140+
@" 1
141+
2
142+
a
143+
144+
b
145+
3
146+
4";
147+
var newContent =
148+
@" 1
149+
2
150+
a
151+
152+
b
153+
a
154+
155+
b
156+
3
157+
4";
158+
var oldBlob = repo.ObjectDatabase.CreateBlob(new MemoryStream(Encoding.UTF8.GetBytes(oldContent)));
159+
var newBlob = repo.ObjectDatabase.CreateBlob(new MemoryStream(Encoding.UTF8.GetBytes(newContent)));
160+
var noIndentHeuristicOption = new CompareOptions { IndentHeuristic = false };
161+
var indentHeuristicOption = new CompareOptions { IndentHeuristic = true };
162+
163+
ContentChanges changes0 = repo.Diff.Compare(oldBlob, newBlob, noIndentHeuristicOption);
164+
ContentChanges changes1 = repo.Diff.Compare(oldBlob, newBlob, indentHeuristicOption);
165+
166+
Assert.NotEqual(changes0.Patch, changes1.Patch);
167+
Assert.Equal(CanonicalChangedLines(changes0), CanonicalChangedLines(changes1));
168+
}
169+
}
170+
171+
[Fact]
172+
public void ComparingBlobsWithNoSpacesIndentHeuristicOptionMakesNoDifference()
173+
{
174+
var path = SandboxStandardTestRepoGitDir();
175+
using (var repo = new Repository(path))
176+
{
177+
var oldContent =
178+
@" 1
179+
2
180+
a
181+
b
182+
3
183+
4";
184+
var newContent =
185+
@" 1
186+
2
187+
a
188+
b
189+
a
190+
b
191+
3
192+
4";
193+
var oldBlob = repo.ObjectDatabase.CreateBlob(new MemoryStream(Encoding.UTF8.GetBytes(oldContent)));
194+
var newBlob = repo.ObjectDatabase.CreateBlob(new MemoryStream(Encoding.UTF8.GetBytes(newContent)));
195+
var noIndentHeuristicOption = new CompareOptions { IndentHeuristic = false };
196+
var indentHeuristicOption = new CompareOptions { IndentHeuristic = true };
197+
198+
ContentChanges changes0 = repo.Diff.Compare(oldBlob, newBlob, noIndentHeuristicOption);
199+
ContentChanges changes1 = repo.Diff.Compare(oldBlob, newBlob, indentHeuristicOption);
200+
201+
Assert.Equal(changes0.Patch, changes1.Patch);
202+
}
203+
}
204+
205+
static string CanonicalChangedLines(ContentChanges changes)
206+
{
207+
// Create an ordered representation of lines that have been added or removed
208+
return string.Join("\n", changes.Patch.Split('\n').Where(l => l.StartsWith("+") || l.StartsWith("-")).OrderBy(l => l));
209+
}
129210
}
130211
}

LibGit2Sharp/CompareOptions.cs

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -44,5 +44,11 @@ public CompareOptions()
4444
/// By default, <see cref="DiffAlgorithm.Myers"/> will be used.
4545
/// </summary>
4646
public DiffAlgorithm Algorithm { get; set; }
47+
48+
/// <summary>
49+
/// Enable --indent-heuristic Diff option, that attempts to produce more aesthetically pleasing diffs.
50+
/// By default, this option will be false.
51+
/// </summary>
52+
public bool IndentHeuristic { get; set; }
4753
}
4854
}

LibGit2Sharp/Core/GitDiff.cs

Lines changed: 11 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -133,6 +133,13 @@ internal enum GitDiffOptionFlags
133133
* Options controlling how output will be generated
134134
*/
135135

136+
/// <summary>
137+
/// Use a heuristic that takes indentation and whitespace into account
138+
/// which generally can produce better diffs when dealing with ambiguous
139+
/// diff hunks.
140+
/// </summary>
141+
GIT_DIFF_INDENT_HEURISTIC = (1 << 18),
142+
136143
/// <summary>
137144
/// Treat all files as text, disabling binary attributes and detection
138145
/// </summary>
@@ -304,11 +311,11 @@ enum GitDiffLineOrigin : byte
304311

305312
enum GitDiffFormat
306313
{
307-
GIT_DIFF_FORMAT_PATCH = 1, // < full git diff
314+
GIT_DIFF_FORMAT_PATCH = 1, // < full git diff
308315
GIT_DIFF_FORMAT_PATCH_HEADER = 2, // < just the file headers of patch
309-
GIT_DIFF_FORMAT_RAW = 3, // < like git diff --raw
310-
GIT_DIFF_FORMAT_NAME_ONLY = 4, // < like git diff --name-only
311-
GIT_DIFF_FORMAT_NAME_STATUS = 5, // < like git diff --name-status
316+
GIT_DIFF_FORMAT_RAW = 3, // < like git diff --raw
317+
GIT_DIFF_FORMAT_NAME_ONLY = 4, // < like git diff --name-only
318+
GIT_DIFF_FORMAT_NAME_STATUS = 5, // < like git diff --name-status
312319
}
313320

314321
[Flags]

LibGit2Sharp/Diff.cs

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -63,6 +63,11 @@ private static GitDiffOptions BuildOptions(DiffModifiers diffOptions, FilePath[]
6363
options.Flags |= GitDiffOptionFlags.GIT_DIFF_DISABLE_PATHSPEC_MATCH;
6464
}
6565

66+
if (compareOptions.IndentHeuristic)
67+
{
68+
options.Flags |= GitDiffOptionFlags.GIT_DIFF_INDENT_HEURISTIC;
69+
}
70+
6671
if (matchedPathsAggregator != null)
6772
{
6873
options.NotifyCallback = matchedPathsAggregator.OnGitDiffNotify;
@@ -351,7 +356,7 @@ public virtual T Compare<T>(Tree oldTree, DiffTargets diffTargets, IEnumerable<s
351356
}
352357

353358
DiffHandle diff = BuildDiffList(oldTreeId, null, comparer, diffOptions, paths, explicitPathsOptions, compareOptions);
354-
359+
355360
try
356361
{
357362
return BuildDiffResult<T>(diff);

0 commit comments

Comments
 (0)
0