public static async Task <string> FindNode(Stream stream, ReadOnlyMemory <byte> name, CancellationToken cancellationToken) { var reader = PipeReader.Create(stream); byte[] hash = null; while (true) { var result = await reader.ReadAsync(cancellationToken).ConfigureAwait(false); var buffer = result.Buffer; var position = TryFindNode(buffer, name.Span, result.IsCompleted, out hash); if (hash != null) { break; } if (result.IsCompleted) { break; } reader.AdvanceTo(position, buffer.End); } reader.Complete(); return(CharUtils.ToHex(hash)); }
public int?GetOffset(byte[] objectId) { if (this.offsets.TryGetValue(CharUtils.ToHex(objectId), out int cachedOffset)) { return(cachedOffset); } var indexReader = this.indexReader.Value; var offset = indexReader.GetOffset(objectId); if (offset != null) { this.offsets.TryAdd(CharUtils.ToHex(objectId), offset.Value); } return(offset); }
public static string FindNode(Stream stream, ReadOnlySpan <byte> name) { byte[] buffer = ArrayPool <byte> .Shared.Rent((int)stream.Length); Span <byte> contents = new Span <byte>(buffer, 0, (int)stream.Length); stream.ReadAll(contents); string value = null; while (contents.Length > 0) { // Format: [mode] [file/ folder name]\0[SHA - 1 of referencing blob or tree] // Mode is either 6-bytes long (directory) or 7-bytes long (file). // If the entry is a file, the first byte is '1' var fileNameEnds = contents.IndexOf((byte)0); bool isFile = contents[0] == (byte)'1'; var modeLength = isFile ? 7 : 6; var currentName = contents.Slice(modeLength, fileNameEnds - modeLength); if (currentName.SequenceEqual(name)) { value = CharUtils.ToHex(contents.Slice(fileNameEnds + 1, 20)); break; } else { contents = contents.Slice(fileNameEnds + 1 + 20); } } ArrayPool <byte> .Shared.Return(buffer); return(value); }
public static Stream GetObject(GitPack pack, Stream stream, int offset, string objectType, GitPackObjectType packObjectType) { if (pack == null) { throw new ArgumentNullException(nameof(pack)); } if (stream == null) { throw new ArgumentNullException(nameof(stream)); } // Read the signature stream.Seek(0, SeekOrigin.Begin); Span <byte> buffer = stackalloc byte[4]; stream.ReadAll(buffer); Debug.Assert(buffer.SequenceEqual(Signature)); stream.ReadAll(buffer); var versionNumber = BinaryPrimitives.ReadInt32BigEndian(buffer); Debug.Assert(versionNumber == 2); stream.ReadAll(buffer); var numberOfObjects = BinaryPrimitives.ReadInt32BigEndian(buffer); stream.Seek(offset, SeekOrigin.Begin); var(type, decompressedSize) = ReadObjectHeader(stream); if (type == GitPackObjectType.OBJ_OFS_DELTA) { var baseObjectRelativeOffset = ReadVariableLengthInteger(stream); var baseObjectOffset = (int)(offset - baseObjectRelativeOffset); var deltaStream = GitObjectStream.Create(stream, decompressedSize); int baseObjectlength = ReadMbsInt(deltaStream); int targetLength = ReadMbsInt(deltaStream); var baseObjectStream = pack.GetObject(baseObjectOffset, objectType); return(new GitPackDeltafiedStream(baseObjectStream, deltaStream, targetLength)); } else if (type == GitPackObjectType.OBJ_REF_DELTA) { Span <byte> baseObjectId = stackalloc byte[20]; stream.ReadAll(baseObjectId); Stream baseObject = pack.Repository.GetObjectBySha(CharUtils.ToHex(baseObjectId), objectType); throw new NotImplementedException(); } // Tips for handling deltas: https://github.com/choffmeister/gitnet/blob/4d907623d5ce2d79a8875aee82e718c12a8aad0b/src/GitNet/GitPack.cs if (type != packObjectType) { throw new GitException(); } return(GitObjectStream.Create(stream, decompressedSize)); }