Thanks to visit codestin.com
Credit goes to github.com

Skip to content

Add unmatched pathspecs options #343

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

Closed
wants to merge 3 commits into from
Closed
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
38 changes: 37 additions & 1 deletion LibGit2Sharp.Tests/DiffTreeToTargetFixture.cs
Original file line number Diff line number Diff line change
Expand Up @@ -283,7 +283,7 @@ public void CanCompareASubsetofTheTreeAgainstTheIndex()
Tree tree = repo.Head.Tip.Tree;

TreeChanges changes = repo.Diff.Compare(tree, DiffTargets.Index,
new[] { "deleted_staged_file.txt", "1/branch_file.txt", "I-do/not-exist" });
new[] { "deleted_staged_file.txt", "1/branch_file.txt" });

Assert.NotNull(changes);

Expand All @@ -292,6 +292,42 @@ public void CanCompareASubsetofTheTreeAgainstTheIndex()
}
}

private static void AssertCanCompareASubsetOfTheTreeAgainstTheIndex(TreeChanges changes)
{
Assert.NotNull(changes);
Assert.Equal(1, changes.Count());
Assert.Equal("deleted_staged_file.txt", changes.Deleted.Single().Path);
}

[Fact]
public void CanCompareASubsetofTheTreeAgainstTheIndexWithLaxExplicitPathsValidationAndANonExistentPath()
{
using (var repo = new Repository(StandardTestRepoPath))
{
Tree tree = repo.Head.Tip.Tree;

TreeChanges changes = repo.Diff.Compare(tree, DiffTargets.Index,
new[] { "deleted_staged_file.txt", "1/branch_file.txt", "I-do/not-exist" }, new ExplicitPathsOptions { ShouldFailOnUnmatchedPath = false });
AssertCanCompareASubsetOfTheTreeAgainstTheIndex(changes);

changes = repo.Diff.Compare(tree, DiffTargets.Index,
new[] { "deleted_staged_file.txt", "1/branch_file.txt", "I-do/not-exist" });
AssertCanCompareASubsetOfTheTreeAgainstTheIndex(changes);
}
}

[Fact]
public void ComparingASubsetofTheTreeAgainstTheIndexWithStrictExplicitPathsValidationAndANonExistentPathThrows()
{
using (var repo = new Repository(StandardTestRepoPath))
{
Tree tree = repo.Head.Tip.Tree;

Assert.Throws<UnmatchedPathException>(() => repo.Diff.Compare(tree, DiffTargets.Index,
new[] { "deleted_staged_file.txt", "1/branch_file.txt", "I-do/not-exist" }, new ExplicitPathsOptions()));
}
}

[Fact]
/*
* $ git init .
Expand Down
34 changes: 33 additions & 1 deletion LibGit2Sharp.Tests/DiffTreeToTreeFixture.cs
Original file line number Diff line number Diff line change
Expand Up @@ -87,7 +87,7 @@ public void CanCompareASubsetofTheTreeAgainstOneOfItsAncestor()
Tree tree = repo.Head.Tip.Tree;
Tree ancestor = repo.Lookup<Commit>("9fd738e").Tree;

TreeChanges changes = repo.Diff.Compare(ancestor, tree, new[]{ "1", "2/" });
TreeChanges changes = repo.Diff.Compare(ancestor, tree, new[]{ "1" });
Assert.NotNull(changes);

Assert.Equal(1, changes.Count());
Expand Down Expand Up @@ -133,6 +133,38 @@ public void CanCompareACommitTreeAgainstATreeWithNoCommonAncestor()
}
}

[Fact]
public void CanCompareATreeAgainstAnotherTreeWithLaxExplicitPathsValidationAndNonExistentPath()
{
using (var repo = new Repository(StandardTestRepoPath))
{
Tree commitTree = repo.Head.Tip.Tree;
Tree commitTreeWithDifferentAncestor = repo.Branches["refs/remotes/origin/test"].Tip.Tree;

TreeChanges changes = repo.Diff.Compare(commitTreeWithDifferentAncestor, commitTree,
new[] { "if-I-exist-this-test-is-really-unlucky.txt" }, new ExplicitPathsOptions { ShouldFailOnUnmatchedPath = false });
Assert.Equal(0, changes.Count());

changes = repo.Diff.Compare(commitTreeWithDifferentAncestor, commitTree,
new[] { "if-I-exist-this-test-is-really-unlucky.txt" });
Assert.Equal(0, changes.Count());
}
}

[Fact]
public void ComparingATreeAgainstAnotherTreeWithStrictExplicitPathsValidationThrows()
{
using (var repo = new Repository(StandardTestRepoPath))
{
Tree commitTree = repo.Head.Tip.Tree;
Tree commitTreeWithDifferentAncestor = repo.Branches["refs/remotes/origin/test"].Tip.Tree;

Assert.Throws<UnmatchedPathException>(() =>
repo.Diff.Compare(commitTreeWithDifferentAncestor, commitTree,
new[] { "if-I-exist-this-test-is-really-unlucky.txt" }, new ExplicitPathsOptions()));
}
}

/*
* $ git diff -M f8d44d7..4be51d6
* diff --git a/my-name-does-not-feel-right.txt b/super-file.txt
Expand Down
127 changes: 127 additions & 0 deletions LibGit2Sharp.Tests/DiffWorkdirToIndexFixture.cs
Original file line number Diff line number Diff line change
@@ -1,6 +1,10 @@
using System;
using System.IO;
using System.Linq;
using System.Text;
using LibGit2Sharp.Tests.TestHelpers;
using Xunit;
using Xunit.Extensions;

namespace LibGit2Sharp.Tests
{
Expand Down Expand Up @@ -36,6 +40,129 @@ public void CanCompareTheWorkDirAgainstTheIndex()
}
}

[Theory]
[InlineData("new_untracked_file.txt", FileStatus.Untracked)]
[InlineData("really-i-cant-exist.txt", FileStatus.Nonexistent)]
public void CanCompareTheWorkDirAgainstTheIndexWithLaxUnmatchedExplicitPathsValidation(string relativePath, FileStatus currentStatus)
{
using (var repo = new Repository(StandardTestRepoPath))
{
Assert.Equal(currentStatus, repo.Index.RetrieveStatus(relativePath));

TreeChanges changes = repo.Diff.Compare(new[] { relativePath }, false, new ExplicitPathsOptions { ShouldFailOnUnmatchedPath = false });
Assert.Equal(0, changes.Count());

changes = repo.Diff.Compare(new[] { relativePath });
Assert.Equal(0, changes.Count());
}
}

[Theory]
[InlineData("new_untracked_file.txt", FileStatus.Untracked)]
[InlineData("really-i-cant-exist.txt", FileStatus.Nonexistent)]
public void ComparingTheWorkDirAgainstTheIndexWithStrictUnmatchedExplicitPathsValidationAndANonExistentPathspecThrows(string relativePath, FileStatus currentStatus)
{
using (var repo = new Repository(StandardTestRepoPath))
{
Assert.Equal(currentStatus, repo.Index.RetrieveStatus(relativePath));

Assert.Throws<UnmatchedPathException>(() => repo.Diff.Compare(new[] { relativePath }, false, new ExplicitPathsOptions()));
}
}

[Theory]
[InlineData("new_untracked_file.txt", FileStatus.Untracked)]
[InlineData("where-am-I.txt", FileStatus.Nonexistent)]
public void CallbackForUnmatchedExplicitPathsIsCalledWhenSet(string relativePath, FileStatus currentStatus)
{
var callback = new AssertUnmatchedPathspecsCallbackIsCalled();

using (var repo = new Repository(StandardTestRepoPath))
{
Assert.Equal(currentStatus, repo.Index.RetrieveStatus(relativePath));

repo.Diff.Compare(new[] { relativePath }, false, new ExplicitPathsOptions { ShouldFailOnUnmatchedPath = false,
OnUnmatchedPath = callback.OnUnmatchedPath });

Assert.True(callback.WasCalled);
}
}

private class AssertUnmatchedPathspecsCallbackIsCalled
{
public bool WasCalled;

public void OnUnmatchedPath(string unmatchedpath)
{
WasCalled = true;
}
}

[Fact]
public void ComparingReliesOnProvidedConfigEntriesIfAny()
{
const string file = "1/branch_file.txt";

string path = CloneStandardTestRepo();
using (var repo = new Repository(path))
{
TreeEntry entry = repo.Head[file];
Assert.Equal(Mode.ExecutableFile, entry.Mode);

// Recreate the file in the workdir without the executable bit
string fullpath = Path.Combine(repo.Info.WorkingDirectory, file);
File.Delete(fullpath);
File.WriteAllBytes(fullpath, ((Blob)(entry.Target)).Content);

// Unset the local core.filemode, if any.
repo.Config.Unset("core.filemode", ConfigurationLevel.Local);
}

SelfCleaningDirectory scd = BuildSelfCleaningDirectory();

var options = BuildFakeSystemConfigFilemodeOption(scd, true);

using (var repo = new Repository(path, options))
{
TreeChanges changes = repo.Diff.Compare(new[] { file });

Assert.Equal(1, changes.Count());

var change = changes.Modified.Single();
Assert.Equal(Mode.ExecutableFile, change.OldMode);
Assert.Equal(Mode.NonExecutableFile, change.Mode);
}

options = BuildFakeSystemConfigFilemodeOption(scd, false);

using (var repo = new Repository(path, options))
{
TreeChanges changes = repo.Diff.Compare(new[] { file });

Assert.Equal(0, changes.Count());
}
}

private RepositoryOptions BuildFakeSystemConfigFilemodeOption(
SelfCleaningDirectory scd,
bool value)
{
Directory.CreateDirectory(scd.DirectoryPath);

var options = new RepositoryOptions
{
SystemConfigurationLocation = Path.Combine(
scd.RootedDirectoryPath, "fake-system.config")
};

StringBuilder sb = new StringBuilder()
.AppendFormat("[core]{0}", Environment.NewLine)
.AppendFormat("filemode = {1}{0}", Environment.NewLine, value);
File.WriteAllText(options.SystemConfigurationLocation, sb.ToString());

return options;
}

[Fact]
public void CanCompareTheWorkDirAgainstTheIndexWithUntrackedFiles()
{
Expand Down
1 change: 1 addition & 0 deletions LibGit2Sharp.Tests/MetaFixture.cs
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@ public class MetaFixture
typeof(Repository),
typeof(RepositoryOptions),
typeof(Signature),
typeof(ExplicitPathsOptions),
};

// Related to https://github.com/libgit2/libgit2sharp/pull/251
Expand Down
15 changes: 13 additions & 2 deletions LibGit2Sharp.Tests/ResetIndexFixture.cs
Original file line number Diff line number Diff line change
Expand Up @@ -124,16 +124,27 @@ public void CanResetTheIndexToASubsetOfTheContentOfACommitWithCommitishAsArgumen
}

[Fact]
public void CanResetTheIndexToASubsetOfTheContentOfACommitWithCommitAsArgument()
public void CanResetTheIndexToASubsetOfTheContentOfACommitWithCommitAsArgumentAndLaxUnmatchedExplicitPathsValidation()
{
string path = CloneStandardTestRepo();
using (var repo = new Repository(path))
{
repo.Reset(repo.Lookup<Commit>("5b5b025"), new[] { "new.txt" });
repo.Reset(repo.Lookup<Commit>("5b5b025"), new[] { "new.txt", "non-existent-path-28.txt" },
new ExplicitPathsOptions { ShouldFailOnUnmatchedPath = false });

Assert.Equal("a8233120f6ad708f843d861ce2b7228ec4e3dec6", repo.Index["README"].Id.Sha);
Assert.Equal("fa49b077972391ad58037050f2a75f74e3671e92", repo.Index["new.txt"].Id.Sha);
}
}

[Fact]
public void ResettingTheIndexToASubsetOfTheContentOfACommitWithCommitAsArgumentAndStrictUnmatchedPathspecsValidationThrows()
{
using (var repo = new Repository(CloneStandardTestRepo()))
{
Assert.Throws<UnmatchedPathException>(() =>
repo.Reset(repo.Lookup<Commit>("5b5b025"), new[] { "new.txt", "non-existent-path-28.txt" }, new ExplicitPathsOptions()));
}
}
}
}
89 changes: 86 additions & 3 deletions LibGit2Sharp.Tests/StageFixture.cs
Original file line number Diff line number Diff line change
Expand Up @@ -60,14 +60,46 @@ public void CanStageTheUpdationOfAStagedFile()
[Theory]
[InlineData("1/I-do-not-exist.txt", FileStatus.Nonexistent)]
[InlineData("deleted_staged_file.txt", FileStatus.Removed)]
public void StagingAnUnknownFileThrows(string relativePath, FileStatus status)
public void StagingAnUnknownFileThrowsIfExplicitPath(string relativePath, FileStatus status)
{
using (var repo = new Repository(StandardTestRepoPath))
{
Assert.Null(repo.Index[relativePath]);
Assert.Equal(status, repo.Index.RetrieveStatus(relativePath));

Assert.Throws<LibGit2SharpException>(() => repo.Index.Stage(relativePath));
Assert.Throws<UnmatchedPathException>(() => repo.Index.Stage(relativePath, new ExplicitPathsOptions()));
}
}

[Theory]
[InlineData("1/I-do-not-exist.txt", FileStatus.Nonexistent)]
[InlineData("deleted_staged_file.txt", FileStatus.Removed)]
public void CanStageAnUnknownFileWithLaxUnmatchedExplicitPathsValidation(string relativePath, FileStatus status)
{
using (var repo = new Repository(StandardTestRepoPath))
{
Assert.Null(repo.Index[relativePath]);
Assert.Equal(status, repo.Index.RetrieveStatus(relativePath));

Assert.DoesNotThrow(() => repo.Index.Stage(relativePath));
Assert.DoesNotThrow(() => repo.Index.Stage(relativePath, new ExplicitPathsOptions { ShouldFailOnUnmatchedPath = false }));

Assert.Equal(status, repo.Index.RetrieveStatus(relativePath));
}
}

[Theory]
[InlineData("1/I-do-not-exist.txt", FileStatus.Nonexistent)]
[InlineData("deleted_staged_file.txt", FileStatus.Removed)]
public void StagingAnUnknownFileWithLaxExplicitPathsValidationDoesntThrow(string relativePath, FileStatus status)
{
using (var repo = new Repository(StandardTestRepoPath))
{
Assert.Null(repo.Index[relativePath]);
Assert.Equal(status, repo.Index.RetrieveStatus(relativePath));

repo.Index.Stage(relativePath);
repo.Index.Stage(relativePath, new ExplicitPathsOptions { ShouldFailOnUnmatchedPath = false });
}
}

Expand Down Expand Up @@ -199,7 +231,7 @@ public void StagingANewFileWithAFullPathWhichEscapesOutOfTheWorkingDirThrows()
}

[Fact]
public void StageFileWithBadParamsThrows()
public void StagingFileWithBadParamsThrows()
{
using (var repo = new Repository(StandardTestRepoPath))
{
Expand All @@ -209,5 +241,56 @@ public void StageFileWithBadParamsThrows()
Assert.Throws<ArgumentException>(() => repo.Index.Stage(new string[] { null }));
}
}

/*
* $ git status -s
* M 1/branch_file.txt
* M README
* M branch_file.txt
* D deleted_staged_file.txt
* D deleted_unstaged_file.txt
* M modified_staged_file.txt
* M modified_unstaged_file.txt
* M new.txt
* A new_tracked_file.txt
* ?? new_untracked_file.txt
*
* By passing "*" to Stage, the following files will be added/removed/updated from the index:
* - deleted_unstaged_file.txt : removed
* - modified_unstaged_file.txt : updated
* - new_untracked_file.txt : added
*/
[Theory]
[InlineData("*u*", 0)]
[InlineData("*", 0)]
[InlineData("1/*", 0)]
[InlineData("RE*", 0)]
[InlineData("d*", -1)]
[InlineData("*modified_unstaged*", 0)]
[InlineData("new_*file.txt", 1)]
public void CanStageWithPathspec(string relativePath, int expectedIndexCountVariation)
{
using (var repo = new Repository(CloneStandardTestRepo()))
{
int count = repo.Index.Count;

repo.Index.Stage(relativePath);

Assert.Equal(count + expectedIndexCountVariation, repo.Index.Count);
}
}

[Fact]
public void CanStageWithMultiplePathspecs()
{
using (var repo = new Repository(CloneStandardTestRepo()))
{
int count = repo.Index.Count;

repo.Index.Stage(new string[] { "*", "u*" });

Assert.Equal(count, repo.Index.Count); // 1 added file, 1 deleted file, so same count
}
}
}
}
Loading