using System; using System.Collections.Generic; using System.Globalization; using System.IO; using System.Linq; using System.Runtime.InteropServices; using LibGit2Sharp.Core; using LibGit2Sharp.Core.Handles; namespace LibGit2Sharp { /// /// Provides methods to directly work against the Git object database /// without involving the index nor the working directory. /// public class ObjectDatabase { private readonly Repository repo; private readonly ObjectDatabaseSafeHandle handle; /// /// Needed for mocking purposes. /// protected ObjectDatabase() { } internal ObjectDatabase(Repository repo) { this.repo = repo; handle = Proxy.git_repository_odb(repo.Handle); repo.RegisterForCleanup(handle); } /// /// Determines if the given object can be found in the object database. /// /// Identifier of the object being searched for. /// True if the object has been found; false otherwise. public virtual bool Contains(ObjectId objectId) { Ensure.ArgumentNotNull(objectId, "objectId"); return Proxy.git_odb_exists(handle, objectId); } /// /// Inserts a into the object database, created from the content of a file. /// /// Path to the file to create the blob from. A relative path is allowed to /// be passed if the is a standard, non-bare, repository. The path /// will then be considered as a path relative to the root of the working directory. /// The created . public virtual Blob CreateBlob(string path) { Ensure.ArgumentNotNullOrEmptyString(path, "path"); if (repo.Info.IsBare && !Path.IsPathRooted(path)) { throw new InvalidOperationException( string.Format(CultureInfo.InvariantCulture, "Cannot create a blob in a bare repository from a relative path ('{0}').", path)); } ObjectId id = Path.IsPathRooted(path) ? Proxy.git_blob_create_fromdisk(repo.Handle, path) : Proxy.git_blob_create_fromfile(repo.Handle, path); return repo.Lookup(id); } /// /// Adds the provided backend to the object database with the specified priority. /// /// The backend to add /// The priority at which libgit2 should consult this backend (higher values are consulted first) public virtual void AddBackend(OdbBackend backend, int priority) { Ensure.ArgumentNotNull(backend, "backend"); Ensure.ArgumentConformsTo(priority, s => s > 0, "priority"); Proxy.git_odb_add_backend(this.handle, backend.GitOdbBackendPointer, priority); } private class Processor { private readonly BinaryReader _reader; public Processor(BinaryReader reader) { _reader = reader; } public int Provider(IntPtr content, int max_length, IntPtr data) { var local = new byte[max_length]; int numberOfReadBytes = _reader.Read(local, 0, max_length); Marshal.Copy(local, 0, content, numberOfReadBytes); return numberOfReadBytes; } } /// /// Inserts a into the object database, created from the content of a data provider. /// /// The reader that will provide the content of the blob to be created. /// The hintpath is used to determine what git filters should be applied to the object before it can be placed to the object database. /// The created . public virtual Blob CreateBlob(BinaryReader reader, string hintpath = null) { Ensure.ArgumentNotNull(reader, "reader"); var proc = new Processor(reader); ObjectId id = Proxy.git_blob_create_fromchunks(repo.Handle, hintpath, proc.Provider); return repo.Lookup(id); } /// /// Inserts a into the object database, created from a . /// /// The . /// The created . public virtual Tree CreateTree(TreeDefinition treeDefinition) { Ensure.ArgumentNotNull(treeDefinition, "treeDefinition"); return treeDefinition.Build(repo); } /// /// Inserts a into the object database, referencing an existing . /// /// The description of why a change was made to the repository. /// The of who made the change. /// The of who added the change to the repository. /// The of the to be created. /// The parents of the to be created. /// The created . public virtual Commit CreateCommit(string message, Signature author, Signature committer, Tree tree, IEnumerable parents) { return CreateCommit(message, author, committer, tree, parents, null); } internal Commit CreateCommit(string message, Signature author, Signature committer, Tree tree, IEnumerable parents, string referenceName) { Ensure.ArgumentNotNull(message, "message"); Ensure.ArgumentNotNull(author, "author"); Ensure.ArgumentNotNull(committer, "committer"); Ensure.ArgumentNotNull(tree, "tree"); Ensure.ArgumentNotNull(parents, "parents"); string prettifiedMessage = Proxy.git_message_prettify(message); IEnumerable parentIds = parents.Select(p => p.Id); ObjectId commitId = Proxy.git_commit_create(repo.Handle, referenceName, author, committer, prettifiedMessage, tree, parentIds); return repo.Lookup(commitId); } } }