Пример #1
0
        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);
        }
Пример #2
0
        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
        }
Пример #3
0
        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);
        }
Пример #4
0
        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);
        }
Пример #5
0
        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 {
Пример #6
0
        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}");
            }
        }
Пример #7
0
        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 !));
        }
Пример #8
0
        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}'");
                }
            }
        }