diff --git a/GitTfs/Core/DirectoryTidier.cs b/GitTfs/Core/DirectoryTidier.cs new file mode 100644 index 00000000..e1da7393 --- /dev/null +++ b/GitTfs/Core/DirectoryTidier.cs @@ -0,0 +1,43 @@ +using System; + +namespace Sep.Git.Tfs.Core +{ + public class DirectoryTidier : ITfsWorkspaceModifier, IDisposable + { + ITfsWorkspaceModifier _workspace; + + public DirectoryTidier(ITfsWorkspaceModifier workspace, object initialTfsTree) + { + _workspace = workspace; + } + + public void Dispose() + { + } + + public string GetLocalPath(string path) + { + return _workspace.GetLocalPath(path); + } + + public void Add(string path) + { + _workspace.Add(path); + } + + public void Edit(string path) + { + _workspace.Edit(path); + } + + public void Delete(string path) + { + _workspace.Delete(path); + } + + public void Rename(string pathFrom, string pathTo, string score) + { + _workspace.Rename(pathFrom, pathTo, score); + } + } +} diff --git a/GitTfs/GitTfs.csproj b/GitTfs/GitTfs.csproj index 24ddf38b..3ef97540 100644 --- a/GitTfs/GitTfs.csproj +++ b/GitTfs/GitTfs.csproj @@ -130,6 +130,7 @@ Properties\Version.cs + @@ -290,4 +291,4 @@ - \ No newline at end of file + diff --git a/GitTfsTest/Core/DirectoryTidierTests.cs b/GitTfsTest/Core/DirectoryTidierTests.cs new file mode 100644 index 00000000..2a18a390 --- /dev/null +++ b/GitTfsTest/Core/DirectoryTidierTests.cs @@ -0,0 +1,169 @@ +using System; +using Xunit; +using Rhino.Mocks; +using Sep.Git.Tfs.Core; + +namespace Sep.Git.Tfs.Test.Core +{ + [Trait("focus", "true")] + public class DirectoryTidierTests : IDisposable + { + MockRepository mocks; + ITfsWorkspaceModifier mockWorkspace; + object initialTfsTree; + DirectoryTidier _tidy; + + public DirectoryTidierTests() + { + mocks = new MockRepository(); + mockWorkspace = mocks.StrictMock(); + initialTfsTree = null; // todo + // topDir/ + // topDir/topFile.txt + // topDir/midDir/midFile.txt + // topDir/midDir/bottomDir/file1.txt + // topDir/midDir/bottomDir/file2.txt + // dir1/dir2/dir3/lonelyFile.txt + } + + public void Dispose() + { + Tidy.Dispose(); + mockWorkspace.VerifyAllExpectations(); + } + + DirectoryTidier Tidy + { + get + { + if (_tidy == null) + { + mocks.ReplayAll(); + _tidy = new DirectoryTidier(mockWorkspace, initialTfsTree); + } + return _tidy; + } + } + + [Fact] + public void PassesThroughGetLocalPath() + { + mockWorkspace.Expect(x => x.GetLocalPath("git-path")).Return("tfs-path"); + Assert.Equal("tfs-path", Tidy.GetLocalPath("git-path")); + } + + [Fact] + public void NoChangesMeansNoChanges() + { + Tidy.Dispose(); + } + + [Fact] + public void AddingAFilePassesThroughAndDoesNotRemoveOtherItems() + { + mockWorkspace.Expect(x => x.Add("topDir/midDir/bottomDir/newFile.txt")); + Tidy.Add("topDir/midDir/bottomDir/newFile.txt"); + Tidy.Dispose(); + } + + [Fact] + public void RemovingAFileWithSiblingsDoesNotRemoveTheDir() + { + mockWorkspace.Expect(x => x.Delete("topDir/midDir/bottomDir/file1.txt")); + Tidy.Delete("topDir/midDir/bottomDir/file1.txt"); + Tidy.Dispose(); + } + + [Fact] + public void RemovingBothSiblingFilesRemovesTheDir() + { + mockWorkspace.Expect(x => x.Delete("topDir/midDir/bottomDir/file1.txt")); + mockWorkspace.Expect(x => x.Delete("topDir/midDir/bottomDir/file2.txt")); + mockWorkspace.Expect(x => x.Delete("topDir/midDir/bottomDir")); + Tidy.Delete("topDir/midDir/bottomDir/file1.txt"); + Tidy.Delete("topDir/midDir/bottomDir/file2.txt"); + Tidy.Dispose(); + } + + [Fact] + public void RemovingAFileRemovesAllEmptyParents() + { + mockWorkspace.Expect(x => x.Delete("dir1/dir2/dir3/lonelyFile.txt")); + mockWorkspace.Expect(x => x.Delete("dir1/dir2/dir3")); + mockWorkspace.Expect(x => x.Delete("dir1/dir2")); + mockWorkspace.Expect(x => x.Delete("dir1")); + Tidy.Delete("dir1/dir2/dir3/lonelyFile.txt"); + Tidy.Dispose(); + } + + [Fact] + public void MovingAFileOutRemovesAllEmptyParents() + { + mockWorkspace.Expect(x => x.Rename("dir1/dir2/dir3/lonelyFile.txt", "otherdir/otherdir2/newName.txt", ScoreIsIrrelevant)); + mockWorkspace.Expect(x => x.Delete("dir1/dir2/dir3")); + mockWorkspace.Expect(x => x.Delete("dir1/dir2")); + mockWorkspace.Expect(x => x.Delete("dir1")); + Tidy.Rename("dir1/dir2/dir3/lonelyFile.txt", "otherdir/otherdir2/newName.txt", ScoreIsIrrelevant); + Tidy.Dispose(); + } + + [Fact] + public void MovingAFileOutAndInLeavesParents() + { + mockWorkspace.Expect(x => x.Rename("dir1/dir2/dir3/lonelyFile.txt", "otherdir/otherdir2/newName.txt", ScoreIsIrrelevant)); + mockWorkspace.Expect(x => x.Rename("topDir/topFile.txt", "dir1/dir2/dir3/replacement.txt", ScoreIsIrrelevant)); + Tidy.Rename("dir1/dir2/dir3/lonelyFile.txt", "otherdir/otherdir2/newName.txt", ScoreIsIrrelevant); + Tidy.Rename("topDir/topFile.txt", "dir1/dir2/dir3/replacement.txt", ScoreIsIrrelevant); + Tidy.Dispose(); + } + + [Fact] + public void DeletingAFileAndAddingAnotherLeavesParents() + { + mockWorkspace.Expect(x => x.Delete("dir1/dir2/dir3/lonelyFile.txt")); + mockWorkspace.Expect(x => x.Add("dir1/dir2/dir3/newFile.txt")); + Tidy.Delete("dir1/dir2/dir3/lonelyFile.txt"); + Tidy.Add("dir1/dir2/dir3/newFile.txt"); + Tidy.Dispose(); + } + + [Fact] + public void RemovingAllFilesRemovesAllParents() + { + mockWorkspace.Expect(x => x.Delete("topDir/midDir/bottomDir/file1.txt")); + mockWorkspace.Expect(x => x.Delete("topDir/midDir/bottomDir/file2.txt")); + mockWorkspace.Expect(x => x.Delete("topDir/midDir/midFile.txt")); + mockWorkspace.Expect(x => x.Delete("topDir/topFile.txt")); + mockWorkspace.Expect(x => x.Delete("topDir/midDir/bottomDir")); + mockWorkspace.Expect(x => x.Delete("topDir/midDir")); + mockWorkspace.Expect(x => x.Delete("topDir")); + Tidy.Delete("topDir/midDir/bottomDir/file1.txt"); + Tidy.Delete("topDir/midDir/bottomDir/file2.txt"); + Tidy.Delete("topDir/midDir/midFile.txt"); + Tidy.Delete("topDir/topFile.txt"); + Tidy.Dispose(); + } + + [Fact] + public void TidyDoesNotCareWhatCaseYouUse() + { + mockWorkspace.Expect(x => x.Delete("TOPDIR/MIDDIR/BOTTOMDIR/FILE1.TXT")); + mockWorkspace.Expect(x => x.Delete("TOPDIR/MIDDIR/BOTTOMDIR/FILE2.TXT")); + mockWorkspace.Expect(x => x.Delete("TOPDIR/MIDDIR/MIDFILE.TXT")); + mockWorkspace.Expect(x => x.Delete("TOPDIR/TOPFILE.TXT")); + mockWorkspace.Expect(x => x.Delete("topDir/midDir/bottomDir")); + mockWorkspace.Expect(x => x.Delete("topDir/midDir")); + mockWorkspace.Expect(x => x.Delete("topDir")); + Tidy.Delete("TOPDIR/MIDDIR/BOTTOMDIR/FILE1.TXT"); + Tidy.Delete("TOPDIR/MIDDIR/BOTTOMDIR/FILE2.TXT"); + Tidy.Delete("TOPDIR/MIDDIR/MIDFILE.TXT"); + Tidy.Delete("TOPDIR/TOPFILE.TXT"); + Tidy.Dispose(); + } + + /// + /// The score argument is passed through by DirectoryTidier, so its value doesn't matter. + /// + const string ScoreIsIrrelevant = "irrelevant"; + } +} diff --git a/GitTfsTest/GitTfsTest.csproj b/GitTfsTest/GitTfsTest.csproj index 14b66239..be772a00 100644 --- a/GitTfsTest/GitTfsTest.csproj +++ b/GitTfsTest/GitTfsTest.csproj @@ -110,6 +110,7 @@ +