~ubuntu-branches/ubuntu/oneiric/monodevelop/oneiric

« back to all changes in this revision

Viewing changes to contrib/NGit/NGit.Dircache/DirCacheIterator.cs

  • Committer: Bazaar Package Importer
  • Author(s): Jo Shields
  • Date: 2011-06-27 17:03:13 UTC
  • mto: (1.8.1 upstream)
  • mto: This revision was merged to the branch mainline in revision 54.
  • Revision ID: james.westby@ubuntu.com-20110627170313-6cvz3s19x6e9hqe9
ImportĀ upstreamĀ versionĀ 2.5.92+dfsg

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/*
 
2
This code is derived from jgit (http://eclipse.org/jgit).
 
3
Copyright owners are documented in jgit's IP log.
 
4
 
 
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
 
9
 
 
10
All rights reserved.
 
11
 
 
12
Redistribution and use in source and binary forms, with or
 
13
without modification, are permitted provided that the following
 
14
conditions are met:
 
15
 
 
16
- Redistributions of source code must retain the above copyright
 
17
  notice, this list of conditions and the following disclaimer.
 
18
 
 
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.
 
23
 
 
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
 
27
  written permission.
 
28
 
 
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.
 
42
*/
 
43
 
 
44
using System;
 
45
using NGit;
 
46
using NGit.Dircache;
 
47
using NGit.Errors;
 
48
using NGit.Treewalk;
 
49
using Sharpen;
 
50
 
 
51
namespace NGit.Dircache
 
52
{
 
53
        /// <summary>
 
54
        /// Iterate a
 
55
        /// <see cref="DirCache">DirCache</see>
 
56
        /// as part of a <code>TreeWalk</code>.
 
57
        /// <p>
 
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.
 
63
        /// </summary>
 
64
        /// <seealso cref="NGit.Treewalk.TreeWalk">NGit.Treewalk.TreeWalk</seealso>
 
65
        public class DirCacheIterator : AbstractTreeIterator
 
66
        {
 
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;
 
70
 
 
71
                /// <summary>The tree this iterator is walking.</summary>
 
72
                /// <remarks>The tree this iterator is walking.</remarks>
 
73
                private readonly DirCacheTree tree;
 
74
 
 
75
                /// <summary>First position in this tree.</summary>
 
76
                /// <remarks>First position in this tree.</remarks>
 
77
                private readonly int treeStart;
 
78
 
 
79
                /// <summary>Last position in this tree.</summary>
 
80
                /// <remarks>Last position in this tree.</remarks>
 
81
                private readonly int treeEnd;
 
82
 
 
83
                /// <summary>
 
84
                /// Special buffer to hold the ObjectId of
 
85
                /// <see cref="currentSubtree">currentSubtree</see>
 
86
                /// .
 
87
                /// </summary>
 
88
                private readonly byte[] subtreeId;
 
89
 
 
90
                /// <summary>
 
91
                /// Index of entry within
 
92
                /// <see cref="cache">cache</see>
 
93
                /// .
 
94
                /// </summary>
 
95
                protected internal int ptr;
 
96
 
 
97
                /// <summary>
 
98
                /// Next subtree to consider within
 
99
                /// <see cref="tree">tree</see>
 
100
                /// .
 
101
                /// </summary>
 
102
                private int nextSubtreePos;
 
103
 
 
104
                /// <summary>
 
105
                /// The current file entry from
 
106
                /// <see cref="cache">cache</see>
 
107
                /// .
 
108
                /// </summary>
 
109
                protected internal DirCacheEntry currentEntry;
 
110
 
 
111
                /// <summary>
 
112
                /// The subtree containing
 
113
                /// <see cref="currentEntry">currentEntry</see>
 
114
                /// if this is first entry.
 
115
                /// </summary>
 
116
                protected internal DirCacheTree currentSubtree;
 
117
 
 
118
                /// <summary>Create a new iterator for an already loaded DirCache instance.</summary>
 
119
                /// <remarks>
 
120
                /// Create a new iterator for an already loaded DirCache instance.
 
121
                /// <p>
 
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
 
124
                /// iterator.
 
125
                /// </remarks>
 
126
                /// <param name="dc">the cache to walk. It must be already loaded into memory.</param>
 
127
                public DirCacheIterator(DirCache dc)
 
128
                {
 
129
                        cache = dc;
 
130
                        tree = dc.GetCacheTree(true);
 
131
                        treeStart = 0;
 
132
                        treeEnd = tree.GetEntrySpan();
 
133
                        subtreeId = new byte[Constants.OBJECT_ID_LENGTH];
 
134
                        if (!Eof)
 
135
                        {
 
136
                                ParseEntry();
 
137
                        }
 
138
                }
 
139
 
 
140
                internal DirCacheIterator(NGit.Dircache.DirCacheIterator p, DirCacheTree dct) : base
 
141
                        (p, p.path, p.pathLen + 1)
 
142
                {
 
143
                        cache = p.cache;
 
144
                        tree = dct;
 
145
                        treeStart = p.ptr;
 
146
                        treeEnd = treeStart + tree.GetEntrySpan();
 
147
                        subtreeId = p.subtreeId;
 
148
                        ptr = p.ptr;
 
149
                        ParseEntry();
 
150
                }
 
151
 
 
152
                /// <exception cref="NGit.Errors.IncorrectObjectTypeException"></exception>
 
153
                /// <exception cref="System.IO.IOException"></exception>
 
154
                public override AbstractTreeIterator CreateSubtreeIterator(ObjectReader reader)
 
155
                {
 
156
                        if (currentSubtree == null)
 
157
                        {
 
158
                                throw new IncorrectObjectTypeException(EntryObjectId, Constants.TYPE_TREE);
 
159
                        }
 
160
                        return new NGit.Dircache.DirCacheIterator(this, currentSubtree);
 
161
                }
 
162
 
 
163
                public override EmptyTreeIterator CreateEmptyTreeIterator()
 
164
                {
 
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);
 
169
                }
 
170
 
 
171
                public override bool HasId
 
172
                {
 
173
                        get
 
174
                        {
 
175
                                if (currentSubtree != null)
 
176
                                {
 
177
                                        return currentSubtree.IsValid();
 
178
                                }
 
179
                                return currentEntry != null;
 
180
                        }
 
181
                }
 
182
 
 
183
                public override byte[] IdBuffer
 
184
                {
 
185
                        get
 
186
                        {
 
187
                                if (currentSubtree != null)
 
188
                                {
 
189
                                        return currentSubtree.IsValid() ? subtreeId : zeroid;
 
190
                                }
 
191
                                if (currentEntry != null)
 
192
                                {
 
193
                                        return currentEntry.IdBuffer;
 
194
                                }
 
195
                                return zeroid;
 
196
                        }
 
197
                }
 
198
 
 
199
                public override int IdOffset
 
200
                {
 
201
                        get
 
202
                        {
 
203
                                if (currentSubtree != null)
 
204
                                {
 
205
                                        return 0;
 
206
                                }
 
207
                                if (currentEntry != null)
 
208
                                {
 
209
                                        return currentEntry.IdOffset;
 
210
                                }
 
211
                                return 0;
 
212
                        }
 
213
                }
 
214
 
 
215
                public override void Reset()
 
216
                {
 
217
                        if (!First)
 
218
                        {
 
219
                                ptr = treeStart;
 
220
                                if (!Eof)
 
221
                                {
 
222
                                        ParseEntry();
 
223
                                }
 
224
                        }
 
225
                }
 
226
 
 
227
                public override bool First
 
228
                {
 
229
                        get
 
230
                        {
 
231
                                return ptr == treeStart;
 
232
                        }
 
233
                }
 
234
 
 
235
                public override bool Eof
 
236
                {
 
237
                        get
 
238
                        {
 
239
                                return ptr == treeEnd;
 
240
                        }
 
241
                }
 
242
 
 
243
                public override void Next(int delta)
 
244
                {
 
245
                        while (--delta >= 0)
 
246
                        {
 
247
                                if (currentSubtree != null)
 
248
                                {
 
249
                                        ptr += currentSubtree.GetEntrySpan();
 
250
                                }
 
251
                                else
 
252
                                {
 
253
                                        ptr++;
 
254
                                }
 
255
                                if (Eof)
 
256
                                {
 
257
                                        break;
 
258
                                }
 
259
                                ParseEntry();
 
260
                        }
 
261
                }
 
262
 
 
263
                public override void Back(int delta)
 
264
                {
 
265
                        while (--delta >= 0)
 
266
                        {
 
267
                                if (currentSubtree != null)
 
268
                                {
 
269
                                        nextSubtreePos--;
 
270
                                }
 
271
                                ptr--;
 
272
                                ParseEntry();
 
273
                                if (currentSubtree != null)
 
274
                                {
 
275
                                        ptr -= currentSubtree.GetEntrySpan() - 1;
 
276
                                }
 
277
                        }
 
278
                }
 
279
 
 
280
                private void ParseEntry()
 
281
                {
 
282
                        currentEntry = cache.GetEntry(ptr);
 
283
                        byte[] cep = currentEntry.path;
 
284
                        if (nextSubtreePos != tree.GetChildCount())
 
285
                        {
 
286
                                DirCacheTree s = tree.GetChild(nextSubtreePos);
 
287
                                if (s.Contains(cep, pathOffset, cep.Length))
 
288
                                {
 
289
                                        // The current position is the first file of this subtree.
 
290
                                        // Use the subtree instead as the current position.
 
291
                                        //
 
292
                                        currentSubtree = s;
 
293
                                        nextSubtreePos++;
 
294
                                        if (s.IsValid())
 
295
                                        {
 
296
                                                s.GetObjectId().CopyRawTo(subtreeId, 0);
 
297
                                        }
 
298
                                        mode = FileMode.TREE.GetBits();
 
299
                                        path = cep;
 
300
                                        pathLen = pathOffset + s.NameLength();
 
301
                                        return;
 
302
                                }
 
303
                        }
 
304
                        // The current position is a file/symlink/gitlink so we
 
305
                        // do not have a subtree located here.
 
306
                        //
 
307
                        mode = currentEntry.RawMode;
 
308
                        path = cep;
 
309
                        pathLen = cep.Length;
 
310
                        currentSubtree = null;
 
311
                }
 
312
 
 
313
                /// <summary>Get the DirCacheEntry for the current file.</summary>
 
314
                /// <remarks>Get the DirCacheEntry for the current file.</remarks>
 
315
                /// <returns>
 
316
                /// the current cache entry, if this iterator is positioned on a
 
317
                /// non-tree.
 
318
                /// </returns>
 
319
                public virtual DirCacheEntry GetDirCacheEntry()
 
320
                {
 
321
                        return currentSubtree == null ? currentEntry : null;
 
322
                }
 
323
        }
 
324
}