int StreamCreateCallback(out IntPtr git_writestream_out, GitFilter self, IntPtr payload, IntPtr filterSourcePtr, IntPtr git_writestream_next) { int result = 0; try { Ensure.ArgumentNotZeroIntPtr(filterSourcePtr, "filterSourcePtr"); Ensure.ArgumentNotZeroIntPtr(git_writestream_next, "git_writestream_next"); thisStream = new GitWriteStream(); thisStream.close = StreamCloseCallback; thisStream.write = StreamWriteCallback; thisStream.free = StreamFreeCallback; thisPtr = Marshal.AllocHGlobal(Marshal.SizeOf(thisStream)); Marshal.StructureToPtr(thisStream, thisPtr, false); nextPtr = git_writestream_next; nextStream = new GitWriteStream(); Marshal.PtrToStructure(nextPtr, nextStream); filterSource = FilterSource.FromNativePtr(filterSourcePtr); output = new WriteStream(nextStream, nextPtr); Create(filterSource.Path, filterSource.Root, filterSource.SourceMode); } catch (Exception exception) { // unexpected failures means memory clean up required if (thisPtr != IntPtr.Zero) { Marshal.FreeHGlobal(thisPtr); thisPtr = IntPtr.Zero; } Log.Write(LogLevel.Error, "Filter.StreamCreateCallback exception"); Log.Write(LogLevel.Error, exception.ToString()); Proxy.giterr_set_str(GitErrorCategory.Filter, exception); result = (int)GitErrorCode.Error; } git_writestream_out = thisPtr; return(result); }
private unsafe Blob CreateBlob(Stream stream, string hintpath, long?numberOfBytesToConsume) { Ensure.ArgumentNotNull(stream, "stream"); // there's no need to buffer the file for filtering, so simply use a stream if (hintpath == null && numberOfBytesToConsume.HasValue) { return(CreateBlob(stream, numberOfBytesToConsume.Value)); } if (!stream.CanRead) { throw new ArgumentException("The stream cannot be read from.", "stream"); } IntPtr writestream_ptr = Proxy.git_blob_create_fromstream(repo.Handle, hintpath); GitWriteStream writestream = (GitWriteStream)Marshal.PtrToStructure(writestream_ptr, typeof(GitWriteStream)); try { var buffer = new byte[4 * 1024]; long totalRead = 0; int read = 0; while (true) { int toRead = numberOfBytesToConsume.HasValue ? (int)Math.Min(numberOfBytesToConsume.Value - totalRead, (long)buffer.Length) : buffer.Length; if (toRead > 0) { read = (toRead > 0) ? stream.Read(buffer, 0, toRead) : 0; } if (read == 0) { break; } fixed(byte *buffer_ptr = buffer) { writestream.write(writestream_ptr, (IntPtr)buffer_ptr, (UIntPtr)read); } totalRead += read; } if (numberOfBytesToConsume.HasValue && totalRead < numberOfBytesToConsume.Value) { throw new EndOfStreamException("The stream ended unexpectedly"); } } catch (Exception e) { writestream.free(writestream_ptr); throw e; } ObjectId id = Proxy.git_blob_create_fromstream_commit(writestream_ptr); return(repo.Lookup <Blob>(id)); }