Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with HTTPS or Subversion.

Download ZIP
Browse files

Add Repository.ObjectDatabase.CreateTree()

  • Loading branch information...
commit 660d27aff85f01c608dbe1b014c3d1bc9faa3939 1 parent 77fd1e4
@nulltoken authored
View
59 LibGit2Sharp.Tests/ObjectDatabaseFixture.cs
@@ -45,5 +45,64 @@ public void CanCreateABlobFromAFileInTheWorkingDirectory()
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);
+ }
+ }
}
}
View
11 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;
+ }
+ }
+}
View
17 LibGit2Sharp/Core/NativeMethods.cs
@@ -507,5 +507,22 @@ public static bool RepositoryStateChecker(RepositorySafeHandle repositoryPtr, Fu
[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);
}
}
View
1  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" />
View
10 LibGit2Sharp/ObjectDatabase.cs
@@ -49,5 +49,15 @@ public Blob CreateBlob(string path)
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);
+ }
}
}
View
61 LibGit2Sharp/TreeDefinition.cs
@@ -3,6 +3,7 @@
using System.IO;
using LibGit2Sharp.Core;
using LibGit2Sharp.Core.Compat;
+using LibGit2Sharp.Core.Handles;
namespace LibGit2Sharp
{
@@ -162,6 +163,36 @@ private TreeDefinition RetrieveOrBuildTreeDefinition(string treeName, bool shoul
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 @@ private void WrapTree(string entryName, TreeEntryDefinition treeEntryDefinition)
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();
+ }
+ }
}
}
Please sign in to comment.
Something went wrong with that request. Please try again.