public Stream GetObjectByPath(GitObjectId sha, string objectType, bool seekable)
        {
            sha.CreateUnicodeString(0, 1, this.objectPathBuffer.AsSpan(this.objectDirLength + 2, 4));
            sha.CreateUnicodeString(1, 19, this.objectPathBuffer.AsSpan(this.objectDirLength + 2 + 4 + 2));

            if (!FileHelpers.TryOpen(this.objectPathBuffer, out Stream compressedFile))
            {
                return(null);
            }

            var file = GitObjectStream.Create(compressedFile, -1);

            file.ReadObjectTypeAndLength(objectType);

            if (string.CompareOrdinal(file.ObjectType, objectType) != 0)
            {
                throw new GitException();
            }

            if (seekable)
            {
                return(new GitPackMemoryCacheStream(file));
            }
            else
            {
                return(file);
            }
        }
        public Stream GetObjectByPath(string path, string objectType)
        {
            string fullPath = Path.Combine(this.ObjectDirectory, path);

            if (!FileHelpers.TryOpen(fullPath, out Stream compressedFile))
            {
                return(null);
            }

            var file = GitObjectStream.Create(compressedFile, -1);

            file.ReadObjectTypeAndLength();

            if (string.CompareOrdinal(file.ObjectType, objectType) != 0)
            {
                throw new GitException();
            }

            return(file);
        }
Пример #3
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));
        }