Permalink
Browse files

Make Diff.Compare able to work against the working directory and the …

…index


Fix #167
  • Loading branch information...
nulltoken committed Jun 12, 2012
1 parent c0bc893 commit bb202dc9b1428f8b9ec02473f95f6b140ee77a67
@@ -23,6 +23,146 @@ private static void SetUpSimpleDiffContext(Repository repo)
File.AppendAllText(fullpath, "!!!\n");
}
+ [Fact]
+ /*
+ * No direct git equivalent but should output
+ *
+ * diff --git a/file.txt b/file.txt
+ * index ce01362..4f125e3 100644
+ * --- a/file.txt
+ * +++ b/file.txt
+ * @@ -1 +1,3 @@
+ * hello
+ * +world
+ * +!!!
+ */
+ public void CanCompareASimpleTreeAgainstTheWorkDir()
+ {
+ var scd = BuildSelfCleaningDirectory();
+
+ using (var repo = Repository.Init(scd.RootedDirectoryPath))
+ {
+ SetUpSimpleDiffContext(repo);
+
+ TreeChanges changes = repo.Diff.Compare(repo.Head.Tip.Tree, DiffTarget.WorkingDirectory);
+
+ var expected = new StringBuilder()
+ .Append("diff --git a/file.txt b/file.txt\n")
+ .Append("index ce01362..4f125e3 100644\n")
+ .Append("--- a/file.txt\n")
+ .Append("+++ b/file.txt\n")
+ .Append("@@ -1 +1,3 @@\n")
+ .Append(" hello\n")
+ .Append("+world\n")
+ .Append("+!!!\n");
+
+ Assert.Equal(expected.ToString(), changes.Patch);
+ }
+ }
+
+ [Fact]
+ /*
+ * $ git diff HEAD
+ * diff --git a/file.txt b/file.txt
+ * index ce01362..4f125e3 100644
+ * --- a/file.txt
+ * +++ b/file.txt
+ * @@ -1 +1,3 @@
+ * hello
+ * +world
+ * +!!!
+ */
+ public void CanCompareASimpleTreeAgainstTheWorkDirAndTheIndex()
+ {
+ var scd = BuildSelfCleaningDirectory();
+
+ using (var repo = Repository.Init(scd.RootedDirectoryPath))
+ {
+ SetUpSimpleDiffContext(repo);
+
+ TreeChanges changes = repo.Diff.Compare(repo.Head.Tip.Tree, DiffTarget.BothWorkingDirectoryAndIndex);
+
+ var expected = new StringBuilder()
+ .Append("diff --git a/file.txt b/file.txt\n")
+ .Append("index ce01362..4f125e3 100644\n")
+ .Append("--- a/file.txt\n")
+ .Append("+++ b/file.txt\n")
+ .Append("@@ -1 +1,3 @@\n")
+ .Append(" hello\n")
+ .Append("+world\n")
+ .Append("+!!!\n");
+
+ Assert.Equal(expected.ToString(), changes.Patch);
+ }
+ }
+
+
+ [Fact]
+ /*
+ * $ git diff
+ *
+ * $ git diff HEAD
+ * diff --git a/file.txt b/file.txt
+ * deleted file mode 100644
+ * index ce01362..0000000
+ * --- a/file.txt
+ * +++ /dev/null
+ * @@ -1 +0,0 @@
+ * -hello
+ *
+ * $ git diff --cached
+ * diff --git a/file.txt b/file.txt
+ * deleted file mode 100644
+ * index ce01362..0000000
+ * --- a/file.txt
+ * +++ /dev/null
+ * @@ -1 +0,0 @@
+ * -hello
+ */
+ public void ShowcaseTheDifferenceBetweenTheTwoKindOfComparison()
+ {
+ var scd = BuildSelfCleaningDirectory();
+
+ using (var repo = Repository.Init(scd.RootedDirectoryPath))
+ {
+ SetUpSimpleDiffContext(repo);
+
+ var fullpath = Path.Combine(repo.Info.WorkingDirectory, "file.txt");
+ File.Move(fullpath, fullpath + ".bak");
+ repo.Index.Stage(fullpath);
+ File.Move(fullpath + ".bak", fullpath);
+
+ FileStatus state = repo.Index.RetrieveStatus("file.txt");
+ Assert.Equal(FileStatus.Removed | FileStatus.Untracked, state);
+
+
+ TreeChanges wrkDirToIdxToTree = repo.Diff.Compare(repo.Head.Tip.Tree, DiffTarget.BothWorkingDirectoryAndIndex);
+ var expected = new StringBuilder()
+ .Append("diff --git a/file.txt b/file.txt\n")
+ .Append("deleted file mode 100644\n")
+ .Append("index ce01362..0000000\n")
+ .Append("--- a/file.txt\n")
+ .Append("+++ /dev/null\n")
+ .Append("@@ -1 +0,0 @@\n")
+ .Append("-hello\n");
+
+ Assert.Equal(expected.ToString(), wrkDirToIdxToTree.Patch);
+
+ TreeChanges wrkDirToTree = repo.Diff.Compare(repo.Head.Tip.Tree, DiffTarget.WorkingDirectory);
+ expected = new StringBuilder()
+ .Append("diff --git a/file.txt b/file.txt\n")
+ .Append("index ce01362..4f125e3 100644\n")
+ .Append("--- a/file.txt\n")
+ .Append("+++ b/file.txt\n")
+ .Append("@@ -1 +1,3 @@\n")
+ .Append(" hello\n")
+ .Append("+world\n")
+ .Append("+!!!\n");
+
+ Assert.Equal(expected.ToString(), wrkDirToTree.Patch);
+ }
+ }
+
[Fact]
/*
* $ git diff --cached
@@ -0,0 +1,39 @@
+using System.Linq;
+using LibGit2Sharp.Tests.TestHelpers;
+using Xunit;
+
+namespace LibGit2Sharp.Tests
+{
+ public class DiffWorkdirToIndexFixture : BaseFixture
+ {
+ /*
+ * $ git diff
+ * diff --git a/deleted_unstaged_file.txt b/deleted_unstaged_file.txt
+ * deleted file mode 100644
+ * index f2e4113..0000000
+ * --- a/deleted_unstaged_file.txt
+ * +++ /dev/null
+ * @@ -1 +0,0 @@
+ * -stuff
+ * diff --git a/modified_unstaged_file.txt b/modified_unstaged_file.txt
+ * index 9217230..da6fd65 100644
+ * --- a/modified_unstaged_file.txt
+ * +++ b/modified_unstaged_file.txt
+ * @@ -1 +1,2 @@
+ * +some more text
+ * more files! more files!
+ */
+ [Fact]
+ public void CanCompareTheWorkDirAgainstTheIndex()
+ {
+ using (var repo = new Repository(StandardTestRepoPath))
+ {
+ TreeChanges changes = repo.Diff.Compare();
+
+ Assert.Equal(2, changes.Count());
+ Assert.Equal("deleted_unstaged_file.txt", changes.Deleted.Single().Path);
+ Assert.Equal("modified_unstaged_file.txt", changes.Modified.Single().Path);
+ }
+ }
+ }
+}
@@ -84,6 +84,7 @@ public void ReadIndexWithBadParamsFails()
[Theory]
[InlineData("1/branch_file.txt", FileStatus.Unaltered, true, FileStatus.Unaltered, true, 0)]
+ [InlineData("README", FileStatus.Unaltered, true, FileStatus.Unaltered, true, 0)]
[InlineData("deleted_unstaged_file.txt", FileStatus.Missing, true, FileStatus.Removed, false, -1)]
[InlineData("modified_unstaged_file.txt", FileStatus.Modified, true, FileStatus.Staged, true, 0)]
[InlineData("new_untracked_file.txt", FileStatus.Untracked, false, FileStatus.Added, true, 1)]
@@ -65,6 +65,7 @@
<Compile Include="NoteFixture.cs" />
<Compile Include="DiffBlobToBlobFixture.cs" />
<Compile Include="DiffTreeToTargetFixture.cs" />
+ <Compile Include="DiffWorkdirToIndexFixture.cs" />
<Compile Include="ObjectDatabaseFixture.cs" />
<Compile Include="DiffTreeToTreeFixture.cs" />
<Compile Include="RepositoryOptionsFixture.cs" />
View
@@ -113,6 +113,8 @@ public virtual ContentChanges Compare(Blob oldBlob, Blob newBlob)
return new Dictionary<DiffTarget, Func<Repository, TreeComparisonHandleRetriever>>
{
{ DiffTarget.Index, r => IndexToTree(r) },
+ { DiffTarget.WorkingDirectory, r => WorkdirToTree(r) },
+ { DiffTarget.BothWorkingDirectoryAndIndex, r => WorkdirAndIndexToTree(r) },
};
}
@@ -136,8 +138,76 @@ public virtual TreeChanges Compare(Tree oldTree, DiffTarget diffTarget, IEnumera
}
}
+ /// <summary>
+ /// Show changes between the working directory and the index.
+ /// </summary>
+ /// <param name = "paths">The list of paths (either files or directories) that should be compared.</param>
+ /// <returns>A <see cref = "TreeChanges"/> containing the changes between the working directory and the index.</returns>
+ public virtual TreeChanges Compare(IEnumerable<string> paths = null)
+ {
+ var comparer = WorkdirToIndex(repo);
+
+ using (GitDiffOptions options = BuildOptions(paths))
+ using (DiffListSafeHandle dl = BuildDiffListFromComparer(null, comparer, options))
+ {
+ return new TreeChanges(dl);
+ }
+ }
+
private delegate DiffListSafeHandle TreeComparisonHandleRetriever(GitObjectSafeHandle treeHandle, GitDiffOptions options);
+ private static TreeComparisonHandleRetriever WorkdirToIndex(Repository repo)
+ {
+ TreeComparisonHandleRetriever comparisonHandleRetriever = (h, o) =>
+ {
+ DiffListSafeHandle diff;
+ Ensure.Success(NativeMethods.git_diff_workdir_to_index(repo.Handle, o, out diff));
+ return diff;
+ };
+
+ return comparisonHandleRetriever;
+ }
+
+ private static TreeComparisonHandleRetriever WorkdirToTree(Repository repo)
+ {
+ TreeComparisonHandleRetriever comparisonHandleRetriever = (h, o) =>
+ {
+ DiffListSafeHandle diff;
+ Ensure.Success(NativeMethods.git_diff_workdir_to_tree(repo.Handle, o, h, out diff));
+ return diff;
+ };
+
+ return comparisonHandleRetriever;
+ }
+
+ private static TreeComparisonHandleRetriever WorkdirAndIndexToTree(Repository repo)
+ {
+ TreeComparisonHandleRetriever comparisonHandleRetriever = (h, o) =>
+ {
+ DiffListSafeHandle diff = null, diff2 = null;
+
+ try
+ {
+ Ensure.Success(NativeMethods.git_diff_index_to_tree(repo.Handle, o, h, out diff));
+ Ensure.Success(NativeMethods.git_diff_workdir_to_index(repo.Handle, o, out diff2));
+ Ensure.Success(NativeMethods.git_diff_merge(diff, diff2));
+ }
+ catch
+ {
+ diff.SafeDispose();
+ throw;
+ }
+ finally
+ {
+ diff2.SafeDispose();
+ }
+
+ return diff;
+ };
+
+ return comparisonHandleRetriever;
+ }
+
private static TreeComparisonHandleRetriever IndexToTree(Repository repo)
{
TreeComparisonHandleRetriever comparisonHandleRetriever = (h, o) =>
View
@@ -1,13 +1,23 @@
namespace LibGit2Sharp
{
/// <summary>
- /// The target for a diff comparison.
+ /// The target of a Tree based diff comparison.
/// </summary>
public enum DiffTarget
{
+ /// <summary>
+ /// The working directory.
+ /// </summary>
+ WorkingDirectory,
+
/// <summary>
/// The repository index.
/// </summary>
Index,
+
+ /// <summary>
+ /// Both the working directory and the repository index.
+ /// </summary>
+ BothWorkingDirectoryAndIndex,
}
}

0 comments on commit bb202dc

Please sign in to comment.