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);
        }
예제 #3
0
        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));
        }