diff --git a/LibGit2Sharp.Tests/ObjectDatabaseFixture.cs b/LibGit2Sharp.Tests/ObjectDatabaseFixture.cs index 767732487..34d3eb77c 100644 --- a/LibGit2Sharp.Tests/ObjectDatabaseFixture.cs +++ b/LibGit2Sharp.Tests/ObjectDatabaseFixture.cs @@ -121,6 +121,31 @@ public void CanCreateABlobFromAStream(string expectedSha, string hintPath) } } + [Fact] + public void CanWriteABlobFromAByteArray() + { + var ba = Encoding.ASCII.GetBytes("libgit2\r\n"); + + using (var repo = new Repository(InitNewRepository())) + { + var id = repo.ObjectDatabase.Write(ba); + Assert.Equal(new ObjectId("99115ea359379a218c47cffc83cd0af8c91c4061"), id); + } + } + + [Fact] + public void CanWriteABlobFromAStream() + { + var ba = Encoding.ASCII.GetBytes("libgit2\r\n"); + + using (var stream = new MemoryStream(ba)) + using (var repo = new Repository(InitNewRepository())) + { + var id = repo.ObjectDatabase.Write(stream, stream.Length); + Assert.Equal(new ObjectId("99115ea359379a218c47cffc83cd0af8c91c4061"), id); + } + } + Stream PrepareMemoryStream(int contentSize) { var sb = new StringBuilder(); diff --git a/LibGit2Sharp/ObjectDatabase.cs b/LibGit2Sharp/ObjectDatabase.cs index 379d3e048..d0f877def 100644 --- a/LibGit2Sharp/ObjectDatabase.cs +++ b/LibGit2Sharp/ObjectDatabase.cs @@ -178,7 +178,7 @@ public int Provider(IntPtr content, int max_length, IntPtr data) } /// - /// Write an object to the object database + /// Writes an object to the object database. /// /// The contents of the object /// The type of object to write @@ -187,6 +187,45 @@ public virtual ObjectId Write(byte[] data) where T : GitObject return Proxy.git_odb_write(handle, data, GitObject.TypeToKindMap[typeof(T)]); } + /// + /// Writes an object to the object database. + /// + /// The contents of the object + /// The number of bytes to consume from the stream + /// The type of object to write + public virtual ObjectId Write(Stream stream, long numberOfBytesToConsume) where T : GitObject + { + Ensure.ArgumentNotNull(stream, "stream"); + + if (!stream.CanRead) + { + throw new ArgumentException("The stream cannot be read from.", "stream"); + } + + using (var odbStream = Proxy.git_odb_open_wstream(handle, numberOfBytesToConsume, GitObjectType.Blob)) + { + var buffer = new byte[4 * 1024]; + long totalRead = 0; + + while (totalRead < numberOfBytesToConsume) + { + long left = numberOfBytesToConsume - totalRead; + int toRead = left < buffer.Length ? (int)left : buffer.Length; + var read = stream.Read(buffer, 0, toRead); + + if (read == 0) + { + throw new EndOfStreamException("The stream ended unexpectedly"); + } + + Proxy.git_odb_stream_write(odbStream, buffer, read); + totalRead += read; + } + + return Proxy.git_odb_stream_finalize_write(odbStream); + } + } + /// /// Inserts a into the object database, created from the content of a stream. /// Optionally, git filters will be applied to the content before storing it. @@ -294,37 +333,8 @@ private unsafe Blob CreateBlob(Stream stream, string hintpath, long? numberOfByt /// The created . public virtual Blob CreateBlob(Stream stream, long numberOfBytesToConsume) { - Ensure.ArgumentNotNull(stream, "stream"); - - if (!stream.CanRead) - { - throw new ArgumentException("The stream cannot be read from.", "stream"); - } - - using (var odbStream = Proxy.git_odb_open_wstream(handle, numberOfBytesToConsume, GitObjectType.Blob)) - { - var buffer = new byte[4 * 1024]; - long totalRead = 0; - - while (totalRead < numberOfBytesToConsume) - { - long left = numberOfBytesToConsume - totalRead; - int toRead = left < buffer.Length ? (int)left : buffer.Length; - var read = stream.Read(buffer, 0, toRead); - - if (read == 0) - { - throw new EndOfStreamException("The stream ended unexpectedly"); - } - - Proxy.git_odb_stream_write(odbStream, buffer, read); - totalRead += read; - } - - var id = Proxy.git_odb_stream_finalize_write(odbStream); - - return repo.Lookup(id); - } + var id = Write(stream, numberOfBytesToConsume); + return repo.Lookup(id); } ///