diff options
author | nulltoken <emeric.fermas@gmail.com> | 2012-04-16 23:56:18 +0400 |
---|---|---|
committer | nulltoken <emeric.fermas@gmail.com> | 2012-04-28 05:32:17 +0400 |
commit | 660d27aff85f01c608dbe1b014c3d1bc9faa3939 (patch) | |
tree | ed6095b6b24b491ef65dc47923e3747944cb535f | |
parent | 77fd1e48d22b99dbcac789ae014edaf9328776c2 (diff) |
Add Repository.ObjectDatabase.CreateTree()
-rw-r--r-- | LibGit2Sharp.Tests/ObjectDatabaseFixture.cs | 59 | ||||
-rw-r--r-- | LibGit2Sharp/Core/Handles/TreeBuilderSafeHandle.cs | 11 | ||||
-rw-r--r-- | LibGit2Sharp/Core/NativeMethods.cs | 17 | ||||
-rw-r--r-- | LibGit2Sharp/LibGit2Sharp.csproj | 1 | ||||
-rw-r--r-- | LibGit2Sharp/ObjectDatabase.cs | 10 | ||||
-rw-r--r-- | LibGit2Sharp/TreeDefinition.cs | 61 |
6 files changed, 159 insertions, 0 deletions
diff --git a/LibGit2Sharp.Tests/ObjectDatabaseFixture.cs b/LibGit2Sharp.Tests/ObjectDatabaseFixture.cs index bc613302..fbece8f0 100644 --- a/LibGit2Sharp.Tests/ObjectDatabaseFixture.cs +++ b/LibGit2Sharp.Tests/ObjectDatabaseFixture.cs @@ -45,5 +45,64 @@ namespace LibGit2Sharp.Tests Assert.Equal(blob, fetchedBlob); } } + + [Theory] + [InlineData("README")] + [InlineData("README AS WELL")] + [InlineData("2/README AS WELL")] + [InlineData("1/README AS WELL")] + [InlineData("1")] + public void CanCreateATreeByAlteringAnExistingOne(string targetPath) + { + TemporaryCloneOfTestRepo scd = BuildTemporaryCloneOfTestRepo(); + + using (var repo = new Repository(scd.RepositoryPath)) + { + var blob = repo.Lookup<Blob>(new ObjectId("a8233120f6ad708f843d861ce2b7228ec4e3dec6")); + + TreeDefinition td = TreeDefinition.From(repo.Head.Tip.Tree) + .Add(targetPath, blob, Mode.NonExecutableFile); + + Tree tree = repo.ObjectDatabase.CreateTree(td); + Assert.NotNull(tree); + } + } + + [Fact] + public void CanCreateAnEmptyTree() + { + TemporaryCloneOfTestRepo scd = BuildTemporaryCloneOfTestRepo(); + + using (var repo = new Repository(scd.RepositoryPath)) + { + var td = new TreeDefinition(); + + Tree tree = repo.ObjectDatabase.CreateTree(td); + Assert.NotNull(tree); + Assert.Equal("4b825dc642cb6eb9a060e54bf8d69288fbee4904", tree.Sha); + } + } + + [Fact] + public void CanReplaceAnExistingTreeWithAnotherPersitedTree() + { + TemporaryCloneOfTestRepo scd = BuildTemporaryCloneOfTestRepo(); + + using (var repo = new Repository(scd.RepositoryPath)) + { + TreeDefinition td = TreeDefinition.From(repo.Head.Tip.Tree); + Assert.Equal(GitObjectType.Tree, td["1"].Type); + + TreeDefinition newTd = new TreeDefinition() + .Add("new/one", repo.Lookup<Blob>("a823312"), Mode.NonExecutableFile) + .Add("new/two", repo.Lookup<Blob>("a71586c"), Mode.NonExecutableFile) + .Add("new/tree", repo.Lookup<Tree>("7f76480")); + + repo.ObjectDatabase.CreateTree(newTd); + + td.Add("1", newTd["new"]); + Assert.Equal(GitObjectType.Tree, td["1/tree"].Type); + } + } } } diff --git a/LibGit2Sharp/Core/Handles/TreeBuilderSafeHandle.cs b/LibGit2Sharp/Core/Handles/TreeBuilderSafeHandle.cs new file mode 100644 index 00000000..5ba90a44 --- /dev/null +++ b/LibGit2Sharp/Core/Handles/TreeBuilderSafeHandle.cs @@ -0,0 +1,11 @@ +namespace LibGit2Sharp.Core.Handles +{ + internal class TreeBuilderSafeHandle : SafeHandleBase + { + protected override bool ReleaseHandle() + { + NativeMethods.git_treebuilder_free(handle); + return true; + } + } +} diff --git a/LibGit2Sharp/Core/NativeMethods.cs b/LibGit2Sharp/Core/NativeMethods.cs index d739ea64..864b07d3 100644 --- a/LibGit2Sharp/Core/NativeMethods.cs +++ b/LibGit2Sharp/Core/NativeMethods.cs @@ -507,5 +507,22 @@ namespace LibGit2Sharp.Core [DllImport(libgit2)] public static extern int git_tree_get_subtree(out GitObjectSafeHandle tree, GitObjectSafeHandle root, [MarshalAs(UnmanagedType.CustomMarshaler, MarshalTypeRef = typeof(FilePathMarshaler))] FilePath treeentry_path); + + [DllImport(libgit2)] + public static extern int git_treebuilder_create(out TreeBuilderSafeHandle builder, IntPtr src); + + [DllImport(libgit2)] + public static extern int git_treebuilder_insert( + IntPtr entry_out, + TreeBuilderSafeHandle builder, + [MarshalAs(UnmanagedType.CustomMarshaler, MarshalTypeRef = typeof(Utf8Marshaler))] string treeentry_name, + ref GitOid id, + uint attributes); + + [DllImport(libgit2)] + public static extern int git_treebuilder_write(out GitOid oid, RepositorySafeHandle repo, TreeBuilderSafeHandle bld); + + [DllImport(libgit2)] + public static extern int git_treebuilder_free(IntPtr bld); } } diff --git a/LibGit2Sharp/LibGit2Sharp.csproj b/LibGit2Sharp/LibGit2Sharp.csproj index 4e6451e2..6fb0edf9 100644 --- a/LibGit2Sharp/LibGit2Sharp.csproj +++ b/LibGit2Sharp/LibGit2Sharp.csproj @@ -65,6 +65,7 @@ <Compile Include="Core\Handles\IndexEntrySafeHandle.cs" /> <Compile Include="Core\Handles\NotOwnedSafeHandleBase.cs" /> <Compile Include="Core\Handles\OidSafeHandle.cs" /> + <Compile Include="Core\Handles\TreeBuilderSafeHandle.cs" /> <Compile Include="Core\ReferenceExtensions.cs" /> <Compile Include="Core\Handles\ReferenceSafeHandle.cs" /> <Compile Include="Core\Handles\SignatureSafeHandle.cs" /> diff --git a/LibGit2Sharp/ObjectDatabase.cs b/LibGit2Sharp/ObjectDatabase.cs index 293cf8de..1a430440 100644 --- a/LibGit2Sharp/ObjectDatabase.cs +++ b/LibGit2Sharp/ObjectDatabase.cs @@ -49,5 +49,15 @@ namespace LibGit2Sharp Ensure.Success(NativeMethods.git_blob_create_fromfile(ref oid, repo.Handle, path)); return repo.Lookup<Blob>(new ObjectId(oid)); } + + /// <summary> + /// Inserts a <see cref = "Tree"/> into the object database, created from a <see cref = "TreeDefinition"/>. + /// </summary> + /// <param name = "treeDefinition">The <see cref = "TreeDefinition"/>.</param> + /// <returns>The created <see cref = "Tree"/>.</returns> + public Tree CreateTree(TreeDefinition treeDefinition) + { + return treeDefinition.Build(repo); + } } } diff --git a/LibGit2Sharp/TreeDefinition.cs b/LibGit2Sharp/TreeDefinition.cs index dddccd25..8ebe90e7 100644 --- a/LibGit2Sharp/TreeDefinition.cs +++ b/LibGit2Sharp/TreeDefinition.cs @@ -3,6 +3,7 @@ using System.Collections.Generic; using System.IO; using LibGit2Sharp.Core; using LibGit2Sharp.Core.Compat; +using LibGit2Sharp.Core.Handles; namespace LibGit2Sharp { @@ -162,6 +163,36 @@ namespace LibGit2Sharp return td; } + internal Tree Build(Repository repository) + { + WrapAllTreeDefinitions(repository); + + using (var builder = new TreeBuilder()) + { + foreach (KeyValuePair<string, TreeEntryDefinition> kvp in entries) + { + string name = kvp.Key; + TreeEntryDefinition ted = kvp.Value; + + builder.Insert(name, ted); + } + + ObjectId treeId = builder.Write(repository); + return repository.Lookup<Tree>(treeId); + } + } + + private void WrapAllTreeDefinitions(Repository repository) + { + foreach (KeyValuePair<string, TreeDefinition> pair in unwrappedTrees) + { + Tree tree = pair.Value.Build(repository); + entries[pair.Key] = TreeEntryDefinition.From(tree); + } + + unwrappedTrees.Clear(); + } + private void WrapTree(string entryName, TreeEntryDefinition treeEntryDefinition) { entries[entryName] = treeEntryDefinition; @@ -203,5 +234,35 @@ namespace LibGit2Sharp return new Tuple<string, string>(segments[0], segments.Length == 2 ? segments[1] : null); } + + private class TreeBuilder : IDisposable + { + private readonly TreeBuilderSafeHandle handle; + + public TreeBuilder() + { + Ensure.Success(NativeMethods.git_treebuilder_create(out handle, IntPtr.Zero)); + } + + public void Insert(string name, TreeEntryDefinition treeEntryDefinition) + { + GitOid oid = treeEntryDefinition.TargetId.Oid; + + Ensure.Success(NativeMethods.git_treebuilder_insert(IntPtr.Zero, handle, name, ref oid, (uint)treeEntryDefinition.Mode)); + } + + public ObjectId Write(Repository repo) + { + GitOid oid; + Ensure.Success(NativeMethods.git_treebuilder_write(out oid, repo.Handle, handle)); + + return new ObjectId(oid); + } + + public void Dispose() + { + handle.SafeDispose(); + } + } } } |