8000 Make Diff.Compare able to compare a Tree against the Index · mm201/libgit2sharp@f8ee885 · GitHub
[go: up one dir, main page]

Skip to content

Commit f8ee885

Browse files
committed
Make Diff.Compare able to compare a Tree against the Index
1 parent 5bf2222 commit f8ee885

File tree

3 files changed

+210
-0
lines changed

3 files changed

+210
-0
lines changed
Lines changed: 153 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,153 @@
1+
using System.IO;
2+
using System.Linq;
3+
using System.Text;
4+
using LibGit2Sharp.Tests.TestHelpers;
5+
using Xunit;
6+
7+
namespace LibGit2Sharp.Tests
8+
{
9+
public class DiffTreeToTargetFixture : BaseFixture
10+
{
11+
private static void SetUpSimpleDiffContext(Repository repo)
12+
{
13+
var fullpath = Path.Combine(repo.Info.WorkingDirectory, "file.txt");
14+
File.WriteAllText(fullpath, "hello\n");
15+
16+
repo.Index.Stage(fullpath);
17+
repo.Commit("Initial commit", DummySignature, DummySignature);
18+
19+
File.AppendAllText(fullpath, "world\n");
20+
21+
repo.Index.Stage(fullpath);
22+
23+
File.AppendAllText(fullpath, "!!!\n");
24+
}
25+
26+
[Fact]
27+
/*
28+
* $ git diff --cached
29+
* diff --git a/file.txt b/file.txt
30+
* index ce01362..94954ab 100644
31+
* --- a/file.txt
32+
* +++ b/file.txt
33+
* @@ -1 +1,2 @@
34+
* hello
35+
* +world
36+
*/
37+
public void CanCompareASimpleTreeAgainstTheIndex()
38+
{
39+
var scd = BuildSelfCleaningDirectory();
40+
41+
using (var repo = Repository.Init(scd.RootedDirectoryPath))
42+
{
43+
SetUpSimpleDiffContext(repo);
44+
45+
TreeChanges changes = repo.Diff.Compare(repo.Head.Tip.Tree, DiffTarget.Index);
46+
47+
var expected = new StringBuilder()
48+
.Append("diff --git a/file.txt b/file.txt\n")
49+
.Append("index ce01362..94954ab 100644\n")
50+
.Append("--- a/file.txt\n")
51+
.Append("+++ b/file.txt\n")
52+
.Append("@@ -1 +1,2 @@\n")
53+
.Append(" hello\n")
54+
.Append("+world\n");
55+
56+
Assert.Equal(expected.ToString(), changes.Patch);
57+
}
58+
}
59+
60+
/*
61+
* $ git diff --cached
62+
* diff --git a/deleted_staged_file.txt b/deleted_staged_file.txt
63+
* deleted file mode 100644
64+
* index 5605472..0000000
65+
* --- a/deleted_staged_file.txt
66+
* +++ /dev/null
67+
* @@ -1 +0,0 @@
68+
* -things
69+
* diff --git a/modified_staged_file.txt b/modified_staged_file.txt
70+
* index 15d2ecc..e68bcc7 100644
71+
* --- a/modified_staged_file.txt
72+
* +++ b/modified_staged_file.txt
73+
* @@ -1 +1,2 @@
74+
* +a change
75+
* more files!
76+
* diff --git a/new_tracked_file.txt b/new_tracked_file.txt
77+
* new file mode 100644
78+
* index 0000000..935a81d
79+
* --- /dev/null
80+
* +++ b/new_tracked_file.txt
81+
* @@ -0,0 +1 @@
82+
* +a new file
83+
*/
84+
[Fact]
85+
public void CanCompareAMoreComplexTreeAgainstTheIndex()
86+
{
87+
using (var repo = new Repository(StandardTestRepoPath))
88+
{
89+
Tree tree = repo.Head.Tip.Tree;
90+
91+
TreeChanges changes = repo.Diff.Compare(tree, DiffTarget.Index);
92+
Assert.NotNull(changes);
93+
94+
Assert.Equal(3, changes.Count());
95+
Assert.Equal("deleted_staged_file.txt", changes.Deleted.Single().Path);
96+
Assert.Equal("new_tracked_file.txt", changes.Added.Single().Path);
97+
Assert.Equal("modified_staged_file.txt", changes.Modified.Single().Path);
98+
}
99+
}
100+
101+
[Fact]
102+
/*
103+
* $ git init .
104+
* $ echo -ne 'a' > file.txt
105+
* $ git add .
106+
* $ git commit -m "No line ending"
107+
* $ echo -ne '\n' >> file.txt
108+
* $ git add .
109+
* $ git diff --cached
110+
* diff --git a/file.txt b/file.txt
111+
* index 2e65efe..7898192 100644
112+
* --- a/file.txt
113+
* +++ b/file.txt
114+
* @@ -1 +1 @@
115+
* -a
116+
* \ No newline at end of file
117+
* +a
118+
*/
119+
public void CanCopeWithEndOfFileNewlineChanges()
120+
{
121+
var scd = BuildSelfCleaningDirectory();
122+
123+
using (var repo = Repository.Init(scd.RootedDirectoryPath))
124+
{
125+
var fullpath = Path.Combine(repo.Info.WorkingDirectory, "file.txt");
126+
File.WriteAllText(fullpath, "a");
127+
128+
repo.Index.Stage("file.txt");
129+
repo.Commit("Add file without line ending", DummySignature, DummySignature);
130+
131+
File.AppendAllText(fullpath, "\n");
132+
repo.Index.Stage("file.txt");
133+
134+
TreeChanges changes = repo.Diff.Compare(repo.Head.Tip.Tree, DiffTarget.Index);
135+
Assert.Equal(1, changes.Modified.Count());
136+
Assert.Equal(1, changes.LinesAdded);
137+
Assert.Equal(1, changes.LinesDeleted);
138+
139+
var expected = new StringBuilder()
140+
.Append("diff --git a/file.txt b/file.txt\n")
141+
.Append("index 2e65efe..7898192 100644\n")
142+
.Append("--- a/file.txt\n")
143+
.Append("+++ b/file.txt\n")
144+
.Append("@@ -1 +1 @@\n")
145+
.Append("-a\n")
146+
.Append("\\ No newline at end of file\n")
147+
.Append("+a\n");
148+
149+
Assert.Equal(expected.ToString(), changes.Patch);
150+
}
151+
}
152+
}
153+
}

LibGit2Sharp.Tests/LibGit2Sharp.Tests.csproj

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -47,6 +47,7 @@
4747
<Compile Include="AttributesFixture.cs" />
4848
<Compile Include="CommitAncestorFixture.cs" />
4949
<Compile Include="DiffBlobToBlobFixture.cs" />
50+
<Compile Include="DiffTreeToTargetFixture.cs" />
5051
<Compile Include="ObjectDatabaseFixture.cs" />
5152
<Compile Include="DiffTreeToTreeFixture.cs" />
5253
<Compile Include="RepositoryOptionsFixture.cs" />

LibGit2Sharp/Diff.cs

Lines changed: 56 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,5 @@
1+
using System;
2+
using System.Collections.Generic;
13
using LibGit2Sharp.Core;
24
using LibGit2Sharp.Core.Handles;
35

@@ -56,5 +58,59 @@ public ContentChanges Compare(Blob oldBlob, Blob newBlob)
5658
{
5759
return new ContentChanges(repo, oldBlob, newBlob, DefaultOptions);
5860
}
61+
62+
private readonly IDictionary<DiffTarget, Func<Repository, TreeComparisonHandleRetriever>> handleRetrieverDispatcher = BuildHandleRetrieverDispatcher();
63+
64+
private static IDictionary<DiffTarget, Func<Repository, TreeComparisonHandleRetriever>> BuildHandleRetrieverDispatcher()
65+
{
66+
return new Dictionary<DiffTarget, Func<Repository, TreeComparisonHandleRetriever>>
67+
{
68+
{ DiffTarget.Index, r => IndexToTree(r) },
69+
};
70+
}
71+
72+
/// <summary>
73+
/// Show changes between a <see cref = "Tree"/> and a selectable target.
74+
/// </summary>
75+
/// <param name = "oldTree">The <see cref = "Tree"/> to compare from.</param>
76+
/// <param name = "diffTarget">The target to compare to.</param>
77+
/// <returns>A <see cref = "TreeChanges"/> containing the changes between the <see cref="Tree"/> and the selected target.</returns>
78+
public TreeChanges Compare(Tree oldTree, DiffTarget diffTarget)
79+
{
80+
var comparer = handleRetrieverDispatcher[diffTarget](repo);
81+
82+
using (DiffListSafeHandle dl = BuildDiffListFromTreeAndComparer(repo, oldTree.Id, comparer))
83+
{
84+
return new TreeChanges(dl);
85+
}
86+
}
87+
88+
private delegate DiffListSafeHandle TreeComparisonHandleRetriever(GitObjectSafeHandle treeHandle, GitDiffOptions options);
89+
90+
private static TreeComparisonHandleRetriever IndexToTree(Repository repo)
91+
{
92+
TreeComparisonHandleRetriever comparisonHandleRetriever = (h, o) =>
93+
{
94+
DiffListSafeHandle diff;
95+
Ensure.Success(NativeMethods.git_diff_index_to_tree(repo.Handle, o, h, out diff));
96+
return diff;
97+
};
98+
99+
return comparisonHandleRetriever;
100+
}
101+
102+
private static DiffListSafeHandle BuildDiffListFromTreeAndComparer(Repository repo, ObjectId treeId, TreeComparisonHandleRetriever comparisonHandleRetriever)
103+
{
104+
using (var osw = new ObjectSafeWrapper(treeId, repo))
105+
{
106+
return BuildDiffListFromComparer(osw.ObjectPtr, comparisonHandleRetriever);
107+
}
108+
}
109+
110+
private static DiffListSafeHandle BuildDiffListFromComparer(GitObjectSafeHandle handle, TreeComparisonHandleRetriever comparisonHandleRetriever)
111+
{
112+
GitDiffOptions options = DefaultOptions;
113+
return comparisonHandleRetriever(handle, options);
114+
}
59115
}
60116
}

0 commit comments

Comments
 (0)
0