async ValueTask <GitId?> LoadIdFromFile(string fileName) { if (string.IsNullOrEmpty(fileName)) { throw new ArgumentNullException(nameof(fileName)); } if (!GitRepository.TryReadRefFile(fileName, null, out var body)) { return(null); } if (body.StartsWith("ref:", StringComparison.Ordinal)) { var ob = await Repository.ReferenceRepository.GetAsync(body.Substring(4).Trim()).ConfigureAwait(false); return(ob?.Id); } else if (GitId.TryParse(body, out var oid)) { return(oid); } else if (GitId.TryParse(body.Trim(), out oid)) { return(oid); } return(null); }
protected internal override async ValueTask <GitReference?> ResolveAsync(GitReference gitReference) { string dir = gitReference.Name.Contains('/', StringComparison.Ordinal) ? GitDir : WorkTreeDir; string fileName = Path.Combine(dir, gitReference.Name); if (!File.Exists(fileName)) { return(null); } if (GitRepository.TryReadRefFile(fileName, null, out var body)) { if (body.StartsWith("ref: ", StringComparison.OrdinalIgnoreCase)) { body = body.Substring("ref: ".Length); var ob = await Repository.ReferenceRepository.GetAsync(body.Trim()).ConfigureAwait(false); if (ob is not null) { return(ob); } } else if (GitId.TryParse(body, out var id)) { return(new GitReference(Repository.ReferenceRepository, gitReference.Name, id)); } } return(gitReference); // Not symbolic, and exists. Or error and exists }
public async ValueTask <GitId> ReadTreeIdAsync() { if (_treeId is not null) { return(_treeId); } var(bb, eol) = await Inner.ReadUntilEolFullAsync(AcceptedEols, null, 5 /* "tree " */ + GitId.MaxHashLength * 2 + 2 /* ALL EOL */).ConfigureAwait(false); if (bb.IsEof || eol == BucketEol.None || !bb.StartsWithASCII("tree ")) { throw new GitBucketException($"Expected 'tree' record at start of commit in '{Inner.Name}'"); } if (GitId.TryParse(bb.Slice(5, eol), out var id)) { _treeId = id; } else { throw new GitBucketException($"Expected valid 'tree' record at start of commit in '{Inner.Name}'"); } return(_treeId); }
public async ValueTask <(GitId, GitObjectType)> ReadObjectIdAsync() { if (_objectId is not null) { return(_objectId, _type); } var(bb, eol) = await Inner.ReadUntilEolFullAsync(AcceptedEols, null, 7 /* "object " */ + GitId.MaxHashLength * 2 + 2 /* ALL EOL */).ConfigureAwait(false); if (bb.IsEof || eol == BucketEol.None || !bb.StartsWithASCII("object ")) { throw new GitBucketException($"Expected 'object' record at start of tag in '{Inner.Name}'"); } if (GitId.TryParse(bb.Slice(7, eol), out var id)) { _objectId = id; } else { throw new GitBucketException($"Expected valid 'object' record at start of tag in '{Inner.Name}'"); } (bb, eol) = await Inner.ReadUntilEolFullAsync(AcceptedEols, null, 5 /* "type " */ + 6 /* "commit" */ + 2 /* ALL EOL */).ConfigureAwait(false); if (bb.IsEof || eol == BucketEol.None || !bb.StartsWithASCII("type ")) { _objectId = null; throw new GitBucketException($"Expected 'type' record of tag in '{Inner.Name}'"); } bb = bb.Slice(5, eol); if (bb.EqualsASCII("commit")) { _type = GitObjectType.Commit; } else if (bb.EqualsASCII("tree")) { _type = GitObjectType.Tree; } else if (bb.EqualsASCII("blob")) { _type = GitObjectType.Blob; } else if (bb.EqualsASCII("tag")) { _type = GitObjectType.Tag; } else { throw new GitBucketException($"Expected valid 'type' record in tag in '{Inner.Name}'"); } return(_objectId, _type); }
private protected void ParseLineToPeel(BucketBytes line, ref GitRefPeel?last, int idLength) { if (char.IsLetterOrDigit((char)line[0]) && line.Length > idLength + 1) { if (GitId.TryParse(line.Slice(0, idLength), out var oid)) { string name = line.Slice(idLength + 1).Trim().ToUTF8String(); if (GitReference.ValidName(name, false)) { _peelRefs ![name] = last = new GitRefPeel {
public async ValueTask <GitId?> ReadFirstParentIdAsync() { if (_parents is not null) { return(_parents.First()); } else if (_treeId is null) { await ReadTreeIdAsync().ConfigureAwait(false); } // Typically every commit has a parent, so optimize for that case var(bb, eol) = await Inner.ReadUntilEolFullAsync(AcceptedEols, requested : ParentLineReadLength).ConfigureAwait(false); if (bb.IsEof || eol == BucketEol.None || !bb.StartsWithASCII("parent ")) { if (bb.IsEof || !bb.StartsWithASCII("author ")) { throw new GitBucketException($"Expected 'parent' or 'author', but got neither in commit {Name} Bucket"); } _parents = Array.Empty <GitId>(); // We accidentally read the first part of the author line. Let's keep things clean if (eol == BucketEol.None) { var authorBucket = (bb.Slice("author ".Length).ToArray().AsBucket() + Inner); (bb, eol) = await authorBucket.ReadUntilEolFullAsync(AcceptedEols, requested : MaxHeader).ConfigureAwait(false); } _author = GitSignatureRecord.TryReadFromBucket(bb.Slice(eol), out var author) ? author : throw new GitBucketException($"Invalid author line in {Name} Bucket"); return(null); } else if (GitId.TryParse(bb.Slice("parent ".Length, eol), out var id)) { _parents = new List <GitId>() { id }; return(id); } else { throw new GitBucketException($"Invalid parent line in '{Inner.Name}"); } }
public static IAsyncEnumerable <GitId> RevisionList(this GitPlumbingClient c, GitRevisionListArgs options) { options.Verify(); List <string> args = new List <string>(); if (options.MaxCount != null) { args.Add($"--max-count={options.MaxCount}"); } if (options.FirstParentOnly) { args.Add("--first-parent"); } if (options.MaxParents != null) { args.Add($"--max-parents={options.MaxParents.Value}"); } if (options.MinParents != null) { args.Add($"--max-parents={options.MinParents.Value}"); } if (options.ShowPulls) { args.Add("--show-pulls"); } if (options.FullHistory) { args.Add("--full-history"); } if (options.Dense) { args.Add("--dense"); } if (options.Sparse) { args.Add("--sparse"); } if (options.SimplifyMerges) { args.Add("--simplify-merges"); } if (options.AncestryPath) { args.Add("--ancestry-path"); } if (options.Reverse) { args.Add("--reverse"); } switch (options.Order) { case GitRevisionListOrder.ReverseChronological: break; // Default case GitRevisionListOrder.Date: args.Add("--date-order"); break; case GitRevisionListOrder.AuthorDate: args.Add("--author-date-order"); break; case GitRevisionListOrder.Topological: args.Add("--topo-order"); break; default: throw new InvalidOperationException(); } if (!options.Commits?.Any() ?? true) { args.Add("HEAD"); } else { args.Add("--"); args.AddRange(options.Commits !); } return(c.Repository.WalkPlumbingCommand("rev-list", args).Select(x => GitId.TryParse(x, out var oid) ? oid : null !)); }
public async ValueTask <IReadOnlyCollection <GitId> > ReadAllParentIdsAsync() { List <GitId> parents; if (_parents is not null) { if (_parents is not List <GitId> lst) { return(_parents); // Already done } parents = lst; // Still collecting after ReadFirstParentIdAsync() } else if (_treeId is null) { await ReadTreeIdAsync().ConfigureAwait(false); parents = new(); } else { parents = new(); } while (true) { var(bb, eol) = await Inner.ReadUntilEolFullAsync(AcceptedEols, requested : MaxHeader).ConfigureAwait(false); if (bb.IsEof) { return(_parents = parents.Count > 0 ? parents.AsReadOnly() : Array.Empty <GitId>()); } else if (bb.StartsWithASCII("parent ") && GitId.TryParse(bb.Slice("parent ".Length, eol), out var id)) { parents.Add(id); // Stop scanning if we don't have more parents bb = Inner.Peek(); if (!bb.IsEmpty && bb[0] != 'p') { return(_parents = parents.AsReadOnly()); } continue; } else if (bb.StartsWithASCII("author ")) { // Auch. We overread. if (eol == BucketEol.None) { var authorBucket = (bb.Slice("author ".Length).ToArray().AsBucket() + Inner); (bb, eol) = await authorBucket.ReadUntilEolFullAsync(AcceptedEols, requested : MaxHeader).ConfigureAwait(false); } _author = GitSignatureRecord.TryReadFromBucket(bb.Slice(eol), out var author) ? author : throw new GitBucketException($"Invalid author line in {Name} Bucket"); return(_parents = parents.AsReadOnly()); } else { throw new GitBucketException($"Expected 'parent' or 'author', but got neither in commit '{Inner.Name}'"); } } }