diff --git a/LibGit2Sharp.Tests/FilterBranchFixture.cs b/LibGit2Sharp.Tests/FilterBranchFixture.cs
index 96c583f76..efed5c0b6 100644
--- a/LibGit2Sharp.Tests/FilterBranchFixture.cs
+++ b/LibGit2Sharp.Tests/FilterBranchFixture.cs
@@ -213,6 +213,34 @@ public void CanRewriteTrees()
Assert.True(repo.Head.Commits.All(c => c["README"] == null));
}
+ [Fact]
+ public void CanRewriteTreesByInjectingTreeEntry()
+ {
+ var commits = repo.Commits.QueryBy(new CommitFilter { Since = repo.Branches }).ToArray();
+
+ var currentReadme = repo.Head["README"];
+
+ repo.Refs.RewriteHistory(new RewriteHistoryOptions
+ {
+ OnError = OnError,
+ OnSucceeding = OnSucceeding,
+ CommitTreeRewriter =
+ c => c["README"] == null
+ ? TreeDefinition.From(c)
+ : TreeDefinition.From(c)
+ .Add("README", currentReadme),
+ }, commits);
+
+ AssertSucceedingButNotError();
+
+ Assert.Equal(new Commit[0],
+ repo.Commits
+ .QueryBy(new CommitFilter {Since = repo.Branches})
+ .Where(c => c["README"] != null
+ && c["README"].Target.Id != currentReadme.Target.Id)
+ .ToArray());
+ }
+
// git log --graph --oneline --name-status --decorate
//
// * 4c062a6 (HEAD, master) directory was added
diff --git a/LibGit2Sharp.Tests/TreeDefinitionFixture.cs b/LibGit2Sharp.Tests/TreeDefinitionFixture.cs
index d4fee346a..b43e6131d 100644
--- a/LibGit2Sharp.Tests/TreeDefinitionFixture.cs
+++ b/LibGit2Sharp.Tests/TreeDefinitionFixture.cs
@@ -91,9 +91,13 @@ private static Mode ToMode(string expectedAttributes)
[Theory]
[InlineData("README", "README_TOO")]
[InlineData("README", "1/README")]
+ [InlineData("README", "1/2/README")]
[InlineData("1/branch_file.txt", "1/another_one.txt")]
[InlineData("1/branch_file.txt", "another_one.txt")]
[InlineData("1/branch_file.txt", "1/2/another_one.txt")]
+ [InlineData("1/branch_file.txt", "1/2/3/another_one.txt")]
+ [InlineData("1", "2")]
+ [InlineData("1", "2/3")]
public void CanAddAnExistingTreeEntryDefinition(string sourcePath, string targetPath)
{
using (var repo = new Repository(BareTestRepoPath))
@@ -132,6 +136,58 @@ public void CanAddAnExistingGitLinkTreeEntryDefinition()
}
}
+ [Theory]
+ [InlineData("README", "README_TOO")]
+ [InlineData("README", "1/README")]
+ [InlineData("README", "1/2/README")]
+ [InlineData("1/branch_file.txt", "1/another_one.txt")]
+ [InlineData("1/branch_file.txt", "another_one.txt")]
+ [InlineData("1/branch_file.txt", "1/2/another_one.txt")]
+ [InlineData("1/branch_file.txt", "1/2/3/another_one.txt")]
+ [InlineData("1", "2")]
+ [InlineData("1", "2/3")]
+ public void CanAddAnExistingTreeEntry(string sourcePath, string targetPath)
+ {
+ using (var repo = new Repository(BareTestRepoPath))
+ {
+ var tree = repo.Head.Tip.Tree;
+ var td = TreeDefinition.From(tree);
+ Assert.Null(td[targetPath]);
+
+ var te = tree[sourcePath];
+ td.Add(targetPath, te);
+
+ var fetched = td[targetPath];
+ Assert.NotNull(fetched);
+
+ Assert.Equal(te.Target.Id, fetched.TargetId);
+ }
+ }
+
+ [Theory]
+ [InlineData("sm_from_td")]
+ [InlineData("1/sm_from_td")]
+ [InlineData("1/2/sm_from_td")]
+ public void CanAddAnExistingGitLinkTreeEntry(string targetPath)
+ {
+ const string sourcePath = "sm_unchanged";
+
+ using (var repo = new Repository(SubmoduleTestRepoWorkingDirPath))
+ {
+ var tree = repo.Head.Tip.Tree;
+ var td = TreeDefinition.From(tree);
+ Assert.Null(td[targetPath]);
+
+ var te = tree[sourcePath];
+ td.Add(targetPath, te);
+
+ var fetched = td[targetPath];
+ Assert.NotNull(fetched);
+
+ Assert.Equal(te.Target.Id, fetched.TargetId);
+ }
+ }
+
[Theory]
[InlineData("a8233120f6ad708f843d861ce2b7228ec4e3dec6", "README_TOO")]
[InlineData("a8233120f6ad708f843d861ce2b7228ec4e3dec6", "1/README")]
diff --git a/LibGit2Sharp/TreeDefinition.cs b/LibGit2Sharp/TreeDefinition.cs
index bd29a20ee..63bbb0caf 100644
--- a/LibGit2Sharp/TreeDefinition.cs
+++ b/LibGit2Sharp/TreeDefinition.cs
@@ -29,7 +29,7 @@ public static TreeDefinition From(Tree tree)
foreach (TreeEntry treeEntry in tree)
{
- td.AddEntry(treeEntry.Name, TreeEntryDefinition.From(treeEntry));
+ td.Add(treeEntry.Name, treeEntry);
}
return td;
@@ -137,6 +137,21 @@ public virtual TreeDefinition Add(string targetTreeEntryPath, TreeEntryDefinitio
return this;
}
+ ///
+ /// Adds or replaces a , built from the provided , at the specified location.
+ ///
+ /// The path within this .
+ /// The to be stored at the described location.
+ /// The current .
+ public virtual TreeDefinition Add(string targetTreeEntryPath, TreeEntry treeEntry)
+ {
+ Ensure.ArgumentNotNull(treeEntry, "treeEntry");
+
+ TreeEntryDefinition ted = TreeEntryDefinition.From(treeEntry);
+
+ return Add(targetTreeEntryPath, ted);
+ }
+
///
/// Adds or replaces a , dynamically built from the provided , at the specified location.
///