2
This code is derived from jgit (http://eclipse.org/jgit).
3
Copyright owners are documented in jgit's IP log.
5
This program and the accompanying materials are made available
6
under the terms of the Eclipse Distribution License v1.0 which
7
accompanies this distribution, is reproduced below, and is
8
available at http://www.eclipse.org/org/documents/edl-v10.php
12
Redistribution and use in source and binary forms, with or
13
without modification, are permitted provided that the following
16
- Redistributions of source code must retain the above copyright
17
notice, this list of conditions and the following disclaimer.
19
- Redistributions in binary form must reproduce the above
20
copyright notice, this list of conditions and the following
21
disclaimer in the documentation and/or other materials provided
22
with the distribution.
24
- Neither the name of the Eclipse Foundation, Inc. nor the
25
names of its contributors may be used to endorse or promote
26
products derived from this software without specific prior
29
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND
30
CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES,
31
INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
32
OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
33
ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
34
CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
35
SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
36
NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
37
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
38
CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
39
STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
40
ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
41
ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
51
namespace NGit.Dircache
55
/// <see cref="DirCache">DirCache</see>
56
/// as part of a <code>TreeWalk</code>.
58
/// This is an iterator to adapt a loaded <code>DirCache</code> instance (such as
59
/// read from an existing <code>.git/index</code> file) to the tree structure
60
/// used by a <code>TreeWalk</code>, making it possible for applications to walk
61
/// over any combination of tree objects already in the object database, index
62
/// files, or working directories.
64
/// <seealso cref="NGit.Treewalk.TreeWalk">NGit.Treewalk.TreeWalk</seealso>
65
public class DirCacheIterator : AbstractTreeIterator
67
/// <summary>The cache this iterator was created to walk.</summary>
68
/// <remarks>The cache this iterator was created to walk.</remarks>
69
protected internal readonly DirCache cache;
71
/// <summary>The tree this iterator is walking.</summary>
72
/// <remarks>The tree this iterator is walking.</remarks>
73
private readonly DirCacheTree tree;
75
/// <summary>First position in this tree.</summary>
76
/// <remarks>First position in this tree.</remarks>
77
private readonly int treeStart;
79
/// <summary>Last position in this tree.</summary>
80
/// <remarks>Last position in this tree.</remarks>
81
private readonly int treeEnd;
84
/// Special buffer to hold the ObjectId of
85
/// <see cref="currentSubtree">currentSubtree</see>
88
private readonly byte[] subtreeId;
91
/// Index of entry within
92
/// <see cref="cache">cache</see>
95
protected internal int ptr;
98
/// Next subtree to consider within
99
/// <see cref="tree">tree</see>
102
private int nextSubtreePos;
105
/// The current file entry from
106
/// <see cref="cache">cache</see>
109
protected internal DirCacheEntry currentEntry;
112
/// The subtree containing
113
/// <see cref="currentEntry">currentEntry</see>
114
/// if this is first entry.
116
protected internal DirCacheTree currentSubtree;
118
/// <summary>Create a new iterator for an already loaded DirCache instance.</summary>
120
/// Create a new iterator for an already loaded DirCache instance.
122
/// The iterator implementation may copy part of the cache's data during
123
/// construction, so the cache must be read in prior to creating the
126
/// <param name="dc">the cache to walk. It must be already loaded into memory.</param>
127
public DirCacheIterator(DirCache dc)
130
tree = dc.GetCacheTree(true);
132
treeEnd = tree.GetEntrySpan();
133
subtreeId = new byte[Constants.OBJECT_ID_LENGTH];
140
internal DirCacheIterator(NGit.Dircache.DirCacheIterator p, DirCacheTree dct) : base
141
(p, p.path, p.pathLen + 1)
146
treeEnd = treeStart + tree.GetEntrySpan();
147
subtreeId = p.subtreeId;
152
/// <exception cref="NGit.Errors.IncorrectObjectTypeException"></exception>
153
/// <exception cref="System.IO.IOException"></exception>
154
public override AbstractTreeIterator CreateSubtreeIterator(ObjectReader reader)
156
if (currentSubtree == null)
158
throw new IncorrectObjectTypeException(EntryObjectId, Constants.TYPE_TREE);
160
return new NGit.Dircache.DirCacheIterator(this, currentSubtree);
163
public override EmptyTreeIterator CreateEmptyTreeIterator()
165
byte[] n = new byte[Math.Max(pathLen + 1, DEFAULT_PATH_SIZE)];
166
System.Array.Copy(path, 0, n, 0, pathLen);
167
n[pathLen] = (byte)('/');
168
return new EmptyTreeIterator(this, n, pathLen + 1);
171
public override bool HasId
175
if (currentSubtree != null)
177
return currentSubtree.IsValid();
179
return currentEntry != null;
183
public override byte[] IdBuffer
187
if (currentSubtree != null)
189
return currentSubtree.IsValid() ? subtreeId : zeroid;
191
if (currentEntry != null)
193
return currentEntry.IdBuffer;
199
public override int IdOffset
203
if (currentSubtree != null)
207
if (currentEntry != null)
209
return currentEntry.IdOffset;
215
public override void Reset()
227
public override bool First
231
return ptr == treeStart;
235
public override bool Eof
239
return ptr == treeEnd;
243
public override void Next(int delta)
247
if (currentSubtree != null)
249
ptr += currentSubtree.GetEntrySpan();
263
public override void Back(int delta)
267
if (currentSubtree != null)
273
if (currentSubtree != null)
275
ptr -= currentSubtree.GetEntrySpan() - 1;
280
private void ParseEntry()
282
currentEntry = cache.GetEntry(ptr);
283
byte[] cep = currentEntry.path;
284
if (nextSubtreePos != tree.GetChildCount())
286
DirCacheTree s = tree.GetChild(nextSubtreePos);
287
if (s.Contains(cep, pathOffset, cep.Length))
289
// The current position is the first file of this subtree.
290
// Use the subtree instead as the current position.
296
s.GetObjectId().CopyRawTo(subtreeId, 0);
298
mode = FileMode.TREE.GetBits();
300
pathLen = pathOffset + s.NameLength();
304
// The current position is a file/symlink/gitlink so we
305
// do not have a subtree located here.
307
mode = currentEntry.RawMode;
309
pathLen = cep.Length;
310
currentSubtree = null;
313
/// <summary>Get the DirCacheEntry for the current file.</summary>
314
/// <remarks>Get the DirCacheEntry for the current file.</remarks>
316
/// the current cache entry, if this iterator is positioned on a
319
public virtual DirCacheEntry GetDirCacheEntry()
321
return currentSubtree == null ? currentEntry : null;