예제 #1
0
파일: DirCache.cs 프로젝트: gilran/GitSharp
 public void replace(DirCacheEntry[] e, int cnt)
 {
     sortedEntries = e;
     entryCnt = cnt;
     tree = null;
 }
예제 #2
0
파일: DirCache.cs 프로젝트: gilran/GitSharp
 /** Empty this index, removing all entries. */
 public void clear()
 {
     lastModified = DateTime.MinValue;
     sortedEntries = NO_ENTRIES;
     entryCnt = 0;
     tree = null;
 }
예제 #3
0
        private void insertChild(int stIdx, DirCacheTree st)
        {
            DirCacheTree[] c = children;
            if (childCnt + 1 <= c.Length)
            {
                if (stIdx < childCnt)
                    Array.Copy(c, stIdx, c, stIdx + 1, childCnt - stIdx);
                c[stIdx] = st;
                childCnt++;
                return;
            }

            int n = c.Length;
            DirCacheTree[] a = new DirCacheTree[n + 1];
            if (stIdx > 0)
                Array.Copy(c, 0, a, 0, stIdx);
            a[stIdx] = st;
            if (stIdx < n)
                Array.Copy(c, stIdx, a, stIdx + 1, n - stIdx);
            children = a;
            childCnt++;
        }
예제 #4
0
 private static int namecmp(byte[] a, int aPos, 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] & 0xff) - (b[bPos] & 0xff);
         if (cmp != 0)
             return cmp;
     }
     if (bPos == bLen)
         return a[aPos] == '/' ? 0 : -1;
     return aLen - bLen;
 }
예제 #5
0
        public DirCacheTree(byte[] @in, MutableInteger off,
                 DirCacheTree myParent)
        {
            parent = myParent;

            int ptr = RawParseUtils.next(@in, off.value, (byte)'\0');
            int nameLen = ptr - off.value - 1;
            if (nameLen > 0)
            {
                encodedName = new byte[nameLen];
                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, (byte)'\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 DirCacheTree[subcnt];
                for (int i = 0; i < subcnt; i++)
                {
                    children[i] = new 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(children[i - 1], children[i]) > 0)
                        alreadySorted = false;
                }
                if (!alreadySorted)
                    Array.Sort(children, TREE_CMP);
            }
            else
            {
                // Leaf level trees have no children, only (file) entries.
                //
                children = NO_CHILDREN;
            }
            childCnt = subcnt;
        }
예제 #6
0
        /**
         * Update (if necessary) this tree's entrySpan.
         *
         * @param cache
         *            the complete cache from DirCache.
         * @param cCnt
         *            number of entries in <code>cache</code> that are valid for
         *            iteration.
         * @param 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 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 > 0.
         */
        public 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;
                }

                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 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++;
            }

            if (stIdx < childCnt)
            {
                // None of our remaining children can be in this tree
                // as the current cache entry is after our own name.
                //
                DirCacheTree[] dct = new DirCacheTree[stIdx];
                Array.Copy(children, 0, dct, 0, stIdx);
                children = dct;
            }
        }
예제 #7
0
		/// <summary>
		/// Obtain (or build) the current cache tree structure.
		/// <para />
		/// This method can optionally recreate the cache tree, without flushing the
		/// tree objects themselves to disk.
		/// </summary>
		///	<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 <paramref name="build"/> was false.
		/// </returns>
		public DirCacheTree getCacheTree(bool build)
		{
			if (build)
			{
				if (_cacheTree == null)
				{
					_cacheTree = new DirCacheTree();
				}
				_cacheTree.validate(_sortedEntries, _entryCnt, 0, 0);
			}
			return _cacheTree;
		}
예제 #8
0
 public DirCacheIterator(DirCacheIterator parentIterator, DirCacheTree cacheTree)
     : base(parentIterator, parentIterator.Path, parentIterator.PathLen + 1)
 {
     Cache = parentIterator.Cache;
     Tree = cacheTree;
     TreeStart = parentIterator._pointer;
     TreeEnd = TreeStart + Tree.getEntrySpan();
     SubtreeId = parentIterator.SubtreeId;
     _pointer = parentIterator._pointer;
     ParseEntry();
 }
예제 #9
0
		public void replace(DirCacheEntry[] e, int cnt)
		{
			_sortedEntries = e;
			_entryCnt = cnt;
			_cacheTree = null;
		}
예제 #10
0
		/// <summary>
		/// Empty this index, removing all entries.
		/// </summary>
		public void clear()
		{
			_lastModified = DateTime.MinValue;
			_sortedEntries = NoEntries;
			_entryCnt = 0;
			_cacheTree = null;
		}
예제 #11
0
		private void InsertChild(int stIdx, DirCacheTree st)
		{
			DirCacheTree[] c = _children;
			if (_childCount + 1 <= c.Length)
			{
				if (stIdx < _childCount)
				{
					Array.Copy(c, stIdx, c, stIdx + 1, _childCount - stIdx);
				}
				c[stIdx] = st;
				_childCount++;
				return;
			}

			int n = c.Length;
			var a = new DirCacheTree[n + 1];
			if (stIdx > 0)
			{
				Array.Copy(c, 0, a, 0, stIdx);
			}
			a[stIdx] = st;
			if (stIdx < n)
			{
				Array.Copy(c, stIdx, a, stIdx + 1, n - stIdx);
			}
			_children = a;
			_childCount++;
		}
예제 #12
0
		private DirCacheTree(DirCacheTree myParent, byte[] path, int pathOff, int pathLen)
		{
			_parent = myParent;
			_encodedName = new byte[pathLen];
			Array.Copy(path, pathOff, _encodedName, 0, pathLen);
			_children = NoChildren;
			_childCount = 0;
			_entrySpan = -1;
		}
예제 #13
0
 /// <summary>
 /// Create a new iterator for an already loaded <see cref="DirCache"/> instance.
 /// <para/>
 /// 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.
 /// </summary>
 /// <param name="parentIterator">The parent iterator</param>
 /// <param name="cacheTree">The cache tree</param>
 DirCacheBuildIterator(DirCacheBuildIterator parentIterator, DirCacheTree cacheTree)
     : base(parentIterator, cacheTree)
 {
     _builder = parentIterator._builder;
 }
예제 #14
0
파일: DirCache.cs 프로젝트: gilran/GitSharp
        private void readFrom(FileStream inStream)
        {
            var @in = new StreamReader(inStream);
            MessageDigest md = Constants.newMessageDigest();

            // Read the index header and verify we understand it.
            //
            byte[] hdr = new byte[20];
            NB.ReadFully(inStream, hdr, 0, 12);
            md.Update(hdr, 0, 12);
            if (!is_DIRC(hdr))
                throw new CorruptObjectException("Not a DIRC file.");
            int ver = NB.decodeInt32(hdr, 4);
            if (ver != 2)
                throw new CorruptObjectException("Unknown DIRC version " + ver);
            entryCnt = NB.decodeInt32(hdr, 8);
            if (entryCnt < 0)
                throw new CorruptObjectException("DIRC has too many entries.");

            // Load the individual file entries.
            //
            byte[] infos = new byte[INFO_LEN * entryCnt];
            sortedEntries = new DirCacheEntry[entryCnt];
            for (int i = 0; i < entryCnt; i++)
                sortedEntries[i] = new DirCacheEntry(infos, i * INFO_LEN, inStream, md);
            lastModified = liveFile.LastAccessTime;

            // After the file entries are index extensions, and then a footer.
            //
            for (; ; )
            {
                var pos = inStream.Position;
                NB.ReadFully(inStream, hdr, 0, 20);
                if (@in.Read() < 0)
                {
                    // No extensions present; the file ended where we expected.
                    //
                    break;
                }
                inStream.Seek(pos, SeekOrigin.Begin);

                switch (NB.decodeInt32(hdr, 0))
                {
                    case EXT_TREE:
                        {
                            byte[] raw = new byte[NB.decodeInt32(hdr, 4)];
                            md.Update(hdr, 0, 8);
                            NB.skipFully(inStream, 8);
                            NB.ReadFully(inStream, raw, 0, raw.Length);
                            md.Update(raw, 0, raw.Length);
                            tree = new DirCacheTree(raw, new MutableInteger(), null);
                            break;
                        }
                    default:
                        if (hdr[0] >= (byte)'A' && hdr[0] <= (byte)'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.
                            //
                            NB.skipFully(inStream, NB.decodeUInt32(hdr, 4));
                        }
                        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("DIRC extension '"
                                    + Constants.CHARSET.GetString(hdr.Take(4).ToArray())
                                    + "' not supported by this version.");
                        }
                        break;
                }
            }

            byte[] exp = md.Digest();
            if (!exp.SequenceEqual( hdr))
            {
                throw new CorruptObjectException("DIRC checksum mismatch");
            }
        }
예제 #15
0
 private DirCacheTree(DirCacheTree myParent, byte[] path,                 int pathOff, int pathLen)
 {
     parent = myParent;
     encodedName = new byte[pathLen];
     Array.Copy(path, pathOff, encodedName, 0, pathLen);
     children = NO_CHILDREN;
     childCnt = 0;
     entrySpan = -1;
 }
예제 #16
0
파일: DirCache.cs 프로젝트: gilran/GitSharp
 /**
  * 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.
  *
  * @param build
  *            if true and the cache tree is not present in the index it will
  *            be generated and returned to the caller.
  * @return the cache tree; null if there is no current cache tree available
  *         and <code>build</code> was false.
  */
 public DirCacheTree getCacheTree(bool build)
 {
     if (build)
     {
         if (tree == null)
             tree = new DirCacheTree();
         tree.validate(sortedEntries, entryCnt, 0, 0);
     }
     return tree;
 }
예제 #17
0
        private void ParseEntry()
        {
            _currentEntry = Cache.getEntry(_pointer);
            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);
                    }
                    else
                    {
                        SubtreeId.Fill((byte)0);
                    }

                    Mode = FileMode.Tree.Bits;

                    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.getRawMode();
            Path = cep;
            PathLen = cep.Length;
            _currentSubtree = null;
        }