Skip to content

Introduce StatusOptions.IncludeUnaltered #863

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 1 commit into from
Apr 15, 2015
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
60 changes: 51 additions & 9 deletions LibGit2Sharp.Tests/StatusFixture.cs
Original file line number Diff line number Diff line change
Expand Up @@ -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());
Expand All @@ -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());
Expand Down Expand Up @@ -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);
Expand Down Expand Up @@ -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();
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Cleaning stuff first. Even untracked files mark the repo as dirty.


RepositoryStatus status = repo.RetrieveStatus(new StatusOptions() { IncludeUnaltered = true });

Assert.Equal(false, status.IsDirty);
Assert.Equal(9, status.Count());
}
}
}
}
36 changes: 29 additions & 7 deletions LibGit2Sharp/RepositoryStatus.cs
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@ public class RepositoryStatus : IEnumerable<StatusEntry>
private readonly List<StatusEntry> ignored = new List<StatusEntry>();
private readonly List<StatusEntry> renamedInIndex = new List<StatusEntry>();
private readonly List<StatusEntry> renamedInWorkDir = new List<StatusEntry>();
private readonly List<StatusEntry> unaltered = new List<StatusEntry>();
private readonly bool isDirty;

private readonly IDictionary<FileStatus, Action<RepositoryStatus, StatusEntry>> dispatcher = Build();
Expand All @@ -42,7 +43,7 @@ private static IDictionary<FileStatus, Action<RepositoryStatus, StatusEntry>> 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) },
};
}

Expand Down Expand Up @@ -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);
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@Therzok As we're modifying the behavior of the IsDirty property, could you please add some test coverage regarding this?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actually, we don't quite modify the behaviour. We extend it here.

Without IncludeUnaltered, we never had Unaltered file status. I'll add coverage for it though.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

That said, does having Untracked files mark the status as dirty? Thoughts?

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'd say no. What does git.git has to say about this?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I just did a:

test -n "$(git status --porcelain)" || echo "asdf" with untracked files and that makes it considered dirty. "asdf" isn't printed.

Okay, should be good to go now.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Ah, the option to take out Untracked files is something else.

You can query the git commandline in two ways for status changes:
git status --porcelain
git status --porcelain -uno (no untracked)

That's for later, yes.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Ah, the option to take out Untracked files is something else.

Dammit! I read it backwards.

That's for later, yes.

👍

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

FileStatus is a Flag enum - do you mean to use the != comparison, or should we use the Enum.HasFlag to check for these instead?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

These are exclusive statuses. Unaltered and Ignored can only appear by themselves.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Also, x & 0 == 0 always. So we can't use bitwise and on Unaltered.

}
}

Expand Down Expand Up @@ -134,6 +135,12 @@ private static GitStatusOptions CreateStatusOptions(StatusOptions options)
GitStatusOptionFlags.DisablePathspecMatch;
}

if (options.IncludeUnaltered)
{
coreOptions.Flags |=
GitStatusOptionFlags.IncludeUnmodified;
}

return coreOptions;
}

Expand Down Expand Up @@ -164,14 +171,21 @@ private void AddStatusEntryForDelta(FileStatus gitStatus, GitDiffDelta deltaHead

StatusEntry statusEntry = new StatusEntry(filePath, gitStatus, headToIndexRenameDetails, indexToWorkDirRenameDetails);

foreach (KeyValuePair<FileStatus, Action<RepositoryStatus, StatusEntry>> kvp in dispatcher)
if (gitStatus == FileStatus.Unaltered)
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Could we handle the FileStatus.Unaltered value in the same way we handle the other values (in the dispatcher dictionary)?

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Ah - probably not if FileStatus.Unaltered = 0.

{
if (!gitStatus.HasFlag(kvp.Key))
unaltered.Add(statusEntry);
}
else
{
foreach (KeyValuePair<FileStatus, Action<RepositoryStatus, StatusEntry>> kvp in dispatcher)
{
continue;
}
if (!gitStatus.HasFlag(kvp.Key))
{
continue;
}

kvp.Value(this, statusEntry);
kvp.Value(this, statusEntry);
}
}

statusEntries.Add(statusEntry);
Expand Down Expand Up @@ -289,6 +303,14 @@ public virtual IEnumerable<StatusEntry> RenamedInWorkDir
get { return renamedInWorkDir; }
}

/// <summary>
/// List of files that were unmodified in the working directory.
/// </summary>
public virtual IEnumerable<StatusEntry> Unaltered
{
get { return unaltered; }
}

/// <summary>
/// True if the index or the working directory has been altered since the last commit. False otherwise.
/// </summary>
Expand Down
8 changes: 8 additions & 0 deletions LibGit2Sharp/StatusOptions.cs
Original file line number Diff line number Diff line change
Expand Up @@ -76,5 +76,13 @@ public StatusOptions()
/// as explicit paths, and NOT as pathspecs containing globs.
/// </summary>
public bool DisablePathSpecMatch { get; set; }

/// <summary>
/// Include unaltered files when scanning for status
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Considering this thread, it may be worthwhile to add an explanation regarding what Unaltered refers to (eg. The file is identical in the workdir, the index and the HEAD). This way, we may have a chance to not forget this later ;-)

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Done in a remarks element.

/// </summary>
/// <remarks>
/// Unaltered meaning the file is identical in the working directory, the index and HEAD.
/// </remarks>
public bool IncludeUnaltered { get; set; }
}
}