diff options
author | Jameson Miller <jamill@microsoft.com> | 2014-05-04 08:54:22 +0400 |
---|---|---|
committer | nulltoken <emeric.fermas@gmail.com> | 2014-05-14 14:37:11 +0400 |
commit | 10ae2aa0d21c03fcc7d07bce17ebc7fc702dce19 (patch) | |
tree | c64a58832bd084bb12c3979c650f8a526705cbb7 /LibGit2Sharp.Tests | |
parent | 469e6da79c9e83fad9cab001b3e6f4bc0c56fc89 (diff) |
Continue implementing revert
Diffstat (limited to 'LibGit2Sharp.Tests')
15 files changed, 404 insertions, 4 deletions
diff --git a/LibGit2Sharp.Tests/Resources/revert_testrepo_wd/a.txt b/LibGit2Sharp.Tests/Resources/revert_testrepo_wd/a.txt new file mode 100644 index 00000000..bc90ea42 --- /dev/null +++ b/LibGit2Sharp.Tests/Resources/revert_testrepo_wd/a.txt @@ -0,0 +1,7 @@ +This is file a.txt +This is the 3rd revision of this file. +It +also +has +several +lines.
\ No newline at end of file diff --git a/LibGit2Sharp.Tests/Resources/revert_testrepo_wd/b.txt b/LibGit2Sharp.Tests/Resources/revert_testrepo_wd/b.txt new file mode 100644 index 00000000..1ca53b49 --- /dev/null +++ b/LibGit2Sharp.Tests/Resources/revert_testrepo_wd/b.txt @@ -0,0 +1,7 @@ +This is file b.txt +This is the 3rd revision of this file. +It +also +has +several +lines.
\ No newline at end of file diff --git a/LibGit2Sharp.Tests/Resources/revert_testrepo_wd/c.txt b/LibGit2Sharp.Tests/Resources/revert_testrepo_wd/c.txt new file mode 100644 index 00000000..88925a54 --- /dev/null +++ b/LibGit2Sharp.Tests/Resources/revert_testrepo_wd/c.txt @@ -0,0 +1,7 @@ +This is file c.txt +This is the 3rd revision of this file. +It +also +has +several +lines.
\ No newline at end of file diff --git a/LibGit2Sharp.Tests/Resources/revert_testrepo_wd/dot_git/HEAD b/LibGit2Sharp.Tests/Resources/revert_testrepo_wd/dot_git/HEAD new file mode 100644 index 00000000..cb089cd8 --- /dev/null +++ b/LibGit2Sharp.Tests/Resources/revert_testrepo_wd/dot_git/HEAD @@ -0,0 +1 @@ +ref: refs/heads/master diff --git a/LibGit2Sharp.Tests/Resources/revert_testrepo_wd/dot_git/config b/LibGit2Sharp.Tests/Resources/revert_testrepo_wd/dot_git/config new file mode 100644 index 00000000..78387c50 --- /dev/null +++ b/LibGit2Sharp.Tests/Resources/revert_testrepo_wd/dot_git/config @@ -0,0 +1,8 @@ +[core] + repositoryformatversion = 0 + filemode = false + bare = false + logallrefupdates = true + symlinks = false + ignorecase = true + hideDotFiles = dotGitOnly diff --git a/LibGit2Sharp.Tests/Resources/revert_testrepo_wd/dot_git/index b/LibGit2Sharp.Tests/Resources/revert_testrepo_wd/dot_git/index Binary files differnew file mode 100644 index 00000000..4dacdda3 --- /dev/null +++ b/LibGit2Sharp.Tests/Resources/revert_testrepo_wd/dot_git/index diff --git a/LibGit2Sharp.Tests/Resources/revert_testrepo_wd/dot_git/objects/info/packs b/LibGit2Sharp.Tests/Resources/revert_testrepo_wd/dot_git/objects/info/packs new file mode 100644 index 00000000..59da9792 --- /dev/null +++ b/LibGit2Sharp.Tests/Resources/revert_testrepo_wd/dot_git/objects/info/packs @@ -0,0 +1,2 @@ +P pack-29d1a036908407037b737d1cb436707551c3cedf.pack + diff --git a/LibGit2Sharp.Tests/Resources/revert_testrepo_wd/dot_git/objects/pack/pack-29d1a036908407037b737d1cb436707551c3cedf.idx b/LibGit2Sharp.Tests/Resources/revert_testrepo_wd/dot_git/objects/pack/pack-29d1a036908407037b737d1cb436707551c3cedf.idx Binary files differnew file mode 100644 index 00000000..ce6281cd --- /dev/null +++ b/LibGit2Sharp.Tests/Resources/revert_testrepo_wd/dot_git/objects/pack/pack-29d1a036908407037b737d1cb436707551c3cedf.idx diff --git a/LibGit2Sharp.Tests/Resources/revert_testrepo_wd/dot_git/objects/pack/pack-29d1a036908407037b737d1cb436707551c3cedf.pack b/LibGit2Sharp.Tests/Resources/revert_testrepo_wd/dot_git/objects/pack/pack-29d1a036908407037b737d1cb436707551c3cedf.pack Binary files differnew file mode 100644 index 00000000..e1eee599 --- /dev/null +++ b/LibGit2Sharp.Tests/Resources/revert_testrepo_wd/dot_git/objects/pack/pack-29d1a036908407037b737d1cb436707551c3cedf.pack diff --git a/LibGit2Sharp.Tests/Resources/revert_testrepo_wd/dot_git/refs/heads/master b/LibGit2Sharp.Tests/Resources/revert_testrepo_wd/dot_git/refs/heads/master new file mode 100644 index 00000000..743c907a --- /dev/null +++ b/LibGit2Sharp.Tests/Resources/revert_testrepo_wd/dot_git/refs/heads/master @@ -0,0 +1 @@ +cb4f7f0eca7a0114cdafd8537332aa17de36a4e9 diff --git a/LibGit2Sharp.Tests/Resources/revert_testrepo_wd/dot_git/refs/heads/revert b/LibGit2Sharp.Tests/Resources/revert_testrepo_wd/dot_git/refs/heads/revert new file mode 100644 index 00000000..7438cbb2 --- /dev/null +++ b/LibGit2Sharp.Tests/Resources/revert_testrepo_wd/dot_git/refs/heads/revert @@ -0,0 +1 @@ +b6fbb29b625aabe0fb5736da6fd61d4147e4405e diff --git a/LibGit2Sharp.Tests/Resources/revert_testrepo_wd/dot_git/refs/heads/revert_merge b/LibGit2Sharp.Tests/Resources/revert_testrepo_wd/dot_git/refs/heads/revert_merge new file mode 100644 index 00000000..0a6cfc12 --- /dev/null +++ b/LibGit2Sharp.Tests/Resources/revert_testrepo_wd/dot_git/refs/heads/revert_merge @@ -0,0 +1 @@ +2747045c29b5b9c5624225ce600f3117fdcf0b87 diff --git a/LibGit2Sharp.Tests/Resources/revert_testrepo_wd/dot_git/refs/heads/revert_rename b/LibGit2Sharp.Tests/Resources/revert_testrepo_wd/dot_git/refs/heads/revert_rename new file mode 100644 index 00000000..c2ca6d98 --- /dev/null +++ b/LibGit2Sharp.Tests/Resources/revert_testrepo_wd/dot_git/refs/heads/revert_rename @@ -0,0 +1 @@ +c4b5cea70e4cd5b633ed0f10ae0ed5384e8190d8 diff --git a/LibGit2Sharp.Tests/RevertFixture.cs b/LibGit2Sharp.Tests/RevertFixture.cs index c2ad3881..33474527 100644 --- a/LibGit2Sharp.Tests/RevertFixture.cs +++ b/LibGit2Sharp.Tests/RevertFixture.cs @@ -1,18 +1,375 @@ +using System.IO; +using System.Linq; using LibGit2Sharp.Tests.TestHelpers; using Xunit; +using Xunit.Extensions; +using System; namespace LibGit2Sharp.Tests { public class RevertFixture : BaseFixture { [Fact] - public void RevertDoesntCrash() + public void CanRevert() { - string path = CloneStandardTestRepo(); + // The branch name to perform the revert on, + // and the file whose contents we expect to be reverted. + const string revertBranchName = "refs/heads/revert"; + const string revertedFile = "a.txt"; + + string path = CloneRevertTestRepo(); + using (var repo = new Repository(path)) + { + // Checkout the revert branch. + Branch branch = repo.Checkout(revertBranchName); + Assert.NotNull(branch); + + // Revert tip commit. + RevertResult result = repo.Revert(repo.Head.Tip, Constants.Signature); + Assert.NotNull(result); + Assert.Equal(RevertStatus.Reverted, result.Status); + + // Verify commit was made. + Assert.NotNull(result.Commit); + + // Verify the expected commit ID. + Assert.Equal("04746060fa753c9970d88a0b59151d7b212ac903", result.Commit.Id.Sha); + + // Verify workspace is clean. + Assert.True(repo.Index.IsFullyMerged); + Assert.False(repo.Index.RetrieveStatus().IsDirty); + + // Lookup the blob containing the expected reverted content of a.txt. + Blob expectedBlob = repo.Lookup<Blob>("bc90ea420cf6c5ae3db7dcdffa0d79df567f219b"); + Assert.NotNull(expectedBlob); + + // Verify contents of Index. + IndexEntry revertedIndexEntry = repo.Index[revertedFile]; + Assert.NotNull(revertedIndexEntry); + + // Verify the contents of the index. + Assert.Equal(expectedBlob.Id, revertedIndexEntry.Id); + + // Verify contents of workspace. + string fullPath = Path.Combine(repo.Info.WorkingDirectory, revertedFile); + Assert.Equal(expectedBlob.GetContentText(new FilteringOptions(revertedFile)), File.ReadAllText(fullPath)); + } + } + + [Fact] + public void CanRevertAndNotCommit() + { + // The branch name to perform the revert on, + // and the file whose contents we expect to be reverted. + const string revertBranchName = "refs/heads/revert"; + const string revertedFile = "a.txt"; + + string path = CloneRevertTestRepo(); using (var repo = new Repository(path)) { - repo.Reset(ResetMode.Hard); - repo.Revert(repo.Head.Tip); + string modifiedFileFullPath = Path.Combine(repo.Info.WorkingDirectory, revertedFile); + + // Checkout the revert branch. + Branch branch = repo.Checkout(revertBranchName); + Assert.NotNull(branch); + + // Revert tip commit. + RevertResult result = repo.Revert(repo.Head.Tip, Constants.Signature, new RevertOptions() { CommitOnSuccess = false }); + Assert.NotNull(result); + Assert.Equal(RevertStatus.Reverted, result.Status); + + // Verify the commit was made. + Assert.Null(result.Commit); + + // Verify workspace is dirty. + FileStatus fileStatus = repo.Index.RetrieveStatus(revertedFile); + Assert.Equal(FileStatus.Staged, fileStatus); + + // This is the ID of the blob containing the expected content. + Blob expectedBlob = repo.Lookup<Blob>("bc90ea420cf6c5ae3db7dcdffa0d79df567f219b"); + Assert.NotNull(expectedBlob); + + // Verify contents of Index. + IndexEntry revertedIndexEntry = repo.Index[revertedFile]; + Assert.NotNull(revertedIndexEntry); + + Assert.Equal(expectedBlob.Id, revertedIndexEntry.Id); + + // Verify contents of workspace. + string fullPath = Path.Combine(repo.Info.WorkingDirectory, revertedFile); + Assert.Equal(expectedBlob.GetContentText(new FilteringOptions(revertedFile)), File.ReadAllText(fullPath)); + } + } + + [Fact] + public void RevertWithConflictDoesNotCommit() + { + // The branch name to perform the revert on, + // and the file whose contents we expect to be reverted. + const string revertBranchName = "refs/heads/revert"; + + string path = CloneRevertTestRepo(); + using (var repo = new Repository(path)) + { + // Checkout the revert branch. + Branch branch = repo.Checkout(revertBranchName); + Assert.NotNull(branch); + + // The commit to revert - we know that reverting this + // specific commit will generate conflicts. + Commit commitToRevert = repo.Lookup<Commit>("cb4f7f0eca7a0114cdafd8537332aa17de36a4e9"); + Assert.NotNull(commitToRevert); + + // Perform the revert and verify there were conflicts. + RevertResult result = repo.Revert(commitToRevert, Constants.Signature); + Assert.NotNull(result); + Assert.Equal(RevertStatus.Conflicts, result.Status); + Assert.Null(result.Commit); + + // Verify there is a conflict on the expected path. + Assert.False(repo.Index.IsFullyMerged); + Assert.NotNull(repo.Index.Conflicts["a.txt"]); + + // Verify the non-conflicting paths are staged. + Assert.Equal(FileStatus.Staged, repo.Index.RetrieveStatus("b.txt")); + Assert.Equal(FileStatus.Staged, repo.Index.RetrieveStatus("c.txt")); + } + } + + [Theory] + [InlineData(CheckoutFileConflictStrategy.Ours)] + [InlineData(CheckoutFileConflictStrategy.Theirs)] + public void RevertWithFileConflictStrategyOption(CheckoutFileConflictStrategy conflictStrategy) + { + // The branch name to perform the revert on, + // and the file which we expect conflicts as result of the revert. + const string revertBranchName = "refs/heads/revert"; + const string conflictedFilePath = "a.txt"; + + string path = CloneRevertTestRepo(); + using (var repo = new Repository(path)) + { + // Checkout the revert branch. + Branch branch = repo.Checkout(revertBranchName); + Assert.NotNull(branch); + + // Specify FileConflictStrategy. + RevertOptions options = new RevertOptions() + { + FileConflictStrategy = conflictStrategy, + }; + + RevertResult result = repo.Revert(repo.Head.Tip.Parents.First(), Constants.Signature, options); + + // Verify there is a conflict. + Assert.False(repo.Index.IsFullyMerged); + + Conflict conflict = repo.Index.Conflicts[conflictedFilePath]; + Assert.NotNull(conflict); + + Assert.NotNull(conflict); + Assert.NotNull(conflict.Theirs); + Assert.NotNull(conflict.Ours); + + // Get the blob containing the expected content. + Blob expectedBlob = null; + switch (conflictStrategy) + { + case CheckoutFileConflictStrategy.Theirs: + expectedBlob = repo.Lookup<Blob>(conflict.Theirs.Id); + break; + case CheckoutFileConflictStrategy.Ours: + expectedBlob = repo.Lookup<Blob>(conflict.Ours.Id); + break; + default: + throw new Exception("Unexpected FileConflictStrategy"); + } + + Assert.NotNull(expectedBlob); + + // Check the content of the file on disk matches what is expected. + string expectedContent = expectedBlob.GetContentText(new FilteringOptions(conflictedFilePath)); + Assert.Equal(expectedContent, File.ReadAllText(Path.Combine(repo.Info.WorkingDirectory, conflictedFilePath))); + } + } + + [Fact] + public void RevertReportsCheckoutProgress() + { + const string revertBranchName = "refs/heads/revert"; + + string repoPath = CloneRevertTestRepo(); + using (var repo = new Repository(repoPath)) + { + // Checkout the revert branch. + Branch branch = repo.Checkout(revertBranchName); + Assert.NotNull(branch); + + bool wasCalled = false; + + RevertOptions options = new RevertOptions() + { + OnCheckoutProgress = (path, completed, total) => wasCalled = true + }; + + repo.Revert(repo.Head.Tip, Constants.Signature, options); + + Assert.True(wasCalled); + } + } + + [Fact] + public void RevertReportsCheckoutNotification() + { + const string revertBranchName = "refs/heads/revert"; + + string repoPath = CloneRevertTestRepo(); + using (var repo = new Repository(repoPath)) + { + // Checkout the revert branch. + Branch branch = repo.Checkout(revertBranchName); + Assert.NotNull(branch); + + bool wasCalled = false; + CheckoutNotifyFlags actualNotifyFlags = CheckoutNotifyFlags.None; + + RevertOptions options = new RevertOptions() + { + OnCheckoutNotify = (path, notificationType) => { wasCalled = true; actualNotifyFlags = notificationType; return true; }, + CheckoutNotifyFlags = CheckoutNotifyFlags.Updated, + }; + + repo.Revert(repo.Head.Tip, Constants.Signature, options); + + Assert.True(wasCalled); + } + } + + [Theory] + [InlineData(null)] + [InlineData(true)] + [InlineData(false)] + public void RevertFindsRenames(bool? findRenames) + { + // The environment is set up such that: + // - file d.txt is edited in the commit that is to be reverted (commit A) + // - file d.txt is renamed to d_renamed.txt + // - commit A is reverted. + // If rename detection is enabled, then the revert is applied + // to d_renamed.txt. If rename detection is not enabled, + // then the revert results in a conflict. + const string revertBranchName = "refs/heads/revert_rename"; + const string commitIdToRevert = "ca3e813"; + const string expectedBlobId = "0ff3bbb9c8bba2291654cd64067fa417ff54c508"; + const string modifiedFilePath = "d_renamed.txt"; + + string repoPath = CloneRevertTestRepo(); + using (var repo = new Repository(repoPath)) + { + Branch currentBranch = repo.Checkout(revertBranchName); + Assert.NotNull(currentBranch); + + Commit commitToRevert = repo.Lookup<Commit>(commitIdToRevert); + Assert.NotNull(currentBranch); + + RevertOptions options; + if (findRenames.HasValue) + { + options = new RevertOptions() + { + FindRenames = findRenames.Value, + }; + } + else + { + options = new RevertOptions(); + } + + RevertResult result = repo.Revert(commitToRevert, Constants.Signature, options); + Assert.NotNull(result); + + if(!findRenames.HasValue || + findRenames.Value == true) + { + Assert.Equal(RevertStatus.Reverted, result.Status); + Assert.NotNull(result.Commit); + Blob expectedBlob = repo.Lookup<Blob>(expectedBlobId); + Assert.NotNull(expectedBlob); + + GitObject blob = result.Commit.Tree[modifiedFilePath].Target as Blob; + Assert.NotNull(blob); + Assert.Equal(blob.Id, expectedBlob.Id); + + // Verify contents of workspace + string fullPath = Path.Combine(repo.Info.WorkingDirectory, modifiedFilePath); + Assert.Equal(expectedBlob.GetContentText(new FilteringOptions(modifiedFilePath)), File.ReadAllText(fullPath)); + } + else + { + Assert.Equal(RevertStatus.Conflicts, result.Status); + Assert.Null(result.Commit); + } + } + } + + [Theory] + [InlineData(1, "a04ef5f22c2413a9743046436c0e5354ed903f78")] + [InlineData(2, "1ae0cd88802bb4f4e6413ba63e41376d235b6fd0")] + public void CanRevertMergeCommit(int mainline, string expectedId) + { + const string revertBranchName = "refs/heads/revert_merge"; + const string commitIdToRevert = "2747045"; + + string repoPath = CloneRevertTestRepo(); + using (var repo = new Repository(repoPath)) + { + Branch branch = repo.Checkout(revertBranchName); + Assert.NotNull(branch); + + Commit commitToRevert = repo.Lookup<Commit>(commitIdToRevert); + Assert.NotNull(commitToRevert); + + RevertOptions options = new RevertOptions() + { + Mainline = mainline, + }; + + RevertResult result = repo.Revert(commitToRevert, Constants.Signature, options); + + Assert.NotNull(result); + Assert.Equal(RevertStatus.Reverted, result.Status); + Assert.Equal(result.Commit.Sha, expectedId); + + if(mainline == 1) + { + // In this case, we expect "d_renamed.txt" to be reverted (deleted), + // and a.txt to match the tip of the "revert" branch. + Assert.Equal(FileStatus.Nonexistent, repo.Index.RetrieveStatus("d_renamed.txt")); + + // This is the commit containing the expected contents of a.txt. + Commit commit = repo.Lookup<Commit>("b6fbb29b625aabe0fb5736da6fd61d4147e4405e"); + Assert.NotNull(commit); + Assert.Equal(commit["a.txt"].Target.Id, repo.Index["a.txt"].Id); + } + else if(mainline == 2) + { + // In this case, we expect "d_renamed.txt" to be preset, + // and a.txt to match the tip of the master branch. + + // In this case, we expect "d_renamed.txt" to be reverted (deleted), + // and a.txt to match the tip of the "revert" branch. + Assert.Equal(FileStatus.Unaltered, repo.Index.RetrieveStatus("d_renamed.txt")); + + // This is the commit containing the expected contents of "d_renamed.txt". + Commit commit = repo.Lookup<Commit>("c4b5cea70e4cd5b633ed0f10ae0ed5384e8190d8"); + Assert.NotNull(commit); + Assert.Equal(commit["d_renamed.txt"].Target.Id, repo.Index["d_renamed.txt"].Id); + + // This is the commit containing the expected contents of a.txt. + commit = repo.Lookup<Commit>("cb4f7f0eca7a0114cdafd8537332aa17de36a4e9"); + Assert.NotNull(commit); + Assert.Equal(commit["a.txt"].Target.Id, repo.Index["a.txt"].Id); + } } } } diff --git a/LibGit2Sharp.Tests/TestHelpers/BaseFixture.cs b/LibGit2Sharp.Tests/TestHelpers/BaseFixture.cs index c4514e3c..5dfa5b12 100644 --- a/LibGit2Sharp.Tests/TestHelpers/BaseFixture.cs +++ b/LibGit2Sharp.Tests/TestHelpers/BaseFixture.cs @@ -30,6 +30,7 @@ namespace LibGit2Sharp.Tests.TestHelpers public static string ShallowTestRepoPath { get; private set; } public static string MergedTestRepoWorkingDirPath { get; private set; } public static string MergeTestRepoWorkingDirPath { get; private set; } + public static string RevertTestRepoWorkingDirPath { get; private set; } public static string SubmoduleTestRepoWorkingDirPath { get; private set; } public static DirectoryInfo ResourcesDirectory { get; private set; } @@ -63,6 +64,7 @@ namespace LibGit2Sharp.Tests.TestHelpers ShallowTestRepoPath = Path.Combine(ResourcesDirectory.FullName, "shallow.git"); MergedTestRepoWorkingDirPath = Path.Combine(ResourcesDirectory.FullName, "mergedrepo_wd"); MergeTestRepoWorkingDirPath = Path.Combine(ResourcesDirectory.FullName, "merge_testrepo_wd"); + RevertTestRepoWorkingDirPath = Path.Combine(ResourcesDirectory.FullName, "revert_testrepo_wd"); SubmoduleTestRepoWorkingDirPath = Path.Combine(ResourcesDirectory.FullName, "submodule_wd"); } @@ -129,6 +131,11 @@ namespace LibGit2Sharp.Tests.TestHelpers return Clone(MergeTestRepoWorkingDirPath); } + protected string CloneRevertTestRepo() + { + return Clone(RevertTestRepoWorkingDirPath); + } + public string CloneSubmoduleTestRepo() { var submoduleTarget = Path.Combine(ResourcesDirectory.FullName, "submodule_target_wd"); |