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

Skip to content
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 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