Skip to content

Commit 3db50fc

Browse files
committed
Make Diff.Compare able to expose type changes
Fix #196
1 parent 6b9afb2 commit 3db50fc

File tree

6 files changed

+100
-8
lines changed

6 files changed

+100
-8
lines changed

LibGit2Sharp.Tests/DiffTreeToTreeFixture.cs

Lines changed: 72 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -356,6 +356,78 @@ public void CanCompareTwoVersionsOfAFileWithADiffOfTwoHunks()
356356
}
357357
}
358358

359+
[Fact]
360+
public void CanHandleTwoTreeEntryChangesWithTheSamePath()
361+
{
362+
SelfCleaningDirectory scd = BuildSelfCleaningDirectory();
363+
364+
using (Repository repo = Repository.Init(scd.DirectoryPath))
365+
{
366+
Blob mainContent = CreateBlob(repo, "awesome content\n");
367+
Blob linkContent = CreateBlob(repo, "../../objc/Nu.h");
368+
369+
string path = string.Format("include{0}Nu{0}Nu.h", Path.DirectorySeparatorChar);
370+
371+
var tdOld = new TreeDefinition()
372+
.Add(path, linkContent, Mode.SymbolicLink)
373+
.Add("objc/Nu.h", mainContent, Mode.NonExecutableFile);
374+
375+
Tree treeOld = repo.ObjectDatabase.CreateTree(tdOld);
376+
377+
var tdNew = new TreeDefinition()
378+
.Add(path, mainContent, Mode.NonExecutableFile);
379+
380+
Tree treeNew = repo.ObjectDatabase.CreateTree(tdNew);
381+
382+
TreeChanges changes = repo.Diff.Compare(treeOld, treeNew);
383+
384+
/*
385+
* $ git diff-tree -p 5c87b67 d5278d0
386+
* diff --git a/include/Nu/Nu.h b/include/Nu/Nu.h
387+
* deleted file mode 120000
388+
* index 19bf568..0000000
389+
* --- a/include/Nu/Nu.h
390+
* +++ /dev/null
391+
* @@ -1 +0,0 @@
392+
* -../../objc/Nu.h
393+
* \ No newline at end of file
394+
* diff --git a/include/Nu/Nu.h b/include/Nu/Nu.h
395+
* new file mode 100644
396+
* index 0000000..f9e6561
397+
* --- /dev/null
398+
* +++ b/include/Nu/Nu.h
399+
* @@ -0,0 +1 @@
400+
* +awesome content
401+
* diff --git a/objc/Nu.h b/objc/Nu.h
402+
* deleted file mode 100644
403+
* index f9e6561..0000000
404+
* --- a/objc/Nu.h
405+
* +++ /dev/null
406+
* @@ -1 +0,0 @@
407+
* -awesome content
408+
*/
409+
410+
Assert.Equal(1, changes.Deleted.Count());
411+
Assert.Equal(0, changes.Modified.Count());
412+
Assert.Equal(1, changes.TypeChanged.Count());
413+
414+
TreeEntryChanges change = changes[path];
415+
Assert.Equal(Mode.SymbolicLink, change.OldMode);
416+
Assert.Equal(Mode.NonExecutableFile, change.Mode);
417+
Assert.Equal(ChangeKind.TypeChanged, change.Status);
418+
Assert.Equal(path, change.Path);
419+
}
420+
}
421+
422+
private static Blob CreateBlob(Repository repo, string content)
423+
{
424+
using (var stream = new MemoryStream(Encoding.UTF8.GetBytes(content)))
425+
using (var binReader = new BinaryReader(stream))
426+
{
427+
return repo.ObjectDatabase.CreateBlob(binReader);
428+
}
429+
}
430+
359431
[Fact]
360432
public void CanCompareATreeAgainstANullTree()
361433
{

LibGit2Sharp/ChangeKind.cs

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -44,5 +44,11 @@ public enum ChangeKind
4444
/// The file is untracked in the workdir.
4545
/// </summary>
4646
Untracked = 7,
47+
48+
/// <summary>
49+
/// The type (i.e. regular file, symlink, submodule, ...)
50+
/// of the file was changed.
51+
/// </summary>
52+
TypeChanged = 8,
4753
}
48-
}
54+
}

LibGit2Sharp/Diff.cs

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,8 @@ private GitDiffOptions BuildOptions(DiffOptions diffOptions, IEnumerable<string>
2222
{
2323
var options = new GitDiffOptions();
2424

25+
options.Flags |= GitDiffOptionFlags.GIT_DIFF_INCLUDE_TYPECHANGE;
26+
2527
if (diffOptions.HasFlag(DiffOptions.IncludeUntracked))
2628
{
2729
options.Flags |= GitDiffOptionFlags.GIT_DIFF_INCLUDE_UNTRACKED |

LibGit2Sharp/TreeChanges.cs

Lines changed: 13 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,7 @@ public class TreeChanges : IEnumerable<TreeEntryChanges>
2121
private readonly List<TreeEntryChanges> added = new List<TreeEntryChanges>();
2222
private readonly List<TreeEntryChanges> deleted = new List<TreeEntryChanges>();
2323
private readonly List<TreeEntryChanges> modified = new List<TreeEntryChanges>();
24+
private readonly List<TreeEntryChanges> typeChanged = new List<TreeEntryChanges>();
2425
private int linesAdded;
2526
private int linesDeleted;
2627

@@ -37,6 +38,7 @@ private static IDictionary<ChangeKind, Action<TreeChanges, TreeEntryChanges>> Bu
3738
{ ChangeKind.Modified, (de, d) => de.modified.Add(d) },
3839
{ ChangeKind.Deleted, (de, d) => de.deleted.Add(d) },
3940
{ ChangeKind.Added, (de, d) => de.added.Add(d) },
41+
{ ChangeKind.TypeChanged, (de, d) => de.typeChanged.Add(d) },
4042
};
4143
}
4244

@@ -176,6 +178,14 @@ public virtual IEnumerable<TreeEntryChanges> Modified
176178
get { return modified; }
177179
}
178180

181+
/// <summary>
182+
/// List of <see cref = "TreeEntryChanges"/> which type have been changed.
183+
/// </summary>
184+
public virtual IEnumerable<TreeEntryChanges> TypeChanged
185+
{
186+
get { return typeChanged; }
187+
}
188+
179189
/// <summary>
180190
/// The total number of lines added in this diff.
181191
/// </summary>
@@ -205,8 +215,9 @@ private string DebuggerDisplay
205215
get
206216
{
207217
return string.Format(CultureInfo.InvariantCulture,
208-
"Added: {0}, Deleted: {1}, Modified: {2}",
209-
Added.Count(), Deleted.Count(), Modified.Count());
218+
"Add: {0}, Del: {1}, Mod: {2}, Typ: {3}",
219+
Added.Count(), Deleted.Count(),
220+
Modified.Count(), TypeChanged.Count());
210221
}
211222
}
212223
}

LibGit2Sharp/TreeDefinition.cs

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
using System;
1+
using System;
22
using System.Collections.Generic;
33
using System.Globalization;
44
using System.IO;
@@ -135,8 +135,7 @@ public virtual TreeDefinition Add(string targetTreeEntryPath, TreeEntryDefinitio
135135
public virtual TreeDefinition Add(string targetTreeEntryPath, Blob blob, Mode mode)
136136
{
137137
Ensure.ArgumentNotNull(blob, "blob");
138-
Ensure.ArgumentConformsTo(mode,
139-
m => m.HasAny(new[] { Mode.ExecutableFile, Mode.NonExecutableFile, Mode.NonExecutableGroupWritableFile }), "mode");
138+
Ensure.ArgumentConformsTo(mode, m => m.HasAny(TreeEntryDefinition.BlobModes), "mode");
140139

141140
TreeEntryDefinition ted = TreeEntryDefinition.From(blob, mode);
142141

LibGit2Sharp/TreeEntryDefinition.cs

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
using System;
1+
using System;
22
using LibGit2Sharp.Core;
33
using LibGit2Sharp.Core.Compat;
44

@@ -14,6 +14,8 @@ public class TreeEntryDefinition : IEquatable<TreeEntryDefinition>
1414
private static readonly LambdaEqualityHelper<TreeEntryDefinition> equalityHelper =
1515
new LambdaEqualityHelper<TreeEntryDefinition>(x => x.Mode, x => x.Type, x => x.TargetId);
1616

17+
internal static readonly Mode[] BlobModes = new[] { Mode.NonExecutableFile, Mode.ExecutableFile, Mode.NonExecutableGroupWritableFile, Mode.SymbolicLink };
18+
1719
/// <summary>
1820
/// Needed for mocking purposes.
1921
/// </summary>
@@ -65,7 +67,7 @@ internal static TreeEntryDefinition From(Blob blob, Mode mode)
6567

6668
internal static TreeEntryDefinition TransientBlobFrom(string filePath, Mode mode)
6769
{
68-
Ensure.ArgumentConformsTo(mode, m => m.HasAny(new[] { Mode.NonExecutableFile, Mode.ExecutableFile, Mode.NonExecutableGroupWritableFile }), "mode");
70+
Ensure.ArgumentConformsTo(mode, m => m.HasAny(BlobModes), "mode");
6971

7072
return new TransientBlobTreeEntryDefinition
7173
{

0 commit comments

Comments
 (0)