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; } }
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); } }
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)); }
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
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>()); } }
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)); }
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); }