private static bool TryReadAuthor(ReadOnlySpan <byte> line, out GitSignature signature)
        {
            signature = default;

            if (!line.Slice(0, AuthorStart.Length).SequenceEqual(AuthorStart))
            {
                return(false);
            }

            line = line.Slice(AuthorStart.Length);

            int emailStart = line.IndexOf((byte)'<');
            int emailEnd   = line.IndexOf((byte)'>');
            var lineEnd    = line.IndexOf((byte)'\n');

            var name  = line.Slice(0, emailStart - 1);
            var email = line.Slice(emailStart + 1, emailEnd - emailStart - 1);
            var time  = line.Slice(emailEnd + 2, lineEnd - emailEnd - 2);

            signature.Name  = GitRepository.GetString(name);
            signature.Email = GitRepository.GetString(email);

            var offsetStart = time.IndexOf((byte)' ');
            var ticks       = long.Parse(GitRepository.GetString(time.Slice(0, offsetStart)));

            signature.Date = DateTimeOffset.FromUnixTimeSeconds(ticks);

            return(true);
        }
        public static GitCommit Read(ReadOnlySpan <byte> commit, GitObjectId sha, bool readAuthor = false)
        {
            var buffer = commit;

            var tree = ReadTree(buffer.Slice(0, TreeLineLength));

            buffer = buffer.Slice(TreeLineLength);

            GitObjectId?       firstParent = null, secondParent = null;
            List <GitObjectId>?additionalParents = null;
            List <GitObjectId> parents           = new List <GitObjectId>();

            while (TryReadParent(buffer, out GitObjectId parent))
            {
                if (!firstParent.HasValue)
                {
                    firstParent = parent;
                }
                else if (!secondParent.HasValue)
                {
                    secondParent = parent;
                }
                else
                {
                    additionalParents ??= new List <GitObjectId>();
                    additionalParents.Add(parent);
                }

                buffer = buffer.Slice(ParentLineLength);
            }

            GitSignature signature = default;

            if (readAuthor && !TryReadAuthor(buffer, out signature))
            {
                throw new GitException();
            }

            return(new GitCommit()
            {
                Sha = sha,
                FirstParent = firstParent,
                SecondParent = secondParent,
                AdditionalParents = additionalParents,
                Tree = tree,
                Author = readAuthor ? signature : (GitSignature?)null,
            });
        }