private void ProcessTree(RevObject obj)
        {
            try
            {
                _treeWalk.reset(obj);
                while (_treeWalk.next())
                {
                    FileMode mode  = _treeWalk.getFileMode(0);
                    int      sType = (int)mode.ObjectType;

                    switch (sType)
                    {
                    case Constants.OBJ_BLOB:
                    case Constants.OBJ_TREE:
                        _treeWalk.getObjectId(_idBuffer, 0);
                        Needs(_revWalk.lookupAny(_idBuffer, sType));
                        continue;

                    default:
                        if (FileMode.GitLink.Equals(sType))
                        {
                            continue;
                        }
                        _treeWalk.getObjectId(_idBuffer, 0);
                        throw new CorruptObjectException("Invalid mode " + mode.ObjectType + " for " + _idBuffer.Name + " " +
                                                         _treeWalk.getPathString() + " in " + obj.getId().Name + ".");
                    }
                }
            }
            catch (IOException ioe)
            {
                throw new TransportException("Cannot Read tree " + obj.Name, ioe);
            }
            obj.add(COMPLETE);
        }
Example #2
0
        ///	<summary>
        /// Recursively add an entire tree into this builder.
        /// <para />
        /// If pathPrefix is "a/b" and the tree contains file "c" then the resulting
        /// DirCacheEntry will have the path "a/b/c".
        /// <para />
        /// All entries are inserted at stage 0, therefore assuming that the
        /// application will not insert any other paths with the same pathPrefix.
        /// </summary>
        /// <param name="pathPrefix">
        /// UTF-8 encoded prefix to mount the tree's entries at. If the
        /// path does not end with '/' one will be automatically inserted
        /// as necessary.
        /// </param>
        /// <param name="stage">Stage of the entries when adding them.</param>
        /// <param name="db">
        /// Repository the tree(s) will be read from during recursive
        /// traversal. This must be the same repository that the resulting
        /// <see cref="DirCache"/> would be written out to (or used in) otherwise
        /// the caller is simply asking for deferred MissingObjectExceptions.
        /// </param>
        /// <param name="tree">
        /// The tree to recursively add. This tree's contents will appear
        /// under <paramref name="pathPrefix"/>. The ObjectId must be that of a
        /// tree; the caller is responsible for dereferencing a tag or
        /// commit (if necessary).
        /// </param>
        /// <exception cref="IOException">
        /// A tree cannot be read to iterate through its entries.
        /// </exception>
        public void addTree(byte[] pathPrefix, int stage, Repository db, AnyObjectId tree)
        {
            var tw = new TreeWalk.TreeWalk(db);

            tw.reset();
            var curs = new WindowCursor();

            try
            {
                tw.addTree(new CanonicalTreeParser(pathPrefix, db, tree.ToObjectId(), curs));
            }
            finally
            {
                curs.Release();
            }
            tw.Recursive = true;

            if (!tw.next())
            {
                return;
            }

            DirCacheEntry newEntry = ToEntry(stage, tw);

            BeforeAdd(newEntry);
            FastAdd(newEntry);
            while (tw.next())
            {
                FastAdd(ToEntry(stage, tw));
            }
        }
Example #3
0
        public override bool include(RevWalk walker, RevCommit c)
        {
            // Reset the tree filter to scan this commit and parents.
            //
            RevCommit[] pList    = c.Parents;
            int         nParents = pList.Length;

            TreeWalk.TreeWalk tw = _pathFilter;
            var trees            = new ObjectId[nParents + 1];

            for (int i = 0; i < nParents; i++)
            {
                RevCommit p = c.Parents[i];
                if ((p.Flags & Parsed) == 0)
                {
                    p.parseHeaders(walker);
                }
                trees[i] = p.Tree;
            }

            trees[nParents] = c.Tree;
            tw.reset(trees);

            if (nParents == 1)
            {
                // We have exactly one parent. This is a very common case.
                //
                int chgs = 0, adds = 0;
                while (tw.next())
                {
                    chgs++;
                    if (tw.getRawMode(0) == 0 && tw.getRawMode(1) != 0)
                    {
                        adds++;
                    }
                    else
                    {
                        break; // no point in looking at this further.
                    }
                }

                if (chgs == 0)
                {
                    // No changes, so our tree is effectively the same as
                    // our parent tree. We pass the buck to our parent.
                    //
                    c.Flags |= Rewrite;
                    return(false);
                }

                // We have interesting items, but neither of the special
                // cases denoted above.
                //
                return(true);
            }

            if (nParents == 0)
            {
                // We have no parents to compare against. Consider us to be
                // Rewrite only if we have no paths matching our filter.
                //
                if (tw.next())
                {
                    return(true);
                }

                c.Flags |= Rewrite;
                return(false);
            }

            // We are a merge commit. We can only be Rewrite if we are same
            // to _all_ parents. We may also be able to eliminate a parent if
            // it does not contribute changes to us. Such a parent may be an
            // uninteresting side branch.
            //
            var chgs_ = new int[nParents];
            var adds_ = new int[nParents];

            while (tw.next())
            {
                int myMode = tw.getRawMode(nParents);
                for (int i = 0; i < nParents; i++)
                {
                    int pMode = tw.getRawMode(i);
                    if (myMode == pMode && tw.idEqual(i, nParents))
                    {
                        continue;
                    }

                    chgs_[i]++;
                    if (pMode == 0 && myMode != 0)
                    {
                        adds_[i]++;
                    }
                }
            }

            bool same = false;
            bool diff = false;

            for (int i = 0; i < nParents; i++)
            {
                if (chgs_[i] == 0)
                {
                    // No changes, so our tree is effectively the same as
                    // this parent tree. We pass the buck to only this one
                    // parent commit.
                    //

                    RevCommit p = pList[i];
                    if ((p.Flags & Uninteresting) != 0)
                    {
                        // This parent was marked as not interesting by the
                        // application. We should look for another parent
                        // that is interesting.
                        //
                        same = true;
                        continue;
                    }

                    c.Flags  |= Rewrite;
                    c.Parents = new[] { p };
                    return(false);
                }

                if (chgs_[i] == adds_[i])
                {
                    // All of the differences from this parent were because we
                    // added files that they did not have. This parent is our
                    // "empty tree root" and thus their history is not relevant.
                    // Cut our grandparents to be an empty list.
                    //
                    pList[i].Parents = RevCommit.NoParents;
                }

                // We have an interesting difference relative to this parent.
                //
                diff = true;
            }

            if (diff && !same)
            {
                // We did not abort above, so we are different in at least one
                // way from all of our parents. We have to take the blame for
                // that difference.
                //
                return(true);
            }

            // We are the same as all of our parents. We must keep them
            // as they are and allow those parents to flow into pending
            // for further scanning.
            //
            c.Flags |= Rewrite;
            return(false);
        }
Example #4
0
 /**
  * Recursively add an entire tree into this builder.
  * <p>
  * If pathPrefix is "a/b" and the tree contains file "c" then the resulting
  * DirCacheEntry will have the path "a/b/c".
  * <p>
  * All entries are inserted at stage 0, therefore assuming that the
  * application will not insert any other paths with the same pathPrefix.
  *
  * @param pathPrefix
  *            UTF-8 encoded prefix to mount the tree's entries at. If the
  *            path does not end with '/' one will be automatically inserted
  *            as necessary.
  * @param stage
  *            stage of the entries when adding them.
  * @param db
  *            repository the tree(s) will be read from during recursive
  *            traversal. This must be the same repository that the resulting
  *            DirCache would be written out to (or used in) otherwise the
  *            caller is simply asking for deferred MissingObjectExceptions.
  * @param tree
  *            the tree to recursively add. This tree's contents will appear
  *            under <code>pathPrefix</code>. The ObjectId must be that of a
  *            tree; the caller is responsible for dereferencing a tag or
  *            commit (if necessary).
  * @throws IOException
  *             a tree cannot be read to iterate through its entries.
  */
 public void addTree(byte[] pathPrefix, int stage, Repository db, AnyObjectId tree)
 {
     var tw = new TreeWalk.TreeWalk(db);
     tw.reset();
     var curs = new WindowCursor();
     try
     {
         tw.addTree(new CanonicalTreeParser(pathPrefix, db, tree.ToObjectId(), curs));
     }
     finally
     {
         curs.release();
     }
     tw.setRecursive(true);
     if (tw.next())
     {
         DirCacheEntry newEntry = toEntry(stage, tw);
         beforeAdd(newEntry);
         fastAdd(newEntry);
         while (tw.next())
             fastAdd(toEntry(stage, tw));
     }
 }