diff --git a/LibGit2Sharp.Tests/StageFixture.cs b/LibGit2Sharp.Tests/StageFixture.cs index 5499f578b..3355645f0 100644 --- a/LibGit2Sharp.Tests/StageFixture.cs +++ b/LibGit2Sharp.Tests/StageFixture.cs @@ -67,7 +67,7 @@ public void StagingAnUnknownFileThrowsIfExplicitPath(string relativePath, FileSt Assert.Null(repo.Index[relativePath]); Assert.Equal(status, repo.Index.RetrieveStatus(relativePath)); - Assert.Throws(() => repo.Index.Stage(relativePath, new ExplicitPathsOptions())); + Assert.Throws(() => repo.Index.Stage(relativePath, new StageOptions { ExplicitPathsOptions = new ExplicitPathsOptions() })); } } @@ -82,7 +82,7 @@ public void CanStageAnUnknownFileWithLaxUnmatchedExplicitPathsValidation(string Assert.Equal(status, repo.Index.RetrieveStatus(relativePath)); Assert.DoesNotThrow(() => repo.Index.Stage(relativePath)); - Assert.DoesNotThrow(() => repo.Index.Stage(relativePath, new ExplicitPathsOptions { ShouldFailOnUnmatchedPath = false })); + Assert.DoesNotThrow(() => repo.Index.Stage(relativePath, new StageOptions { ExplicitPathsOptions = new ExplicitPathsOptions { ShouldFailOnUnmatchedPath = false } })); Assert.Equal(status, repo.Index.RetrieveStatus(relativePath)); } @@ -99,7 +99,7 @@ public void StagingAnUnknownFileWithLaxExplicitPathsValidationDoesntThrow(string Assert.Equal(status, repo.Index.RetrieveStatus(relativePath)); repo.Index.Stage(relativePath); - repo.Index.Stage(relativePath, new ExplicitPathsOptions { ShouldFailOnUnmatchedPath = false }); + repo.Index.Stage(relativePath, new StageOptions { ExplicitPathsOptions = new ExplicitPathsOptions { ShouldFailOnUnmatchedPath = false } }); } } @@ -299,6 +299,22 @@ public void CanStageWithMultiplePathspecs() } } + [Theory] + [InlineData("ignored_file.txt")] + [InlineData("ignored_folder/file.txt")] + public void CanIgnoreIgnoredPaths(string path) + { + using (var repo = new Repository(CloneStandardTestRepo())) + { + Touch(repo.Info.WorkingDirectory, ".gitignore", "ignored_file.txt\nignored_folder/\n"); + Touch(repo.Info.WorkingDirectory, path, "This file is ignored."); + + Assert.Equal(FileStatus.Ignored, repo.Index.RetrieveStatus(path)); + repo.Index.Stage("*"); + Assert.Equal(FileStatus.Ignored, repo.Index.RetrieveStatus(path)); + } + } + [Theory] [InlineData("ignored_file.txt")] [InlineData("ignored_folder/file.txt")] @@ -310,7 +326,7 @@ public void CanStageIgnoredPaths(string path) Touch(repo.Info.WorkingDirectory, path, "This file is ignored."); Assert.Equal(FileStatus.Ignored, repo.Index.RetrieveStatus(path)); - repo.Index.Stage(path); + repo.Index.Stage(path, new StageOptions { IncludeIgnored = true }); Assert.Equal(FileStatus.Added, repo.Index.RetrieveStatus(path)); } } diff --git a/LibGit2Sharp.Tests/UnstageFixture.cs b/LibGit2Sharp.Tests/UnstageFixture.cs index 47562a6fe..d58784423 100644 --- a/LibGit2Sharp.Tests/UnstageFixture.cs +++ b/LibGit2Sharp.Tests/UnstageFixture.cs @@ -50,7 +50,7 @@ public void CanStageAndUnstageAnIgnoredFile() Assert.Equal(FileStatus.Ignored, repo.Index.RetrieveStatus(relativePath)); - repo.Index.Stage(relativePath); + repo.Index.Stage(relativePath, new StageOptions { IncludeIgnored = true }); Assert.Equal(FileStatus.Added, repo.Index.RetrieveStatus(relativePath)); repo.Index.Unstage(relativePath); diff --git a/LibGit2Sharp/Index.cs b/LibGit2Sharp/Index.cs index ee5e02979..f7e26318a 100644 --- a/LibGit2Sharp/Index.cs +++ b/LibGit2Sharp/Index.cs @@ -129,32 +129,70 @@ IEnumerator IEnumerable.GetEnumerator() /// /// Promotes to the staging area the latest modifications of a file in the working directory (addition, updation or removal). + /// + /// If this path is ignored by configuration then it will not be staged. /// /// The path of the file within the working directory. /// /// If set, the passed will be treated as explicit paths. /// Use these options to determine how unmatched explicit paths should be handled. /// - public virtual void Stage(string path, ExplicitPathsOptions explicitPathsOptions = null) + [Obsolete("This will be removed in a future release. Supply ExplicitPathsOptions to StageOptions.")] + public virtual void Stage(string path, ExplicitPathsOptions explicitPathsOptions) + { + Stage(path, new StageOptions { ExplicitPathsOptions = explicitPathsOptions }); + } + + /// + /// Promotes to the staging area the latest modifications of a file in the working directory (addition, updation or removal). + /// + /// If this path is ignored by configuration then it will not be staged unless is unset. + /// + /// The path of the file within the working directory. + /// If set, determines how paths will be staged. + public virtual void Stage(string path, StageOptions stageOptions = null) { Ensure.ArgumentNotNull(path, "path"); - Stage(new[] { path }, explicitPathsOptions); + Stage(new[] { path }, stageOptions); } /// /// Promotes to the staging area the latest modifications of a collection of files in the working directory (addition, updation or removal). + /// + /// Any paths (even those listed explicitly) that are ignored by configuration will not be staged. /// /// The collection of paths of the files within the working directory. /// /// If set, the passed will be treated as explicit paths. /// Use these options to determine how unmatched explicit paths should be handled. /// - public virtual void Stage(IEnumerable paths, ExplicitPathsOptions explicitPathsOptions = null) + [Obsolete("This will be removed in a future release. Supply ExplicitPathsOptions to StageOptions.")] + public virtual void Stage(IEnumerable paths, ExplicitPathsOptions explicitPathsOptions) + { + Stage(paths, new StageOptions { ExplicitPathsOptions = explicitPathsOptions }); + } + + /// + /// Promotes to the staging area the latest modifications of a collection of files in the working directory (addition, updation or removal). + /// + /// Any paths (even those listed explicitly) that are ignored by configuration will not be staged unless is unset. + /// + /// The collection of paths of the files within the working directory. + /// If set, determines how paths will be staged. + public virtual void Stage(IEnumerable paths, StageOptions stageOptions = null) { Ensure.ArgumentNotNull(paths, "paths"); - var changes = repo.Diff.Compare(DiffModifiers.IncludeUntracked | DiffModifiers.IncludeIgnored, paths, explicitPathsOptions); + DiffModifiers diffModifiers = DiffModifiers.IncludeUntracked; + ExplicitPathsOptions explicitPathsOptions = stageOptions != null ? stageOptions.ExplicitPathsOptions : null; + + if (stageOptions != null && stageOptions.IncludeIgnored) + { + diffModifiers |= DiffModifiers.IncludeIgnored; + } + + var changes = repo.Diff.Compare(diffModifiers, paths, explicitPathsOptions); foreach (var treeEntryChanges in changes) { diff --git a/LibGit2Sharp/LibGit2Sharp.csproj b/LibGit2Sharp/LibGit2Sharp.csproj index 8ed8c54c1..d8814ab95 100644 --- a/LibGit2Sharp/LibGit2Sharp.csproj +++ b/LibGit2Sharp/LibGit2Sharp.csproj @@ -132,6 +132,7 @@ + @@ -351,4 +352,4 @@ - + \ No newline at end of file diff --git a/LibGit2Sharp/StageOptions.cs b/LibGit2Sharp/StageOptions.cs new file mode 100644 index 000000000..7701b8948 --- /dev/null +++ b/LibGit2Sharp/StageOptions.cs @@ -0,0 +1,22 @@ +using System; + +namespace LibGit2Sharp +{ + /// + /// Options to define file staging behavior. + /// + public sealed class StageOptions + { + /// + /// Stage ignored files. (Default = false) + /// + public bool IncludeIgnored { get; set; } + + /// + /// If set, the passed paths will be treated as explicit paths. + /// Use these options to determine how unmatched explicit paths + /// should be handled. (Default = null) + /// + public ExplicitPathsOptions ExplicitPathsOptions { get; set; } + } +}