Ejemplo n.º 1
0
        public static Stream GetObject(GitPack pack, Stream stream, long offset, string objectType, GitPackObjectType packObjectType)
        {
            if (pack == null)
            {
                throw new ArgumentNullException(nameof(pack));
            }

            if (stream == null)
            {
                throw new ArgumentNullException(nameof(stream));
            }

            // Read the signature
#if DEBUG
            stream.Seek(0, SeekOrigin.Begin);
            Span <byte> buffer = stackalloc byte[12];
            stream.ReadAll(buffer);

            Debug.Assert(buffer.Slice(0, 4).SequenceEqual(Signature));

            var versionNumber = BinaryPrimitives.ReadInt32BigEndian(buffer.Slice(4, 4));
            Debug.Assert(versionNumber == 2);

            var numberOfObjects = BinaryPrimitives.ReadInt32BigEndian(buffer.Slice(8, 4));
#endif

            stream.Seek(offset, SeekOrigin.Begin);

            var(type, decompressedSize) = ReadObjectHeader(stream);

            if (type == GitPackObjectType.OBJ_OFS_DELTA)
            {
                var baseObjectRelativeOffset = ReadVariableLengthInteger(stream);
                var baseObjectOffset         = (long)(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(GitObjectId.Parse(baseObjectId), objectType, seekable: true);

                var deltaStream = GitObjectStream.Create(stream, decompressedSize);

                int baseObjectlength = ReadMbsInt(deltaStream);
                int targetLength     = ReadMbsInt(deltaStream);

                return(new GitPackDeltafiedStream(baseObject, deltaStream, targetLength));
            }

            // 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));
        }
Ejemplo n.º 2
0
        public static Stream GetObject(GitPack pack, Stream stream, long offset, string objectType, GitPackObjectType packObjectType)
        {
            if (pack is null)
            {
                throw new ArgumentNullException(nameof(pack));
            }

            if (stream is null)
            {
                throw new ArgumentNullException(nameof(stream));
            }

            // Read the signature
#if DEBUG
            stream.Seek(0, SeekOrigin.Begin);
            Span <byte> buffer = stackalloc byte[12];
            stream.ReadAll(buffer);

            Debug.Assert(buffer.Slice(0, 4).SequenceEqual(Signature));

            var versionNumber = BinaryPrimitives.ReadInt32BigEndian(buffer.Slice(4, 4));
            Debug.Assert(versionNumber == 2);

            var numberOfObjects = BinaryPrimitives.ReadInt32BigEndian(buffer.Slice(8, 4));
#endif

            stream.Seek(offset, SeekOrigin.Begin);

            var(type, decompressedSize) = ReadObjectHeader(stream);

            if (type == GitPackObjectType.OBJ_OFS_DELTA)
            {
                var  baseObjectRelativeOffset = ReadVariableLengthInteger(stream);
                long baseObjectOffset         = offset - baseObjectRelativeOffset;

                var deltaStream      = new ZLibStream(stream, decompressedSize);
                var baseObjectStream = pack.GetObject(baseObjectOffset, objectType);

                return(new GitPackDeltafiedStream(baseObjectStream, deltaStream));
            }
            else if (type == GitPackObjectType.OBJ_REF_DELTA)
            {
                Span <byte> baseObjectId = stackalloc byte[20];
                stream.ReadAll(baseObjectId);

                Stream baseObject         = pack.GetObjectFromRepository(GitObjectId.Parse(baseObjectId), objectType) !;
                var    seekableBaseObject = new GitPackMemoryCacheStream(baseObject);

                var deltaStream = new ZLibStream(stream, decompressedSize);

                return(new GitPackDeltafiedStream(seekableBaseObject, deltaStream));
            }

            // Tips for handling deltas: https://github.com/choffmeister/gitnet/blob/4d907623d5ce2d79a8875aee82e718c12a8aad0b/src/GitNet/GitPack.cs
            if (type != packObjectType)
            {
                throw new GitException($"An object of type {objectType} could not be located at offset {offset}.")
                      {
                          ErrorCode = GitException.ErrorCodes.ObjectNotFound
                      };
            }

            return(new ZLibStream(stream, decompressedSize));
        }