libgit2sharp/LibGit2Sharp.Tests/CommitFixture.cs

884 строки
34 KiB
C#

using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using LibGit2Sharp.Core;
using LibGit2Sharp.Tests.TestHelpers;
using Xunit;
namespace LibGit2Sharp.Tests
{
public class CommitFixture : BaseFixture
{
private const string sha = "8496071c1b46c854b31185ea97743be6a8774479";
private readonly List<string> expectedShas = new List<string> { "a4a7d", "c4780", "9fd73", "4a202", "5b5b0", "84960" };
[Fact]
public void CanCountCommits()
{
using (var repo = new Repository(BareTestRepoPath))
{
Assert.Equal(7, repo.Commits.Count());
}
}
[Fact]
public void CanCorrectlyCountCommitsWhenSwitchingToAnotherBranch()
{
string path = CloneStandardTestRepo();
using (var repo = new Repository(path))
{
// Hard reset and then remove untracked files
repo.Reset(ResetOptions.Hard);
repo.RemoveUntrackedFiles();
repo.Checkout("test");
Assert.Equal(2, repo.Commits.Count());
Assert.Equal("e90810b8df3e80c413d903f631643c716887138d", repo.Commits.First().Id.Sha);
repo.Checkout("master");
Assert.Equal(9, repo.Commits.Count());
Assert.Equal("32eab9cb1f450b5fe7ab663462b77d7f4b703344", repo.Commits.First().Id.Sha);
}
}
[Fact]
public void CanEnumerateCommits()
{
int count = 0;
using (var repo = new Repository(BareTestRepoPath))
{
foreach (Commit commit in repo.Commits)
{
Assert.NotNull(commit);
count++;
}
}
Assert.Equal(7, count);
}
[Fact]
public void CanEnumerateCommitsInDetachedHeadState()
{
string path = CloneBareTestRepo();
using (var repo = new Repository(path))
{
ObjectId parentOfHead = repo.Head.Tip.Parents.First().Id;
repo.Refs.Add("HEAD", parentOfHead.Sha, true);
Assert.Equal(true, repo.Info.IsHeadDetached);
Assert.Equal(6, repo.Commits.Count());
}
}
[Fact]
public void DefaultOrderingWhenEnumeratingCommitsIsTimeBased()
{
using (var repo = new Repository(BareTestRepoPath))
{
Assert.Equal(CommitSortStrategies.Time, repo.Commits.SortedBy);
}
}
[Fact]
public void CanEnumerateCommitsFromSha()
{
int count = 0;
using (var repo = new Repository(BareTestRepoPath))
{
foreach (Commit commit in repo.Commits.QueryBy(new CommitFilter { Since = "a4a7dce85cf63874e984719f4fdd239f5145052f" }))
{
Assert.NotNull(commit);
count++;
}
}
Assert.Equal(6, count);
}
[Fact]
public void QueryingTheCommitHistoryWithUnknownShaOrInvalidEntryPointThrows()
{
using (var repo = new Repository(BareTestRepoPath))
{
Assert.Throws<LibGit2SharpException>(() => repo.Commits.QueryBy(new CommitFilter { Since = Constants.UnknownSha }).Count());
Assert.Throws<LibGit2SharpException>(() => repo.Commits.QueryBy(new CommitFilter { Since = "refs/heads/deadbeef" }).Count());
Assert.Throws<ArgumentNullException>(() => repo.Commits.QueryBy(new CommitFilter { Since = null }).Count());
}
}
[Fact]
public void QueryingTheCommitHistoryFromACorruptedReferenceThrows()
{
string path = CloneBareTestRepo();
using (var repo = new Repository(path))
{
CreateCorruptedDeadBeefHead(repo.Info.Path);
Assert.Throws<LibGit2SharpException>(() => repo.Commits.QueryBy(new CommitFilter { Since = repo.Branches["deadbeef"] }).Count());
Assert.Throws<LibGit2SharpException>(() => repo.Commits.QueryBy(new CommitFilter { Since = repo.Refs["refs/heads/deadbeef"] }).Count());
}
}
[Fact]
public void QueryingTheCommitHistoryWithBadParamsThrows()
{
using (var repo = new Repository(BareTestRepoPath))
{
Assert.Throws<ArgumentException>(() => repo.Commits.QueryBy(new CommitFilter { Since = string.Empty }));
Assert.Throws<ArgumentNullException>(() => repo.Commits.QueryBy(new CommitFilter { Since = null }));
Assert.Throws<ArgumentNullException>(() => repo.Commits.QueryBy(default(CommitFilter)));
}
}
[Fact]
public void CanEnumerateCommitsWithReverseTimeSorting()
{
var reversedShas = new List<string>(expectedShas);
reversedShas.Reverse();
int count = 0;
using (var repo = new Repository(BareTestRepoPath))
{
foreach (Commit commit in repo.Commits.QueryBy(new CommitFilter
{
Since = "a4a7dce85cf63874e984719f4fdd239f5145052f",
SortBy = CommitSortStrategies.Time | CommitSortStrategies.Reverse
}))
{
Assert.NotNull(commit);
Assert.True(commit.Sha.StartsWith(reversedShas[count]));
count++;
}
}
Assert.Equal(6, count);
}
[Fact]
public void CanEnumerateCommitsWithReverseTopoSorting()
{
using (var repo = new Repository(BareTestRepoPath))
{
List<Commit> commits = repo.Commits.QueryBy(new CommitFilter
{
Since = "a4a7dce85cf63874e984719f4fdd239f5145052f",
SortBy = CommitSortStrategies.Time | CommitSortStrategies.Reverse
}).ToList();
foreach (Commit commit in commits)
{
Assert.NotNull(commit);
foreach (Commit p in commit.Parents)
{
Commit parent = commits.Single(x => x.Id == p.Id);
Assert.True(commits.IndexOf(commit) > commits.IndexOf(parent));
}
}
}
}
[Fact]
public void CanGetParentsCount()
{
using (var repo = new Repository(BareTestRepoPath))
{
Assert.Equal(1, repo.Commits.First().Parents.Count());
}
}
[Fact]
public void CanEnumerateCommitsWithTimeSorting()
{
int count = 0;
using (var repo = new Repository(BareTestRepoPath))
{
foreach (Commit commit in repo.Commits.QueryBy(new CommitFilter
{
Since = "a4a7dce85cf63874e984719f4fdd239f5145052f",
SortBy = CommitSortStrategies.Time
}))
{
Assert.NotNull(commit);
Assert.True(commit.Sha.StartsWith(expectedShas[count]));
count++;
}
}
Assert.Equal(6, count);
}
[Fact]
public void CanEnumerateCommitsWithTopoSorting()
{
using (var repo = new Repository(BareTestRepoPath))
{
List<Commit> commits = repo.Commits.QueryBy(new CommitFilter
{
Since = "a4a7dce85cf63874e984719f4fdd239f5145052f",
SortBy = CommitSortStrategies.Topological
}).ToList();
foreach (Commit commit in commits)
{
Assert.NotNull(commit);
foreach (Commit p in commit.Parents)
{
Commit parent = commits.Single(x => x.Id == p.Id);
Assert.True(commits.IndexOf(commit) < commits.IndexOf(parent));
}
}
}
}
[Fact]
public void CanEnumerateFromHead()
{
AssertEnumerationOfCommits(
repo => new CommitFilter { Since = repo.Head },
new[]
{
"4c062a6", "be3563a", "c47800c", "9fd738e",
"4a202b3", "5b5b025", "8496071",
});
}
[Fact]
public void CanEnumerateFromDetachedHead()
{
string path = CloneStandardTestRepo();
using (var repoClone = new Repository(path))
{
// Hard reset and then remove untracked files
repoClone.Reset(ResetOptions.Hard);
repoClone.RemoveUntrackedFiles();
string headSha = repoClone.Head.Tip.Sha;
repoClone.Checkout(headSha);
AssertEnumerationOfCommitsInRepo(repoClone,
repo => new CommitFilter { Since = repo.Head },
new[]
{
"32eab9c", "592d3c8", "4c062a6",
"be3563a", "c47800c", "9fd738e",
"4a202b3", "5b5b025", "8496071",
});
}
}
[Fact]
public void CanEnumerateUsingTwoHeadsAsBoundaries()
{
AssertEnumerationOfCommits(
repo => new CommitFilter { Since = "HEAD", Until = "refs/heads/br2" },
new[] { "4c062a6", "be3563a" }
);
}
[Fact]
public void CanEnumerateUsingImplicitHeadAsSinceBoundary()
{
AssertEnumerationOfCommits(
repo => new CommitFilter { Until = "refs/heads/br2" },
new[] { "4c062a6", "be3563a" }
);
}
[Fact]
public void CanEnumerateUsingTwoAbbreviatedShasAsBoundaries()
{
AssertEnumerationOfCommits(
repo => new CommitFilter { Since = "a4a7dce", Until = "4a202b3" },
new[] { "a4a7dce", "c47800c", "9fd738e" }
);
}
[Fact]
public void CanEnumerateCommitsFromTwoHeads()
{
AssertEnumerationOfCommits(
repo => new CommitFilter { Since = new[] { "refs/heads/br2", "refs/heads/master" } },
new[]
{
"4c062a6", "a4a7dce", "be3563a", "c47800c",
"9fd738e", "4a202b3", "5b5b025", "8496071",
});
}
[Fact]
public void CanEnumerateCommitsFromMixedStartingPoints()
{
AssertEnumerationOfCommits(
repo => new CommitFilter { Since = new object[] { repo.Branches["br2"],
"refs/heads/master",
new ObjectId("e90810b8df3e80c413d903f631643c716887138d") } },
new[]
{
"4c062a6", "e90810b", "6dcf9bf", "a4a7dce",
"be3563a", "c47800c", "9fd738e", "4a202b3",
"5b5b025", "8496071",
});
}
[Fact]
public void CanEnumerateCommitsUsingGlob()
{
AssertEnumerationOfCommits(
repo => new CommitFilter { Since = repo.Refs.FromGlob("refs/heads/*") },
new[]
{
"4c062a6", "e90810b", "6dcf9bf", "a4a7dce", "be3563a", "c47800c", "9fd738e", "4a202b3", "41bc8c6", "5001298", "5b5b025", "8496071"
});
}
[Fact]
public void CanHideCommitsUsingGlob()
{
AssertEnumerationOfCommits(
repo => new CommitFilter { Since = "refs/heads/packed-test", Until = repo.Refs.FromGlob("*/packed") },
new[]
{
"4a202b3", "5b5b025", "8496071"
});
}
[Fact]
public void CanEnumerateCommitsFromAnAnnotatedTag()
{
CanEnumerateCommitsFromATag(t => t);
}
[Fact]
public void CanEnumerateCommitsFromATagAnnotation()
{
CanEnumerateCommitsFromATag(t => t.Annotation);
}
private static void CanEnumerateCommitsFromATag(Func<Tag, object> transformer)
{
AssertEnumerationOfCommits(
repo => new CommitFilter { Since = transformer(repo.Tags["test"]) },
new[] { "e90810b", "6dcf9bf", }
);
}
[Fact]
public void CanEnumerateAllCommits()
{
AssertEnumerationOfCommits(
repo => new CommitFilter
{
Since = repo.Refs.OrderBy(r => r.CanonicalName, StringComparer.Ordinal),
},
new[]
{
"44d5d18", "bb65291", "532740a", "503a16f", "3dfd6fd",
"4409de1", "902c60b", "4c062a6", "e90810b", "6dcf9bf",
"a4a7dce", "be3563a", "c47800c", "9fd738e", "4a202b3",
"41bc8c6", "5001298", "5b5b025", "8496071",
});
}
[Fact]
public void CanEnumerateCommitsFromATagWhichPointsToABlob()
{
AssertEnumerationOfCommits(
repo => new CommitFilter { Since = repo.Tags["point_to_blob"] },
new string[] { });
}
[Fact]
public void CanEnumerateCommitsFromATagWhichPointsToATree()
{
string path = CloneBareTestRepo();
using (var repo = new Repository(path))
{
string headTreeSha = repo.Head.Tip.Tree.Sha;
Tag tag = repo.ApplyTag("point_to_tree", headTreeSha);
AssertEnumerationOfCommitsInRepo(repo,
r => new CommitFilter { Since = tag },
new string[] { });
}
}
private static void AssertEnumerationOfCommits(Func<Repository, CommitFilter> filterBuilder, IEnumerable<string> abbrevIds)
{
using (var repo = new Repository(BareTestRepoPath))
{
AssertEnumerationOfCommitsInRepo(repo, filterBuilder, abbrevIds);
}
}
private static void AssertEnumerationOfCommitsInRepo(Repository repo, Func<Repository, CommitFilter> filterBuilder, IEnumerable<string> abbrevIds)
{
ICommitLog commits = repo.Commits.QueryBy(filterBuilder(repo));
IEnumerable<string> commitShas = commits.Select(c => c.Id.ToString(7)).ToArray();
Assert.Equal(abbrevIds, commitShas);
}
[Fact]
public void CanLookupCommitGeneric()
{
using (var repo = new Repository(BareTestRepoPath))
{
var commit = repo.Lookup<Commit>(sha);
Assert.Equal("testing\n", commit.Message);
Assert.Equal("testing", commit.MessageShort);
Assert.Equal(sha, commit.Sha);
}
}
[Fact]
public void CanReadCommitData()
{
using (var repo = new Repository(BareTestRepoPath))
{
GitObject obj = repo.Lookup(sha);
Assert.NotNull(obj);
Assert.Equal(typeof(Commit), obj.GetType());
var commit = (Commit)obj;
Assert.Equal("testing\n", commit.Message);
Assert.Equal("testing", commit.MessageShort);
Assert.Equal("UTF-8", commit.Encoding);
Assert.Equal(sha, commit.Sha);
Assert.NotNull(commit.Author);
Assert.Equal("Scott Chacon", commit.Author.Name);
Assert.Equal("schacon@gmail.com", commit.Author.Email);
Assert.Equal(1273360386, commit.Author.When.ToSecondsSinceEpoch());
Assert.NotNull(commit.Committer);
Assert.Equal("Scott Chacon", commit.Committer.Name);
Assert.Equal("schacon@gmail.com", commit.Committer.Email);
Assert.Equal(1273360386, commit.Committer.When.ToSecondsSinceEpoch());
Assert.Equal("181037049a54a1eb5fab404658a3a250b44335d7", commit.Tree.Sha);
Assert.Equal(0, commit.Parents.Count());
}
}
[Fact]
public void CanReadCommitWithMultipleParents()
{
using (var repo = new Repository(BareTestRepoPath))
{
var commit = repo.Lookup<Commit>("a4a7dce85cf63874e984719f4fdd239f5145052f");
Assert.Equal(2, commit.Parents.Count());
}
}
[Fact]
public void CanDirectlyAccessABlobOfTheCommit()
{
using (var repo = new Repository(BareTestRepoPath))
{
var commit = repo.Lookup<Commit>("4c062a6");
var blob = commit["1/branch_file.txt"].Target as Blob;
Assert.NotNull(blob);
Assert.Equal("hi\n", blob.ContentAsText());
}
}
[Fact]
public void CanDirectlyAccessATreeOfTheCommit()
{
using (var repo = new Repository(BareTestRepoPath))
{
var commit = repo.Lookup<Commit>("4c062a6");
var tree1 = commit["1"].Target as Tree;
Assert.NotNull(tree1);
}
}
[Fact]
public void DirectlyAccessingAnUnknownTreeEntryOfTheCommitReturnsNull()
{
using (var repo = new Repository(BareTestRepoPath))
{
var commit = repo.Lookup<Commit>("4c062a6");
Assert.Null(commit["I-am-not-here"]);
}
}
[SkippableFact]
public void CanCommitWithSignatureFromConfig()
{
string repoPath = InitNewRepository();
using (var repo = new Repository(repoPath))
{
string dir = repo.Info.Path;
Assert.True(Path.IsPathRooted(dir));
Assert.True(Directory.Exists(dir));
InconclusiveIf(() => !repo.Config.HasConfig(ConfigurationLevel.Global),
"No Git global configuration available");
const string relativeFilepath = "new.txt";
string filePath = Touch(repo.Info.WorkingDirectory, relativeFilepath, "null");
repo.Index.Stage(relativeFilepath);
File.AppendAllText(filePath, "token\n");
repo.Index.Stage(relativeFilepath);
Assert.Null(repo.Head[relativeFilepath]);
Commit commit = repo.Commit("Initial egotistic commit");
AssertBlobContent(repo.Head[relativeFilepath], "nulltoken\n");
AssertBlobContent(commit[relativeFilepath], "nulltoken\n");
var name = repo.Config.Get<string>("user.name");
var email = repo.Config.Get<string>("user.email");
Assert.Equal(commit.Author.Name, name.Value);
Assert.Equal(commit.Author.Email, email.Value);
Assert.Equal(commit.Committer.Name, name.Value);
Assert.Equal(commit.Committer.Email, email.Value);
}
}
[Fact]
public void CommitParentsAreMergeHeads()
{
string path = CloneStandardTestRepo();
using (var repo = new Repository(path))
{
repo.Reset(ResetOptions.Hard, "c47800");
CreateAndStageANewFile(repo);
Touch(repo.Info.Path, "MERGE_HEAD", "9fd738e8f7967c078dceed8190330fc8648ee56a\n");
Assert.Equal(CurrentOperation.Merge, repo.Info.CurrentOperation);
Commit newMergedCommit = repo.Commit("Merge commit", Constants.Signature, Constants.Signature);
Assert.Equal(CurrentOperation.None, repo.Info.CurrentOperation);
Assert.Equal(2, newMergedCommit.Parents.Count());
Assert.Equal(newMergedCommit.Parents.First().Sha, "c47800c7266a2be04c571c04d5a6614691ea99bd");
Assert.Equal(newMergedCommit.Parents.Skip(1).First().Sha, "9fd738e8f7967c078dceed8190330fc8648ee56a");
// Assert reflog entry is created
var reflogEntry = repo.Refs.Log(repo.Refs.Head).First();
Assert.Equal(repo.Head.Tip.Id, reflogEntry.To);
Assert.NotNull(reflogEntry.Commiter.Email);
Assert.NotNull(reflogEntry.Commiter.Name);
Assert.Equal(string.Format("commit (merge): {0}", newMergedCommit.MessageShort), reflogEntry.Message);
}
}
[Fact]
public void CommitCleansUpMergeMetadata()
{
string repoPath = InitNewRepository();
using (var repo = new Repository(repoPath))
{
string dir = repo.Info.Path;
Assert.True(Path.IsPathRooted(dir));
Assert.True(Directory.Exists(dir));
const string relativeFilepath = "new.txt";
Touch(repo.Info.WorkingDirectory, relativeFilepath, "this is a new file");
repo.Index.Stage(relativeFilepath);
string mergeHeadPath = Touch(repo.Info.Path, "MERGE_HEAD", "abcdefabcdefabcdefabcdefabcdefabcdefabcd");
string mergeMsgPath = Touch(repo.Info.Path, "MERGE_MSG", "This is a dummy merge.\n");
string mergeModePath = Touch(repo.Info.Path, "MERGE_MODE", "no-ff");
string origHeadPath = Touch(repo.Info.Path, "ORIG_HEAD", "beefbeefbeefbeefbeefbeefbeefbeefbeefbeef");
Assert.True(File.Exists(mergeHeadPath));
Assert.True(File.Exists(mergeMsgPath));
Assert.True(File.Exists(mergeModePath));
Assert.True(File.Exists(origHeadPath));
var author = Constants.Signature;
repo.Commit("Initial egotistic commit", author, author);
Assert.False(File.Exists(mergeHeadPath));
Assert.False(File.Exists(mergeMsgPath));
Assert.False(File.Exists(mergeModePath));
Assert.True(File.Exists(origHeadPath));
}
}
[Fact]
public void CanCommitALittleBit()
{
string repoPath = InitNewRepository();
using (var repo = new Repository(repoPath))
{
string dir = repo.Info.Path;
Assert.True(Path.IsPathRooted(dir));
Assert.True(Directory.Exists(dir));
const string relativeFilepath = "new.txt";
string filePath = Touch(repo.Info.WorkingDirectory, relativeFilepath, "null");
repo.Index.Stage(relativeFilepath);
File.AppendAllText(filePath, "token\n");
repo.Index.Stage(relativeFilepath);
Assert.Null(repo.Head[relativeFilepath]);
var author = Constants.Signature;
const string shortMessage = "Initial egotistic commit";
const string commitMessage = shortMessage + "\n\nOnly the coolest commits from us";
Commit commit = repo.Commit(commitMessage, author, author);
AssertBlobContent(repo.Head[relativeFilepath], "nulltoken\n");
AssertBlobContent(commit[relativeFilepath], "nulltoken\n");
Assert.Equal(0, commit.Parents.Count());
Assert.False(repo.Info.IsHeadUnborn);
// Assert a reflog entry is created on HEAD
Assert.Equal(1, repo.Refs.Log("HEAD").Count());
var reflogEntry = repo.Refs.Log("HEAD").First();
Assert.Equal(author, reflogEntry.Commiter);
Assert.Equal(commit.Id, reflogEntry.To);
Assert.Equal(ObjectId.Zero, reflogEntry.From);
Assert.Equal(string.Format("commit (initial): {0}", shortMessage), reflogEntry.Message);
// Assert a reflog entry is created on HEAD target
var targetCanonicalName = repo.Refs.Head.TargetIdentifier;
Assert.Equal(1, repo.Refs.Log(targetCanonicalName).Count());
Assert.Equal(commit.Id, repo.Refs.Log(targetCanonicalName).First().To);
File.WriteAllText(filePath, "nulltoken commits!\n");
repo.Index.Stage(relativeFilepath);
var author2 = new Signature(author.Name, author.Email, author.When.AddSeconds(5));
Commit commit2 = repo.Commit("Are you trying to fork me?", author2, author2);
AssertBlobContent(repo.Head[relativeFilepath], "nulltoken commits!\n");
AssertBlobContent(commit2[relativeFilepath], "nulltoken commits!\n");
Assert.Equal(1, commit2.Parents.Count());
Assert.Equal(commit.Id, commit2.Parents.First().Id);
// Assert the reflog is shifted
Assert.Equal(2, repo.Refs.Log("HEAD").Count());
Assert.Equal(reflogEntry.To, repo.Refs.Log("HEAD").First().From);
Branch firstCommitBranch = repo.CreateBranch("davidfowl-rules", commit);
repo.Checkout(firstCommitBranch);
File.WriteAllText(filePath, "davidfowl commits!\n");
var author3 = new Signature("David Fowler", "david.fowler@microsoft.com", author.When.AddSeconds(2));
repo.Index.Stage(relativeFilepath);
Commit commit3 = repo.Commit("I'm going to branch you backwards in time!", author3, author3);
AssertBlobContent(repo.Head[relativeFilepath], "davidfowl commits!\n");
AssertBlobContent(commit3[relativeFilepath], "davidfowl commits!\n");
Assert.Equal(1, commit3.Parents.Count());
Assert.Equal(commit.Id, commit3.Parents.First().Id);
AssertBlobContent(firstCommitBranch[relativeFilepath], "nulltoken\n");
}
}
private static void AssertBlobContent(TreeEntry entry, string expectedContent)
{
Assert.Equal(TreeEntryTargetType.Blob, entry.TargetType);
Assert.Equal(expectedContent, ((Blob)(entry.Target)).ContentAsText());
}
private static void AddCommitToRepo(string path)
{
using (var repo = new Repository(path))
{
const string relativeFilepath = "test.txt";
Touch(repo.Info.WorkingDirectory, relativeFilepath, "test\n");
repo.Index.Stage(relativeFilepath);
var author = new Signature("nulltoken", "emeric.fermas@gmail.com", DateTimeOffset.Parse("Wed, Dec 14 2011 08:29:03 +0100"));
repo.Commit("Initial commit", author, author);
}
}
[Fact]
public void CanGeneratePredictableObjectShas()
{
string repoPath = InitNewRepository();
AddCommitToRepo(repoPath);
using (var repo = new Repository(repoPath))
{
Commit commit = repo.Commits.Single();
Assert.Equal("1fe3126578fc4eca68c193e4a3a0a14a0704624d", commit.Sha);
Tree tree = commit.Tree;
Assert.Equal("2b297e643c551e76cfa1f93810c50811382f9117", tree.Sha);
GitObject blob = tree.Single().Target;
Assert.IsAssignableFrom<Blob>(blob);
Assert.Equal("9daeafb9864cf43055ae93beb0afd6c7d144bfa4", blob.Sha);
}
}
[Fact]
public void CanAmendARootCommit()
{
string repoPath = InitNewRepository();
AddCommitToRepo(repoPath);
using (var repo = new Repository(repoPath))
{
Assert.Equal(1, repo.Head.Commits.Count());
Commit originalCommit = repo.Head.Tip;
Assert.Equal(0, originalCommit.Parents.Count());
CreateAndStageANewFile(repo);
Commit amendedCommit = repo.Commit("I'm rewriting the history!", Constants.Signature, Constants.Signature, true);
Assert.Equal(1, repo.Head.Commits.Count());
AssertCommitHasBeenAmended(repo, amendedCommit, originalCommit);
}
}
[Fact]
public void CanAmendACommitWithMoreThanOneParent()
{
string path = CloneStandardTestRepo();
using (var repo = new Repository(path))
{
var mergedCommit = repo.Lookup<Commit>("be3563a");
Assert.NotNull(mergedCommit);
Assert.Equal(2, mergedCommit.Parents.Count());
repo.Reset(ResetOptions.Soft, mergedCommit.Sha);
CreateAndStageANewFile(repo);
const string commitMessage = "I'm rewriting the history!";
Commit amendedCommit = repo.Commit(commitMessage, Constants.Signature, Constants.Signature, true);
AssertCommitHasBeenAmended(repo, amendedCommit, mergedCommit);
AssertRefLogEntry(repo, "HEAD",
amendedCommit.Id,
string.Format("commit (amend): {0}", commitMessage),
mergedCommit.Id,
amendedCommit.Committer);
}
}
private static void CreateAndStageANewFile(Repository repo)
{
string relativeFilepath = string.Format("new-file-{0}.txt", Guid.NewGuid());
Touch(repo.Info.WorkingDirectory, relativeFilepath, "brand new content\n");
repo.Index.Stage(relativeFilepath);
}
private static void AssertCommitHasBeenAmended(Repository repo, Commit amendedCommit, Commit originalCommit)
{
Commit headCommit = repo.Head.Tip;
Assert.Equal(amendedCommit, headCommit);
Assert.NotEqual(originalCommit.Sha, amendedCommit.Sha);
Assert.Equal(originalCommit.Parents, amendedCommit.Parents);
}
[Fact]
public void CanNotAmendAnEmptyRepository()
{
string repoPath = InitNewRepository();
using (var repo = new Repository(repoPath))
{
Assert.Throws<UnbornBranchException>(() => repo.Commit("I can not amend anything !:(", Constants.Signature, Constants.Signature, true));
}
}
[Fact]
public void CanRetrieveChildrenOfASpecificCommit()
{
string path = CloneStandardTestRepo();
using (var repo = new Repository(path))
{
const string parentSha = "5b5b025afb0b4c913b4c338a42934a3863bf3644";
var filter = new CommitFilter
{
/* Revwalk from all the refs (git log --all) ... */
Since = repo.Refs,
/* ... and stop when the parent is reached */
Until = parentSha
};
var commits = repo.Commits.QueryBy(filter);
var children = from c in commits
from p in c.Parents
let pId = p.Id
where pId.Sha == parentSha
select c;
var expectedChildren = new[] { "c47800c7266a2be04c571c04d5a6614691ea99bd",
"4a202b346bb0fb0db7eff3cffeb3c70babbd2045" };
Assert.Equal(expectedChildren, children.Select(c => c.Id.Sha));
}
}
[Fact]
public void CanCorrectlyDistinguishAuthorFromCommitter()
{
string path = CloneStandardTestRepo();
using (var repo = new Repository(path))
{
var author = new Signature("Wilbert van Dolleweerd", "getit@xs4all.nl",
Epoch.ToDateTimeOffset(1244187936, 120));
var committer = new Signature("Henk Westhuis", "Henk_Westhuis@hotmail.com",
Epoch.ToDateTimeOffset(1244286496, 120));
Commit c = repo.Commit("I can haz an author and a committer!", author, committer);
Assert.Equal(author, c.Author);
Assert.Equal(committer, c.Committer);
}
}
[Fact]
public void CanCommitOnOrphanedBranch()
{
string newBranchName = "refs/heads/newBranch";
string repoPath = InitNewRepository();
using (var repo = new Repository(repoPath))
{
// Set Head to point to branch other than master
repo.Refs.UpdateTarget("HEAD", newBranchName);
Assert.Equal(newBranchName, repo.Head.CanonicalName);
const string relativeFilepath = "test.txt";
Touch(repo.Info.WorkingDirectory, relativeFilepath, "test\n");
repo.Index.Stage(relativeFilepath);
repo.Commit("Initial commit", Constants.Signature, Constants.Signature);
Assert.Equal(1, repo.Head.Commits.Count());
}
}
}
}