From 11da2fa1b9e79bb87a19e3945fab721ab72c203a Mon Sep 17 00:00:00 2001 From: Marius Ungureanu Date: Fri, 7 Nov 2014 15:26:16 +0200 Subject: [PATCH] Introduce StatusOptions.IncludeUnaltered --- LibGit2Sharp.Tests/StatusFixture.cs | 60 ++++++++++++++++++++++++----- LibGit2Sharp/RepositoryStatus.cs | 36 +++++++++++++---- LibGit2Sharp/StatusOptions.cs | 8 ++++ 3 files changed, 88 insertions(+), 16 deletions(-) diff --git a/LibGit2Sharp.Tests/StatusFixture.cs b/LibGit2Sharp.Tests/StatusFixture.cs index e8f9d7314..476dab8bd 100644 --- a/LibGit2Sharp.Tests/StatusFixture.cs +++ b/LibGit2Sharp.Tests/StatusFixture.cs @@ -103,20 +103,22 @@ public void RetrievingTheStatusOfADirectoryThrows() } } - [Fact] - public void CanRetrieveTheStatusOfTheWholeWorkingDirectory() + [Theory] + [InlineData(false, 0)] + [InlineData(true, 5)] + public void CanRetrieveTheStatusOfTheWholeWorkingDirectory(bool includeUnaltered, int unalteredCount) { string path = SandboxStandardTestRepo(); using (var repo = new Repository(path)) { const string file = "modified_staged_file.txt"; - RepositoryStatus status = repo.RetrieveStatus(); + RepositoryStatus status = repo.RetrieveStatus(new StatusOptions() { IncludeUnaltered = includeUnaltered }); Assert.Equal(FileStatus.Staged, status[file].State); Assert.NotNull(status); - Assert.Equal(6, status.Count()); + Assert.Equal(6 + unalteredCount, status.Count()); Assert.True(status.IsDirty); Assert.Equal("new_untracked_file.txt", status.Untracked.Select(s => s.FilePath).Single()); @@ -131,11 +133,11 @@ public void CanRetrieveTheStatusOfTheWholeWorkingDirectory() Assert.Equal(FileStatus.Staged | FileStatus.Modified, repo.RetrieveStatus(file)); - RepositoryStatus status2 = repo.RetrieveStatus(); + RepositoryStatus status2 = repo.RetrieveStatus(new StatusOptions() { IncludeUnaltered = includeUnaltered }); Assert.Equal(FileStatus.Staged | FileStatus.Modified, status2[file].State); Assert.NotNull(status2); - Assert.Equal(6, status2.Count()); + Assert.Equal(6 + unalteredCount, status2.Count()); Assert.True(status2.IsDirty); Assert.Equal("new_untracked_file.txt", status2.Untracked.Select(s => s.FilePath).Single()); @@ -242,14 +244,16 @@ public void CanDetectedVariousKindsOfRenaming() } } - [Fact] - public void CanRetrieveTheStatusOfANewRepository() + [Theory] + [InlineData(true)] + [InlineData(false)] + public void CanRetrieveTheStatusOfANewRepository(bool includeUnaltered) { string repoPath = InitNewRepository(); using (var repo = new Repository(repoPath)) { - RepositoryStatus status = repo.RetrieveStatus(); + RepositoryStatus status = repo.RetrieveStatus(new StatusOptions() { IncludeUnaltered = includeUnaltered }); Assert.NotNull(status); Assert.Equal(0, status.Count()); Assert.False(status.IsDirty); @@ -592,5 +596,43 @@ public void RetrievingTheStatusHonorsAssumedUnchangedMarkedIndexEntries() Assert.Equal("hello.txt", status.Modified.Single().FilePath); } } + + [Fact] + public void CanIncludeStatusOfUnalteredFiles() + { + var path = SandboxStandardTestRepo(); + string[] unalteredPaths = { + "1.txt", + "1" + Path.DirectorySeparatorChar + "branch_file.txt", + "branch_file.txt", + "new.txt", + "README", + }; + + using (var repo = new Repository(path)) + { + RepositoryStatus status = repo.RetrieveStatus(new StatusOptions() { IncludeUnaltered = true }); + + Assert.Equal(unalteredPaths.Length, status.Unaltered.Count()); + Assert.Equal(unalteredPaths, status.Unaltered.OrderBy(s => s.FilePath).Select(s => s.FilePath).ToArray()); + } + } + + [Fact] + public void UnalteredFilesDontMarkIndexAsDirty() + { + var path = SandboxStandardTestRepo(); + + using (var repo = new Repository(path)) + { + repo.Reset(ResetMode.Hard); + repo.RemoveUntrackedFiles(); + + RepositoryStatus status = repo.RetrieveStatus(new StatusOptions() { IncludeUnaltered = true }); + + Assert.Equal(false, status.IsDirty); + Assert.Equal(9, status.Count()); + } + } } } diff --git a/LibGit2Sharp/RepositoryStatus.cs b/LibGit2Sharp/RepositoryStatus.cs index 1eac10e16..d5e82ef4b 100644 --- a/LibGit2Sharp/RepositoryStatus.cs +++ b/LibGit2Sharp/RepositoryStatus.cs @@ -26,6 +26,7 @@ public class RepositoryStatus : IEnumerable private readonly List ignored = new List(); private readonly List renamedInIndex = new List(); private readonly List renamedInWorkDir = new List(); + private readonly List unaltered = new List(); private readonly bool isDirty; private readonly IDictionary> dispatcher = Build(); @@ -42,7 +43,7 @@ private static IDictionary> Bu { FileStatus.Removed, (rs, s) => rs.removed.Add(s) }, { FileStatus.RenamedInIndex, (rs, s) => rs.renamedInIndex.Add(s) }, { FileStatus.Ignored, (rs, s) => rs.ignored.Add(s) }, - { FileStatus.RenamedInWorkDir, (rs, s) => rs.renamedInWorkDir.Add(s) } + { FileStatus.RenamedInWorkDir, (rs, s) => rs.renamedInWorkDir.Add(s) }, }; } @@ -81,7 +82,7 @@ internal RepositoryStatus(Repository repo, StatusOptions options) AddStatusEntryForDelta(entry.Status, deltaHeadToIndex, deltaIndexToWorkDir); } - isDirty = statusEntries.Any(entry => entry.State != FileStatus.Ignored); + isDirty = statusEntries.Any(entry => entry.State != FileStatus.Ignored && entry.State != FileStatus.Unaltered); } } @@ -134,6 +135,12 @@ private static GitStatusOptions CreateStatusOptions(StatusOptions options) GitStatusOptionFlags.DisablePathspecMatch; } + if (options.IncludeUnaltered) + { + coreOptions.Flags |= + GitStatusOptionFlags.IncludeUnmodified; + } + return coreOptions; } @@ -164,14 +171,21 @@ private void AddStatusEntryForDelta(FileStatus gitStatus, GitDiffDelta deltaHead StatusEntry statusEntry = new StatusEntry(filePath, gitStatus, headToIndexRenameDetails, indexToWorkDirRenameDetails); - foreach (KeyValuePair> kvp in dispatcher) + if (gitStatus == FileStatus.Unaltered) { - if (!gitStatus.HasFlag(kvp.Key)) + unaltered.Add(statusEntry); + } + else + { + foreach (KeyValuePair> kvp in dispatcher) { - continue; - } + if (!gitStatus.HasFlag(kvp.Key)) + { + continue; + } - kvp.Value(this, statusEntry); + kvp.Value(this, statusEntry); + } } statusEntries.Add(statusEntry); @@ -289,6 +303,14 @@ public virtual IEnumerable RenamedInWorkDir get { return renamedInWorkDir; } } + /// + /// List of files that were unmodified in the working directory. + /// + public virtual IEnumerable Unaltered + { + get { return unaltered; } + } + /// /// True if the index or the working directory has been altered since the last commit. False otherwise. /// diff --git a/LibGit2Sharp/StatusOptions.cs b/LibGit2Sharp/StatusOptions.cs index a7e51760d..f389303af 100644 --- a/LibGit2Sharp/StatusOptions.cs +++ b/LibGit2Sharp/StatusOptions.cs @@ -76,5 +76,13 @@ public StatusOptions() /// as explicit paths, and NOT as pathspecs containing globs. /// public bool DisablePathSpecMatch { get; set; } + + /// + /// Include unaltered files when scanning for status + /// + /// + /// Unaltered meaning the file is identical in the working directory, the index and HEAD. + /// + public bool IncludeUnaltered { get; set; } } }