Exemplo n.º 1
0
        private protected virtual async ValueTask ReadRefs()
        {
            string fileName = Path.Combine(GitDir, PackedRefsFile);

            if (!File.Exists(fileName))
            {
                return;
            }

            try
            {
                using var sr = FileBucket.OpenRead(fileName, false);

                var idLength = GitId.HashLength(Repository.InternalConfig.IdType) * 2;

                GitRefPeel?last = null;
                while (true)
                {
                    var(bb, eol) = await sr.ReadUntilEolFullAsync(BucketEol.LF).ConfigureAwait(false);

                    if (bb.IsEof)
                    {
                        return;
                    }

                    bb = bb.Trim(eol);
                    ParseLineToPeel(bb, ref last, idLength);
                }
            }
            catch (FileNotFoundException)
            {
                return;
            }
        }
Exemplo n.º 2
0
        private protected override async ValueTask ReadRefs()
        {
            GitRefPeel?last     = null;
            var        idLength = GitId.HashLength(Repository.InternalConfig.IdType) * 2;

            await foreach (var line in Repository.WalkPlumbingCommand("show-ref", new[] { "-d", "--head" },
                                                                      expectedResults: new int[] { 0 /* ok */, 1 /* no references found */ }).ConfigureAwait(false))
            {
                ParseLineToPeel(line.Trim(), ref last, idLength);
            }
        }
Exemplo n.º 3
0
        protected async ValueTask <GitId> GetGitIdByIndexAsync(uint i)
        {
            int hashLength = GitId.HashLength(IdType);

            byte[] oidData = new byte[hashLength];

            if (await ReadFromChunkAsync("OIDL", i * hashLength, oidData).ConfigureAwait(false) != hashLength)
            {
                throw new InvalidOperationException();
            }

            return(new GitId(IdType, oidData));
        }
Exemplo n.º 4
0
        private async ValueTask <byte[]> GetOffsetArrayAsync(uint start, uint count, byte[] oids)
        {
            if (count == 0)
            {
                return(Array.Empty <byte>());
            }

            if (_ver == 2)
            {
                int    sz   = GitId.HashLength(_idType);
                byte[] data = new byte[4 * count];

                long offset = 8 /* header */ + 256 * 4 /* fanout */
                              + sz * _fanOut ![255]    // Hashes
Exemplo n.º 5
0
        private async ValueTask <byte[]> GetOidArrayAsync(uint start, uint count)
        {
            if (count == 0)
            {
                return(Array.Empty <byte>());
            }

            if (_ver == 2)
            {
                int    sz   = GitId.HashLength(_idType);
                byte[] data = new byte[sz * count];

                long offset = 8 /* header */ + 256 * 4 /* fanout */ + sz * start;

                if (data.Length != await _fIdx !.ReadAtAsync(offset, data).ConfigureAwait(false))
                {
                    return(Array.Empty <byte>());
                }

                return(data);
            }
            else if (_ver == 1)
            {
                int    sz   = GitId.HashLength(_idType) + 4;
                byte[] data = new byte[sz * count];

                long offset = 256 * 4 /* fanout */ + sz * start;

                if (data.Length != await _fIdx !.ReadAtAsync(offset, data).ConfigureAwait(false))
                {
                    return(Array.Empty <byte>());
                }

                return(data);
            }
            else
            {
                return(Array.Empty <byte>());
            }
        }
Exemplo n.º 6
0
        private async ValueTask <GitId> GetOidAsync(int index)
        {
            int offset = OidOffset;

            if (index < offset)
            {
                return(await ParentGraph !.GetOidAsync(index).ConfigureAwait(false));
            }

            index -= offset;

            int hashLength = GitId.HashLength(IdType);

            byte[] oidData = new byte[hashLength];

            if (hashLength != await ReadFromChunkAsync("OIDL", index * hashLength, oidData).ConfigureAwait(false))
            {
                throw new InvalidOperationException();
            }

            return(new GitId(IdType, oidData));
        }
Exemplo n.º 7
0
        internal override async ValueTask <IGitCommitGraphInfo?> GetCommitInfo(GitId id)
        {
            await InitAsync().ConfigureAwait(false);

            var(success, index) = await TryFindIdAsync(id).ConfigureAwait(false);

            if (success)
            {
                int    hashLength   = GitId.HashLength(IdType);
                int    commitDataSz = hashLength + 2 * sizeof(uint) + sizeof(ulong);
                byte[] commitData   = new byte[commitDataSz];

                if (commitDataSz != await ReadFromChunkAsync("CDAT", index * commitDataSz, commitData).ConfigureAwait(false))
                {
                    return(null);
                }

                // commitData now contains the root hash, 2 parent indexes and the topological level
                uint  parent0    = NetBitConverter.ToUInt32(commitData, hashLength);
                uint  parent1    = NetBitConverter.ToUInt32(commitData, hashLength + sizeof(uint));
                ulong chainLevel = NetBitConverter.ToUInt64(commitData, hashLength + 2 * sizeof(uint));

                Task <GitId>[] parents;

                if (parent0 == 0x70000000)
                {
                    return(new GitCommitGraphInfo(Array.Empty <GitId>(), chainLevel, _haveV2 ? await ReadCommitTimeOffset(index).ConfigureAwait(false) : long.MinValue));
                }
                else if (parent1 == 0x70000000)
                {
                    parents = new[] { GetOidAsync((int)parent0).AsTask() }
                }
                ;
                else if (parent1 >= 0x80000000)
                {
                    var extraParents = new byte[sizeof(uint) * 256];
                    int len          = await ReadFromChunkAsync("EDGE", 4 *(parent1 & 0x7FFFFFFF), extraParents).ConfigureAwait(false) / sizeof(uint);

                    if (len == 0 || len >= 256)
                    {
                        return(null); // Handle as if not exists in chain. Should never happen
                    }
                    int?stopAfter = null;

                    parents = new[] { GetOidAsync((int)parent0).AsTask() }.Concat(
                        Enumerable.Range(0, len)
                        .Select(i => NetBitConverter.ToUInt32(extraParents, i * sizeof(uint)))
                        .TakeWhile((v, i) => { if (i > stopAfter)
                                               {
                                                   return(false);
                                               }
                                               else if ((v & 0x80000000) != 0)
                                               {
                                                   stopAfter = i;
                                               }
                                               ; return(true); })
                        .Select(v => GetOidAsync((int)(v & 0x7FFFFFFF)).AsTask())).ToArray();
                }
                else
                {
                    parents = new[] { GetOidAsync((int)parent0).AsTask(), GetOidAsync((int)parent1).AsTask() }
                };

                IEnumerable <Task> waits;
                Task <long>?       v2 = null;
                if (_haveV2)
                {
                    v2    = ReadCommitTimeOffset(index).AsTask();
                    waits = parents.Concat(new Task[] { v2 });
                }
                else
                {
                    waits = parents;
                }

                await Task.WhenAll(waits).ConfigureAwait(false);

                long offset = v2 != null ? await v2.ConfigureAwait(false) : long.MinValue;

                return(new GitCommitGraphInfo(parents.Select(x => x.Result).ToArray(), chainLevel, offset));
            }

            return(null);
        }