Parses raw Git trees from the canonical semi-text/semi-binary format.
Inheritance: AbstractTreeIterator
示例#1
0
        private CanonicalTreeParser ParserFor(AnyObjectId id)
        {
            var p = new CanonicalTreeParser();

            p.reset(_db, id, _cursor);
            return(p);
        }
示例#2
0
        /**
         * Back door to quickly Create a subtree iterator for any subtree.
         * <para />
         * Don't use this unless you are ObjectWalk. The method is meant to be
         * called only once the current entry has been identified as a tree and its
         * identity has been converted into an ObjectId.
         *
         * @param repo
         *            repository to load the tree data from.
         * @param id
         *            ObjectId of the tree to open.
         * @param curs
         *            window cursor to use during repository access.
         * @return a new parser that walks over the current subtree.
         * @throws IOException
         *             a loose object or pack file could not be Read.
         */
        public CanonicalTreeParser createSubtreeIterator0(Repository repo, AnyObjectId id, WindowCursor curs)         // [henon] createSubtreeIterator0 <--- not a typo!
        {
            var p = new CanonicalTreeParser(this);

            p.reset(repo, id, curs);
            return(p);
        }
示例#3
0
        /**
         * Reset this walker to run over a single existing tree.
         *
         * @param id
         *            the tree we need to parse. The walker will execute over this
         *            single tree if the reset is successful.
         * @throws MissingObjectException
         *             the given tree object does not exist in this repository.
         * @throws IncorrectObjectTypeException
         *             the given object id does not denote a tree, but instead names
         *             some other non-tree type of object. Note that commits are not
         *             trees, even if they are sometimes called a "tree-ish".
         * @throws CorruptObjectException
         *             the object claimed to be a tree, but its contents did not
         *             appear to be a tree. The repository may have data corruption.
         * @throws IOException
         *             a loose object or pack file could not be Read.
         */
        public void reset(AnyObjectId id)
        {
            if (_trees.Length == 1)
            {
                AbstractTreeIterator iterator = _trees[0];
                while (iterator.Parent != null)
                {
                    iterator = iterator.Parent;
                }

                CanonicalTreeParser oParse = (iterator as CanonicalTreeParser);
                if (oParse != null)
                {
                    iterator.Matches    = null;
                    iterator.MatchShift = 0;

                    oParse.reset(_db, id, _cursor);
                    _trees[0] = iterator;
                }
                else
                {
                    _trees[0] = ParserFor(id);
                }
            }
            else
            {
                _trees = new AbstractTreeIterator[] { ParserFor(id) };
            }

            _advance = false;
            _depth   = 0;
        }
示例#4
0
        /**
         * Reset this parser to walk through the given tree.
         *
         * @param repo
         *            repository to load the tree data from.
         * @param id
         *            identity of the tree being parsed; used only in exception
         *            messages if data corruption is found.
         * @param curs
         *            window cursor to use during repository access.
         * @return the root level parser.
         * @throws MissingObjectException
         *             the object supplied is not available from the repository.
         * @throws IncorrectObjectTypeException
         *             the object supplied as an argument is not actually a tree and
         *             cannot be parsed as though it were a tree.
         * @throws IOException
         *             a loose object or pack file could not be Read.
         */
        public CanonicalTreeParser resetRoot(Repository repo, AnyObjectId id, WindowCursor curs)
        {
            CanonicalTreeParser p = this;

            while (p.Parent != null)
            {
                p = (CanonicalTreeParser)p.Parent;
            }
            p.reset(repo, id, curs);
            return(p);
        }
示例#5
0
        /// <summary>
        /// Return this iterator, or its parent, if the tree is at eof.
        /// </summary>
        /// <returns></returns>
        public CanonicalTreeParser next()
        {
            CanonicalTreeParser iterator = this;

            while (true)
            {
                iterator.next(1);
                if (iterator.eof() && iterator.Parent != null)
                {
                    // Parent was left pointing at the entry for us; advance
                    // the parent to the next entry, possibly unwinding many
                    // levels up the tree.
                    //
                    iterator = (CanonicalTreeParser)iterator.Parent;
                    continue;
                }
                return(iterator);
            }
        }
示例#6
0
        /**
         * Reset this walker to run over a set of existing trees.
         *
         * @param ids
         *            the trees we need to parse. The walker will execute over this
         *            many parallel trees if the reset is successful.
         * @throws MissingObjectException
         *             the given tree object does not exist in this repository.
         * @throws IncorrectObjectTypeException
         *             the given object id does not denote a tree, but instead names
         *             some other non-tree type of object. Note that commits are not
         *             trees, even if they are sometimes called a "tree-ish".
         * @throws CorruptObjectException
         *             the object claimed to be a tree, but its contents did not
         *             appear to be a tree. The repository may have data corruption.
         * @throws IOException
         *             a loose object or pack file could not be Read.
         */
        public void reset(AnyObjectId[] ids)
        {
            if (ids == null)
            {
                throw new ArgumentNullException("ids");
            }
            int oldLen = _trees.Length;
            int newLen = ids.Length;

            AbstractTreeIterator[] r = newLen == oldLen ? _trees : new AbstractTreeIterator[newLen];
            for (int i = 0; i < newLen; i++)
            {
                AbstractTreeIterator iterator;

                if (i < oldLen)
                {
                    iterator = _trees[i];
                    while (iterator.Parent != null)
                    {
                        iterator = iterator.Parent;
                    }

                    CanonicalTreeParser oParse = (iterator as CanonicalTreeParser);
                    if (oParse != null && iterator.PathOffset == 0)
                    {
                        iterator.Matches    = null;
                        iterator.MatchShift = 0;
                        oParse.reset(_db, ids[i], _cursor);
                        r[i] = iterator;
                        continue;
                    }
                }

                iterator = ParserFor(ids[i]);
                r[i]     = iterator;
            }

            _trees   = r;
            _advance = false;
            _depth   = 0;
        }
示例#7
0
        /// <summary>
        /// Return this iterator, or its parent, if the tree is at eof.
        /// </summary>
        /// <returns></returns>
        public CanonicalTreeParser next()
        {
            CanonicalTreeParser iterator = this;

            while (true)
            {
                if (iterator._nextPtr == iterator._raw.Length)
                {
                    // This parser has reached EOF, return to the parent.
                    if (iterator._parent == null)
                    {
                        iterator._currPtr = iterator._nextPtr;
                        return(iterator);
                    }
                    iterator = (CanonicalTreeParser)iterator.Parent;
                    continue;
                }

                iterator._prevPtr = iterator._currPtr;
                iterator._currPtr = iterator._nextPtr;
                iterator.ParseEntry();
                return(iterator);
            }
        }
示例#8
0
 /// <summary>
 /// Create a new revision and object walker for a given repository.
 /// </summary>
 /// <param name="repo">
 /// The repository the walker will obtain data from.
 /// </param>
 public ObjectWalk(Repository repo)
     : base(repo)
 {
     _pendingObjects = new BlockObjQueue();
     _treeWalk = new CanonicalTreeParser();
 }
示例#9
0
        private void MarkTreeUninteresting(RevObject tree)
        {
            if ((tree.Flags & UNINTERESTING) != 0) return;
            tree.Flags |= UNINTERESTING;

            _treeWalk = _treeWalk.resetRoot(Repository, tree, WindowCursor);
            while (!_treeWalk.eof())
            {
                FileMode mode = _treeWalk.EntryFileMode;
                var sType = (int)mode.ObjectType;

                switch (sType)
                {
                    case Constants.OBJ_BLOB:
                        _treeWalk.getEntryObjectId(IdBuffer);
                        lookupBlob(IdBuffer).Flags |= UNINTERESTING;
                        break;

                    case Constants.OBJ_TREE:
                        _treeWalk.getEntryObjectId(IdBuffer);
                        RevTree t = lookupTree(IdBuffer);
                        if ((t.Flags & UNINTERESTING) == 0)
                        {
                            t.Flags |= UNINTERESTING;
                            _treeWalk = _treeWalk.createSubtreeIterator0(Repository, t, WindowCursor);
                            continue;
                        }
                        break;

                    default:
                        if (FileMode.GitLink == FileMode.FromBits(mode.Bits)) break;
                        _treeWalk.getEntryObjectId(IdBuffer);

                        throw new CorruptObjectException("Invalid mode " + mode
                                + " for " + IdBuffer + " "
                                + _treeWalk.EntryPathString + " in " + tree + ".");
                }

                _treeWalk = _treeWalk.next();
            }
        }
示例#10
0
 internal override void reset(int retainFlags)
 {
     base.reset(retainFlags);
     _pendingObjects = new BlockObjQueue();
     _treeWalk = new CanonicalTreeParser();
     _currentTree = null;
     last = null;
 }
示例#11
0
        /// <summary>
        /// Pop the next most recent object.
        /// </summary>
        /// <returns>next most recent object; null if traversal is over.</returns>
        /// <exception cref="MissingObjectException">
        /// One or or more of the next objects are not available from the
        /// object database, but were thought to be candidates for
        /// traversal. This usually indicates a broken link.
        /// </exception>
        /// <exception cref="IncorrectObjectTypeException">
        /// One or or more of the objects in a tree do not match the type indicated.
        /// </exception>
        /// <exception cref="Exception">
        /// A pack file or loose object could not be Read.
        /// </exception>
        public RevObject nextObject()
        {
            if (last != null)
            {
                _treeWalk = last is RevTree ? enter(last) : _treeWalk.next();
            }

            while (!_treeWalk.eof())
            {
                FileMode mode = _treeWalk.EntryFileMode;

                switch ((int)mode.ObjectType)
                {
                    case Constants.OBJ_BLOB:
                        _treeWalk.getEntryObjectId(IdBuffer);

                        RevBlob blob = lookupBlob(IdBuffer);
                        if ((blob.Flags & SEEN) != 0) break;

                        blob.Flags |= SEEN;
                        if (ShouldSkipObject(blob)) break;

                        last = blob;
                        return blob;

                    case Constants.OBJ_TREE:
                        _treeWalk.getEntryObjectId(IdBuffer);

                        RevTree tree = lookupTree(IdBuffer);
                        if ((tree.Flags & SEEN) != 0) break;

                        tree.Flags |= SEEN;
                        if (ShouldSkipObject(tree)) break;

                        last = tree;
                        return tree;

                    default:
                        if (FileMode.GitLink.Equals(mode.Bits)) break;
                        _treeWalk.getEntryObjectId(IdBuffer);

                        throw new CorruptObjectException("Invalid mode " + mode
                                + " for " + IdBuffer.Name + " '"
                                + _treeWalk.EntryPathString + "' in "
                                + _currentTree.Name + ".");
                }

                _treeWalk = _treeWalk.next();
            }

            last = null;
            while (true)
            {
                RevObject obj = _pendingObjects.next();
                if (obj == null) return null;
                if ((obj.Flags & SEEN) != 0) continue;

                obj.Flags |= SEEN;
                if (ShouldSkipObject(obj)) continue;

                RevTree oTree = (obj as RevTree);
                if (oTree != null)
                {
                    _currentTree = oTree;
                    _treeWalk = _treeWalk.resetRoot(Repository, _currentTree, WindowCursor);
                }

                return obj;
            }
        }
示例#12
0
 public override void Dispose()
 {
     base.Dispose();
     _pendingObjects = new BlockObjQueue();
     _treeWalk = new CanonicalTreeParser();
     _currentTree = null;
     last = null;
 }
示例#13
0
 // [henon] createSubtreeIterator0 <--- not a typo!
 /**
  * Back door to quickly Create a subtree iterator for any subtree.
  * <para />
  * Don't use this unless you are ObjectWalk. The method is meant to be
  * called only once the current entry has been identified as a tree and its
  * identity has been converted into an ObjectId.
  *
  * @param repo
  *            repository to load the tree data from.
  * @param id
  *            ObjectId of the tree to open.
  * @param curs
  *            window cursor to use during repository access.
  * @return a new parser that walks over the current subtree.
  * @throws IOException
  *             a loose object or pack file could not be Read.
  */
 public CanonicalTreeParser createSubtreeIterator0(Repository repo, AnyObjectId id, WindowCursor curs)
 {
     var p = new CanonicalTreeParser(this);
     p.reset(repo, id, curs);
     return p;
 }
示例#14
0
        /// <summary>
        /// Pop the next most recent object.
        /// </summary>
        /// <returns>next most recent object; null if traversal is over.</returns>
        /// <exception cref="MissingObjectException">
        /// One or or more of the next objects are not available from the
        /// object database, but were thought to be candidates for
        /// traversal. This usually indicates a broken link.
        /// </exception>
        /// <exception cref="IncorrectObjectTypeException">
        /// One or or more of the objects in a tree do not match the type indicated.
        /// </exception>
        /// <exception cref="Exception">
        /// A pack file or loose object could not be Read.
        /// </exception>
        public RevObject nextObject()
        {
            _fromTreeWalk = false;

            if (_nextSubtree != null)
            {
                _treeWalk = _treeWalk.createSubtreeIterator0(Repository, _nextSubtree, WindowCursor);
                _nextSubtree = null;
            }

            while (!_treeWalk.eof())
            {
                FileMode mode = _treeWalk.EntryFileMode;
                var sType = (int)mode.ObjectType;

                switch (sType)
                {
                    case Constants.OBJ_BLOB:
                        _treeWalk.getEntryObjectId(IdBuffer);

                        RevBlob blob = lookupBlob(IdBuffer);
                        if ((blob.Flags & SEEN) != 0) break;

                        blob.Flags |= SEEN;
                        if (ShouldSkipObject(blob)) break;

                        _fromTreeWalk = true;
                        return blob;

                    case Constants.OBJ_TREE:
                        _treeWalk.getEntryObjectId(IdBuffer);

                        RevTree tree = lookupTree(IdBuffer);
                        if ((tree.Flags & SEEN) != 0) break;

                        tree.Flags |= SEEN;
                        if (ShouldSkipObject(tree)) break;

                        _nextSubtree = tree;
                        _fromTreeWalk = true;
                        return tree;

                    default:
                        if (FileMode.GitLink.Equals(mode.Bits)) break;
                        _treeWalk.getEntryObjectId(IdBuffer);

                        throw new CorruptObjectException("Invalid mode " + mode
                                + " for " + IdBuffer + " "
                                + _treeWalk.EntryPathString + " in " + _currentTree
                                + ".");
                }

                _treeWalk = _treeWalk.next();
            }

            while (true)
            {
                RevObject obj = _pendingObjects.next();
                if (obj == null) return null;
                if ((obj.Flags & SEEN) != 0) continue;

                obj.Flags |= SEEN;
                if (ShouldSkipObject(obj)) continue;

                if (obj is RevTree)
                {
                    _currentTree = (RevTree)obj;
                    _treeWalk = _treeWalk.resetRoot(Repository, _currentTree, WindowCursor);
                }

                return obj;
            }
        }