/// <summary>Write (if necessary) this tree to the object store.</summary>
 /// <remarks>Write (if necessary) this tree to the object store.</remarks>
 /// <param name="cache">the complete cache from DirCache.</param>
 /// <param name="cIdx">
 /// first position of <code>cache</code> that is a member of this
 /// tree. The path of <code>cache[cacheIdx].path</code> for the
 /// range <code>[0,pathOff-1)</code> matches the complete path of
 /// this tree, from the root of the repository.
 /// </param>
 /// <param name="pathOffset">
 /// number of bytes of <code>cache[cacheIdx].path</code> that
 /// matches this tree's path. The value at array position
 /// <code>cache[cacheIdx].path[pathOff-1]</code> is always '/' if
 /// <code>pathOff</code> is &gt; 0.
 /// </param>
 /// <param name="ow">the writer to use when serializing to the store.</param>
 /// <returns>identity of this tree.</returns>
 /// <exception cref="NGit.Errors.UnmergedPathException">
 /// one or more paths contain higher-order stages (stage &gt; 0),
 /// which cannot be stored in a tree object.
 /// </exception>
 /// <exception cref="System.IO.IOException">an unexpected error occurred writing to the object store.
 ///     </exception>
 internal virtual ObjectId WriteTree(DirCacheEntry[] cache, int cIdx, int pathOffset
                                     , ObjectInserter ow)
 {
     if (id == null)
     {
         int           endIdx   = cIdx + entrySpan;
         TreeFormatter fmt      = new TreeFormatter(ComputeSize(cache, cIdx, pathOffset, ow));
         int           childIdx = 0;
         int           entryIdx = cIdx;
         while (entryIdx < endIdx)
         {
             DirCacheEntry e  = cache[entryIdx];
             byte[]        ep = e.path;
             if (childIdx < childCnt)
             {
                 NGit.Dircache.DirCacheTree st = children[childIdx];
                 if (st.Contains(ep, pathOffset, ep.Length))
                 {
                     fmt.Append(st.encodedName, FileMode.TREE, st.id);
                     entryIdx += st.entrySpan;
                     childIdx++;
                     continue;
                 }
             }
             fmt.Append(ep, pathOffset, ep.Length - pathOffset, e.FileMode, e.IdBuffer, e.IdOffset
                        );
             entryIdx++;
         }
         id = ow.Insert(fmt);
     }
     return(id);
 }
Example #2
0
 private void ParseEntry()
 {
     currentEntry = cache.GetEntry(ptr);
     byte[] cep = currentEntry.path;
     if (nextSubtreePos != tree.GetChildCount())
     {
         DirCacheTree s = tree.GetChild(nextSubtreePos);
         if (s.Contains(cep, pathOffset, cep.Length))
         {
             // The current position is the first file of this subtree.
             // Use the subtree instead as the current position.
             //
             currentSubtree = s;
             nextSubtreePos++;
             if (s.IsValid())
             {
                 s.GetObjectId().CopyRawTo(subtreeId, 0);
             }
             mode    = FileMode.TREE.GetBits();
             path    = cep;
             pathLen = pathOffset + s.NameLength();
             return;
         }
     }
     // The current position is a file/symlink/gitlink so we
     // do not have a subtree located here.
     //
     mode           = currentEntry.RawMode;
     path           = cep;
     pathLen        = cep.Length;
     currentSubtree = null;
 }
        /// <exception cref="NGit.Errors.UnmergedPathException"></exception>
        /// <exception cref="System.IO.IOException"></exception>
        private int ComputeSize(DirCacheEntry[] cache, int cIdx, int pathOffset, ObjectInserter
                                ow)
        {
            int endIdx   = cIdx + entrySpan;
            int childIdx = 0;
            int entryIdx = cIdx;
            int size     = 0;

            while (entryIdx < endIdx)
            {
                DirCacheEntry e = cache[entryIdx];
                if (e.Stage != 0)
                {
                    throw new UnmergedPathException(e);
                }
                byte[] ep = e.path;
                if (childIdx < childCnt)
                {
                    NGit.Dircache.DirCacheTree st = children[childIdx];
                    if (st.Contains(ep, pathOffset, ep.Length))
                    {
                        int stOffset = pathOffset + st.NameLength() + 1;
                        st.WriteTree(cache, entryIdx, stOffset, ow);
                        size     += TreeFormatter.EntrySize(FileMode.TREE, st.NameLength());
                        entryIdx += st.entrySpan;
                        childIdx++;
                        continue;
                    }
                }
                size += TreeFormatter.EntrySize(e.FileMode, ep.Length - pathOffset);
                entryIdx++;
            }
            return(size);
        }
        private static int Namecmp(byte[] a, int aPos, NGit.Dircache.DirCacheTree ct)
        {
            if (ct == null)
            {
                return(-1);
            }
            byte[] b    = ct.encodedName;
            int    aLen = a.Length;
            int    bLen = b.Length;
            int    bPos = 0;

            for (; aPos < aLen && bPos < bLen; aPos++, bPos++)
            {
                int cmp = (a[aPos] & unchecked ((int)(0xff))) - (b[bPos] & unchecked ((int)(0xff)));
                if (cmp != 0)
                {
                    return(cmp);
                }
            }
            if (bPos == bLen)
            {
                return(a[aPos] == '/' ? 0 : -1);
            }
            return(aLen - bLen);
        }
        private void InsertChild(int stIdx, NGit.Dircache.DirCacheTree st)
        {
            NGit.Dircache.DirCacheTree[] c = children;
            if (childCnt + 1 <= c.Length)
            {
                if (stIdx < childCnt)
                {
                    System.Array.Copy(c, stIdx, c, stIdx + 1, childCnt - stIdx);
                }
                c[stIdx] = st;
                childCnt++;
                return;
            }
            int n = c.Length;

            NGit.Dircache.DirCacheTree[] a = new NGit.Dircache.DirCacheTree[n + 1];
            if (stIdx > 0)
            {
                System.Array.Copy(c, 0, a, 0, stIdx);
            }
            a[stIdx] = st;
            if (stIdx < n)
            {
                System.Array.Copy(c, stIdx, a, stIdx + 1, n - stIdx);
            }
            children = a;
            childCnt++;
        }
Example #6
0
 /// <summary>Empty this index, removing all entries.</summary>
 /// <remarks>Empty this index, removing all entries.</remarks>
 public virtual void Clear()
 {
     snapshot      = null;
     sortedEntries = NO_ENTRIES;
     entryCnt      = 0;
     tree          = null;
 }
Example #7
0
 /// <summary>Empty this index, removing all entries.</summary>
 /// <remarks>Empty this index, removing all entries.</remarks>
 public virtual void Clear()
 {
     snapshot          = null;
     sortedEntries     = NO_ENTRIES;
     entryCnt          = 0;
     tree              = null;
     readIndexChecksum = NO_CHECKSUM;
 }
        internal DirCacheTree(byte[] @in, MutableInteger off, NGit.Dircache.DirCacheTree
                              myParent)
        {
            parent = myParent;
            int ptr     = RawParseUtils.Next(@in, off.value, '\0');
            int nameLen = ptr - off.value - 1;

            if (nameLen > 0)
            {
                encodedName = new byte[nameLen];
                System.Array.Copy(@in, off.value, encodedName, 0, nameLen);
            }
            else
            {
                encodedName = NO_NAME;
            }
            entrySpan = RawParseUtils.ParseBase10(@in, ptr, off);
            int subcnt = RawParseUtils.ParseBase10(@in, off.value, off);

            off.value = RawParseUtils.Next(@in, off.value, '\n');
            if (entrySpan >= 0)
            {
                // Valid trees have a positive entry count and an id of a
                // tree object that should exist in the object database.
                //
                id         = ObjectId.FromRaw(@in, off.value);
                off.value += Constants.OBJECT_ID_LENGTH;
            }
            if (subcnt > 0)
            {
                bool alreadySorted = true;
                children = new NGit.Dircache.DirCacheTree[subcnt];
                for (int i = 0; i < subcnt; i++)
                {
                    children[i] = new NGit.Dircache.DirCacheTree(@in, off, this);
                    // C Git's ordering differs from our own; it prefers to
                    // sort by length first. This sometimes produces a sort
                    // we do not desire. On the other hand it may have been
                    // created by us, and be sorted the way we want.
                    //
                    if (alreadySorted && i > 0 && TREE_CMP.Compare(children[i - 1], children[i]) > 0)
                    {
                        alreadySorted = false;
                    }
                }
                if (!alreadySorted)
                {
                    Arrays.Sort(children, 0, subcnt, TREE_CMP);
                }
            }
            else
            {
                // Leaf level trees have no children, only (file) entries.
                //
                children = NO_CHILDREN;
            }
            childCnt = subcnt;
        }
 private DirCacheTree(NGit.Dircache.DirCacheTree myParent, byte[] path, int pathOff
                      , int pathLen)
 {
     parent      = myParent;
     encodedName = new byte[pathLen];
     System.Array.Copy(path, pathOff, encodedName, 0, pathLen);
     children  = NO_CHILDREN;
     childCnt  = 0;
     entrySpan = -1;
 }
        public virtual void TestEmptyCache_Clear_NoCacheTree()
        {
            DirCache     dc   = db.ReadDirCache();
            DirCacheTree tree = dc.GetCacheTree(true);

            NUnit.Framework.Assert.IsNotNull(tree);
            dc.Clear();
            NUnit.Framework.Assert.IsNull(dc.GetCacheTree(false));
            NUnit.Framework.Assert.AreNotSame(tree, dc.GetCacheTree(true));
        }
Example #11
0
 internal DirCacheIterator(NGit.Dircache.DirCacheIterator p, DirCacheTree dct) : base
         (p, p.path, p.pathLen + 1)
 {
     cache     = p.cache;
     tree      = dct;
     treeStart = p.ptr;
     treeEnd   = treeStart + tree.GetEntrySpan();
     subtreeId = p.subtreeId;
     ptr       = p.ptr;
     ParseEntry();
 }
Example #12
0
 /// <summary>Create a new iterator for an already loaded DirCache instance.</summary>
 /// <remarks>
 /// Create a new iterator for an already loaded DirCache instance.
 /// <p>
 /// The iterator implementation may copy part of the cache's data during
 /// construction, so the cache must be read in prior to creating the
 /// iterator.
 /// </remarks>
 /// <param name="dc">the cache to walk. It must be already loaded into memory.</param>
 public DirCacheIterator(DirCache dc)
 {
     cache     = dc;
     tree      = dc.GetCacheTree(true);
     treeStart = 0;
     treeEnd   = tree.GetEntrySpan();
     subtreeId = new byte[Constants.OBJECT_ID_LENGTH];
     if (!Eof)
     {
         ParseEntry();
     }
 }
Example #13
0
 /// <summary>Obtain (or build) the current cache tree structure.</summary>
 /// <remarks>
 /// Obtain (or build) the current cache tree structure.
 /// <p>
 /// This method can optionally recreate the cache tree, without flushing the
 /// tree objects themselves to disk.
 /// </remarks>
 /// <param name="build">
 /// if true and the cache tree is not present in the index it will
 /// be generated and returned to the caller.
 /// </param>
 /// <returns>
 /// the cache tree; null if there is no current cache tree available
 /// and <code>build</code> was false.
 /// </returns>
 public virtual DirCacheTree GetCacheTree(bool build)
 {
     if (build)
     {
         if (tree == null)
         {
             tree = new DirCacheTree();
         }
         tree.Validate(sortedEntries, entryCnt, 0, 0);
     }
     return(tree);
 }
Example #14
0
 internal virtual int NextEntry(byte[] p, int pLen, int nextIdx)
 {
     while (nextIdx < entryCnt)
     {
         DirCacheEntry next = sortedEntries[nextIdx];
         if (!DirCacheTree.Peq(p, next.path, pLen))
         {
             break;
         }
         nextIdx++;
     }
     return(nextIdx);
 }
        public virtual void TestTwoLevelSubtree()
        {
            DirCache dc = db.ReadDirCache();

            string[]        paths = new string[] { "a.", "a/b", "a/c/e", "a/c/f", "a/d", "a0b" };
            DirCacheEntry[] ents  = new DirCacheEntry[paths.Length];
            for (int i = 0; i < paths.Length; i++)
            {
                ents[i]          = new DirCacheEntry(paths[i]);
                ents[i].FileMode = FileMode.REGULAR_FILE;
            }
            int             aFirst  = 1;
            int             aLast   = 4;
            int             acFirst = 2;
            int             acLast  = 3;
            DirCacheBuilder b       = dc.Builder();

            for (int i_1 = 0; i_1 < ents.Length; i_1++)
            {
                b.Add(ents[i_1]);
            }
            b.Finish();
            NUnit.Framework.Assert.IsNull(dc.GetCacheTree(false));
            DirCacheTree root = dc.GetCacheTree(true);

            NUnit.Framework.Assert.IsNotNull(root);
            NUnit.Framework.Assert.AreSame(root, dc.GetCacheTree(true));
            NUnit.Framework.Assert.AreEqual(string.Empty, root.GetNameString());
            NUnit.Framework.Assert.AreEqual(string.Empty, root.GetPathString());
            NUnit.Framework.Assert.AreEqual(1, root.GetChildCount());
            NUnit.Framework.Assert.AreEqual(dc.GetEntryCount(), root.GetEntrySpan());
            NUnit.Framework.Assert.IsFalse(root.IsValid());
            DirCacheTree aTree = root.GetChild(0);

            NUnit.Framework.Assert.IsNotNull(aTree);
            NUnit.Framework.Assert.AreSame(aTree, root.GetChild(0));
            NUnit.Framework.Assert.AreEqual("a", aTree.GetNameString());
            NUnit.Framework.Assert.AreEqual("a/", aTree.GetPathString());
            NUnit.Framework.Assert.AreEqual(1, aTree.GetChildCount());
            NUnit.Framework.Assert.AreEqual(aLast - aFirst + 1, aTree.GetEntrySpan());
            NUnit.Framework.Assert.IsFalse(aTree.IsValid());
            DirCacheTree acTree = aTree.GetChild(0);

            NUnit.Framework.Assert.IsNotNull(acTree);
            NUnit.Framework.Assert.AreSame(acTree, aTree.GetChild(0));
            NUnit.Framework.Assert.AreEqual("c", acTree.GetNameString());
            NUnit.Framework.Assert.AreEqual("a/c/", acTree.GetPathString());
            NUnit.Framework.Assert.AreEqual(0, acTree.GetChildCount());
            NUnit.Framework.Assert.AreEqual(acLast - acFirst + 1, acTree.GetEntrySpan());
            NUnit.Framework.Assert.IsFalse(acTree.IsValid());
        }
        public virtual void TestEmptyCache_CreateEmptyCacheTree()
        {
            DirCache     dc   = db.ReadDirCache();
            DirCacheTree tree = dc.GetCacheTree(true);

            NUnit.Framework.Assert.IsNotNull(tree);
            NUnit.Framework.Assert.AreSame(tree, dc.GetCacheTree(false));
            NUnit.Framework.Assert.AreSame(tree, dc.GetCacheTree(true));
            NUnit.Framework.Assert.AreEqual(string.Empty, tree.GetNameString());
            NUnit.Framework.Assert.AreEqual(string.Empty, tree.GetPathString());
            NUnit.Framework.Assert.AreEqual(0, tree.GetChildCount());
            NUnit.Framework.Assert.AreEqual(0, tree.GetEntrySpan());
            NUnit.Framework.Assert.IsFalse(tree.IsValid());
        }
        public virtual void TestReadIndex_DirCacheTree()
        {
            IDictionary <string, DirCacheCGitCompatabilityTest.CGitIndexRecord> cList = ReadLsFiles
                                                                                            ();
            IDictionary <string, DirCacheCGitCompatabilityTest.CGitLsTreeRecord> cTree = ReadLsTree
                                                                                             ();
            DirCache dc = new DirCache(index, FS.DETECTED);

            NUnit.Framework.Assert.AreEqual(0, dc.GetEntryCount());
            dc.Read();
            NUnit.Framework.Assert.AreEqual(cList.Count, dc.GetEntryCount());
            DirCacheTree jTree = dc.GetCacheTree(false);

            NUnit.Framework.Assert.IsNotNull(jTree);
            NUnit.Framework.Assert.AreEqual(string.Empty, jTree.GetNameString());
            NUnit.Framework.Assert.AreEqual(string.Empty, jTree.GetPathString());
            NUnit.Framework.Assert.IsTrue(jTree.IsValid());
            NUnit.Framework.Assert.AreEqual(ObjectId.FromString("698dd0b8d0c299f080559a1cffc7fe029479a408"
                                                                ), jTree.GetObjectId());
            NUnit.Framework.Assert.AreEqual(cList.Count, jTree.GetEntrySpan());
            AList <DirCacheCGitCompatabilityTest.CGitLsTreeRecord> subtrees = new AList <DirCacheCGitCompatabilityTest.CGitLsTreeRecord
                                                                                         >();

            foreach (DirCacheCGitCompatabilityTest.CGitLsTreeRecord r in cTree.Values)
            {
                if (FileMode.TREE.Equals(r.mode))
                {
                    subtrees.AddItem(r);
                }
            }
            NUnit.Framework.Assert.AreEqual(subtrees.Count, jTree.GetChildCount());
            for (int i = 0; i < jTree.GetChildCount(); i++)
            {
                DirCacheTree sj = jTree.GetChild(i);
                DirCacheCGitCompatabilityTest.CGitLsTreeRecord sc = subtrees[i];
                NUnit.Framework.Assert.AreEqual(sc.path, sj.GetNameString());
                NUnit.Framework.Assert.AreEqual(sc.path + "/", sj.GetPathString());
                NUnit.Framework.Assert.IsTrue(sj.IsValid());
                NUnit.Framework.Assert.AreEqual(sc.id, sj.GetObjectId());
            }
        }
Example #18
0
 internal DirCacheBuildIterator(NGit.Dircache.DirCacheBuildIterator p, DirCacheTree
                                dct) : base(p, dct)
 {
     builder = p.builder;
 }
Example #19
0
        /// <exception cref="System.IO.IOException"></exception>
        /// <exception cref="NGit.Errors.CorruptObjectException"></exception>
        private void ReadFrom(InputStream inStream)
        {
            BufferedInputStream @in = new BufferedInputStream(inStream);
            MessageDigest       md  = Constants.NewMessageDigest();

            // Read the index header and verify we understand it.
            //
            byte[] hdr = new byte[20];
            IOUtil.ReadFully(@in, hdr, 0, 12);
            md.Update(hdr, 0, 12);
            if (!Is_DIRC(hdr))
            {
                throw new CorruptObjectException(JGitText.Get().notADIRCFile);
            }
            int  ver      = NB.DecodeInt32(hdr, 4);
            bool extended = false;

            if (ver == 3)
            {
                extended = true;
            }
            else
            {
                if (ver != 2)
                {
                    throw new CorruptObjectException(MessageFormat.Format(JGitText.Get().unknownDIRCVersion
                                                                          , ver));
                }
            }
            entryCnt = NB.DecodeInt32(hdr, 8);
            if (entryCnt < 0)
            {
                throw new CorruptObjectException(JGitText.Get().DIRCHasTooManyEntries);
            }
            // Load the individual file entries.
            //
            int infoLength = DirCacheEntry.GetMaximumInfoLength(extended);

            byte[] infos = new byte[infoLength * entryCnt];
            sortedEntries = new DirCacheEntry[entryCnt];
            MutableInteger infoAt = new MutableInteger();

            for (int i = 0; i < entryCnt; i++)
            {
                sortedEntries[i] = new DirCacheEntry(infos, infoAt, @in, md);
            }
            snapshot = FileSnapshot.Save(liveFile);
            // After the file entries are index extensions, and then a footer.
            //
            for (; ;)
            {
                @in.Mark(21);
                IOUtil.ReadFully(@in, hdr, 0, 20);
                if (@in.Read() < 0)
                {
                    // No extensions present; the file ended where we expected.
                    //
                    break;
                }
                @in.Reset();
                md.Update(hdr, 0, 8);
                IOUtil.SkipFully(@in, 8);
                long sz = NB.DecodeUInt32(hdr, 4);
                switch (NB.DecodeInt32(hdr, 0))
                {
                case EXT_TREE:
                {
                    if (int.MaxValue < sz)
                    {
                        throw new CorruptObjectException(MessageFormat.Format(JGitText.Get().DIRCExtensionIsTooLargeAt
                                                                              , FormatExtensionName(hdr), sz));
                    }
                    byte[] raw = new byte[(int)sz];
                    IOUtil.ReadFully(@in, raw, 0, raw.Length);
                    md.Update(raw, 0, raw.Length);
                    tree = new DirCacheTree(raw, new MutableInteger(), null);
                    break;
                }

                default:
                {
                    if (hdr[0] >= 'A' && ((sbyte)hdr[0]) <= 'Z')
                    {
                        // The extension is optional and is here only as
                        // a performance optimization. Since we do not
                        // understand it, we can safely skip past it, after
                        // we include its data in our checksum.
                        //
                        SkipOptionalExtension(@in, md, hdr, sz);
                    }
                    else
                    {
                        // The extension is not an optimization and is
                        // _required_ to understand this index format.
                        // Since we did not trap it above we must abort.
                        //
                        throw new CorruptObjectException(MessageFormat.Format(JGitText.Get().DIRCExtensionNotSupportedByThisVersion
                                                                              , FormatExtensionName(hdr)));
                    }
                    break;
                }
                }
            }
            byte[] exp = md.Digest();
            if (!Arrays.Equals(exp, hdr))
            {
                throw new CorruptObjectException(JGitText.Get().DIRCChecksumMismatch);
            }
        }
        /// <summary>Update (if necessary) this tree's entrySpan.</summary>
        /// <remarks>Update (if necessary) this tree's entrySpan.</remarks>
        /// <param name="cache">the complete cache from DirCache.</param>
        /// <param name="cCnt">
        /// number of entries in <code>cache</code> that are valid for
        /// iteration.
        /// </param>
        /// <param name="cIdx">
        /// first position of <code>cache</code> that is a member of this
        /// tree. The path of <code>cache[cacheIdx].path</code> for the
        /// range <code>[0,pathOff-1)</code> matches the complete path of
        /// this tree, from the root of the repository.
        /// </param>
        /// <param name="pathOff">
        /// number of bytes of <code>cache[cacheIdx].path</code> that
        /// matches this tree's path. The value at array position
        /// <code>cache[cacheIdx].path[pathOff-1]</code> is always '/' if
        /// <code>pathOff</code> is &gt; 0.
        /// </param>
        internal virtual void Validate(DirCacheEntry[] cache, int cCnt, int cIdx, int pathOff
                                       )
        {
            if (entrySpan >= 0)
            {
                // If we are valid, our children are also valid.
                // We have no need to validate them.
                //
                return;
            }
            entrySpan = 0;
            if (cCnt == 0)
            {
                // Special case of an empty index, and we are the root tree.
                //
                return;
            }
            byte[] firstPath = cache[cIdx].path;
            int    stIdx     = 0;

            while (cIdx < cCnt)
            {
                byte[] currPath = cache[cIdx].path;
                if (pathOff > 0 && !Peq(firstPath, currPath, pathOff))
                {
                    // The current entry is no longer in this tree. Our
                    // span is updated and the remainder goes elsewhere.
                    //
                    break;
                }
                NGit.Dircache.DirCacheTree st = stIdx < childCnt ? children[stIdx] : null;
                int cc = Namecmp(currPath, pathOff, st);
                if (cc > 0)
                {
                    // This subtree is now empty.
                    //
                    RemoveChild(stIdx);
                    continue;
                }
                if (cc < 0)
                {
                    int p = Slash(currPath, pathOff);
                    if (p < 0)
                    {
                        // The entry has no '/' and thus is directly in this
                        // tree. Count it as one of our own.
                        //
                        cIdx++;
                        entrySpan++;
                        continue;
                    }
                    // Build a new subtree for this entry.
                    //
                    st = new NGit.Dircache.DirCacheTree(this, currPath, pathOff, p - pathOff);
                    InsertChild(stIdx, st);
                }
                // The entry is contained in this subtree.
                //
                st.Validate(cache, cCnt, cIdx, pathOff + st.NameLength() + 1);
                cIdx      += st.entrySpan;
                entrySpan += st.entrySpan;
                stIdx++;
            }
            // None of our remaining children can be in this tree
            // as the current cache entry is after our own name.
            //
            while (stIdx < childCnt)
            {
                RemoveChild(childCnt - 1);
            }
        }
Example #21
0
 internal virtual void Replace(DirCacheEntry[] e, int cnt)
 {
     sortedEntries = e;
     entryCnt      = cnt;
     tree          = null;
 }