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

« back to all changes in this revision

Viewing changes to contrib/NGit/NGit.Revwalk/ObjectWalk.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.Collections.Generic;
 
45
using NGit;
 
46
using NGit.Errors;
 
47
using NGit.Revwalk;
 
48
using NGit.Treewalk;
 
49
using Sharpen;
 
50
 
 
51
namespace NGit.Revwalk
 
52
{
 
53
        /// <summary>Specialized subclass of RevWalk to include trees, blobs and tags.</summary>
 
54
        /// <remarks>
 
55
        /// Specialized subclass of RevWalk to include trees, blobs and tags.
 
56
        /// <p>
 
57
        /// Unlike RevWalk this subclass is able to remember starting roots that include
 
58
        /// annotated tags, or arbitrary trees or blobs. Once commit generation is
 
59
        /// complete and all commits have been popped by the application, individual
 
60
        /// annotated tag, tree and blob objects can be popped through the additional
 
61
        /// method
 
62
        /// <see cref="NextObject()">NextObject()</see>
 
63
        /// .
 
64
        /// <p>
 
65
        /// Tree and blob objects reachable from interesting commits are automatically
 
66
        /// scheduled for inclusion in the results of
 
67
        /// <see cref="NextObject()">NextObject()</see>
 
68
        /// , returning
 
69
        /// each object exactly once. Objects are sorted and returned according to the
 
70
        /// the commits that reference them and the order they appear within a tree.
 
71
        /// Ordering can be affected by changing the
 
72
        /// <see cref="RevSort">RevSort</see>
 
73
        /// used to order the
 
74
        /// commits that are returned first.
 
75
        /// </remarks>
 
76
        public class ObjectWalk : RevWalk
 
77
        {
 
78
                /// <summary>
 
79
                /// Indicates a non-RevCommit is in
 
80
                /// <see cref="pendingObjects">pendingObjects</see>
 
81
                /// .
 
82
                /// <p>
 
83
                /// We can safely reuse
 
84
                /// <see cref="RevWalk.REWRITE">RevWalk.REWRITE</see>
 
85
                /// here for the same value as it
 
86
                /// is only set on RevCommit and
 
87
                /// <see cref="pendingObjects">pendingObjects</see>
 
88
                /// never has RevCommit
 
89
                /// instances inserted into it.
 
90
                /// </summary>
 
91
                private const int IN_PENDING = RevWalk.REWRITE;
 
92
 
 
93
                private static readonly byte[] EMPTY_PATH = new byte[] {  };
 
94
 
 
95
                private CanonicalTreeParser treeWalk;
 
96
 
 
97
                private IList<RevObject> rootObjects;
 
98
 
 
99
                private BlockObjQueue pendingObjects;
 
100
 
 
101
                private RevTree currentTree;
 
102
 
 
103
                private RevObject last;
 
104
 
 
105
                private RevCommit firstCommit;
 
106
 
 
107
                private RevCommit lastCommit;
 
108
 
 
109
                /// <summary>Create a new revision and object walker for a given repository.</summary>
 
110
                /// <remarks>Create a new revision and object walker for a given repository.</remarks>
 
111
                /// <param name="repo">the repository the walker will obtain data from.</param>
 
112
                public ObjectWalk(Repository repo) : this(repo.NewObjectReader())
 
113
                {
 
114
                }
 
115
 
 
116
                /// <summary>Create a new revision and object walker for a given repository.</summary>
 
117
                /// <remarks>Create a new revision and object walker for a given repository.</remarks>
 
118
                /// <param name="or">
 
119
                /// the reader the walker will obtain data from. The reader should
 
120
                /// be released by the caller when the walker is no longer
 
121
                /// required.
 
122
                /// </param>
 
123
                public ObjectWalk(ObjectReader or) : base(or)
 
124
                {
 
125
                        rootObjects = new AList<RevObject>();
 
126
                        pendingObjects = new BlockObjQueue();
 
127
                        treeWalk = new CanonicalTreeParser();
 
128
                }
 
129
 
 
130
                /// <summary>Mark an object or commit to start graph traversal from.</summary>
 
131
                /// <remarks>
 
132
                /// Mark an object or commit to start graph traversal from.
 
133
                /// <p>
 
134
                /// Callers are encouraged to use
 
135
                /// <see cref="RevWalk.ParseAny(NGit.AnyObjectId)">RevWalk.ParseAny(NGit.AnyObjectId)
 
136
                ///     </see>
 
137
                /// instead of
 
138
                /// <see cref="RevWalk.LookupAny(NGit.AnyObjectId, int)">RevWalk.LookupAny(NGit.AnyObjectId, int)
 
139
                ///     </see>
 
140
                /// , as this method
 
141
                /// requires the object to be parsed before it can be added as a root for the
 
142
                /// traversal.
 
143
                /// <p>
 
144
                /// The method will automatically parse an unparsed object, but error
 
145
                /// handling may be more difficult for the application to explain why a
 
146
                /// RevObject is not actually valid. The object pool of this walker would
 
147
                /// also be 'poisoned' by the invalid RevObject.
 
148
                /// <p>
 
149
                /// This method will automatically call
 
150
                /// <see cref="RevWalk.MarkStart(RevCommit)">RevWalk.MarkStart(RevCommit)</see>
 
151
                /// if passed RevCommit instance, or a RevTag that directly (or indirectly)
 
152
                /// references a RevCommit.
 
153
                /// </remarks>
 
154
                /// <param name="o">
 
155
                /// the object to start traversing from. The object passed must be
 
156
                /// from this same revision walker.
 
157
                /// </param>
 
158
                /// <exception cref="NGit.Errors.MissingObjectException">
 
159
                /// the object supplied is not available from the object
 
160
                /// database. This usually indicates the supplied object is
 
161
                /// invalid, but the reference was constructed during an earlier
 
162
                /// invocation to
 
163
                /// <see cref="RevWalk.LookupAny(NGit.AnyObjectId, int)">RevWalk.LookupAny(NGit.AnyObjectId, int)
 
164
                ///     </see>
 
165
                /// .
 
166
                /// </exception>
 
167
                /// <exception cref="NGit.Errors.IncorrectObjectTypeException">
 
168
                /// the object was not parsed yet and it was discovered during
 
169
                /// parsing that it is not actually the type of the instance
 
170
                /// passed in. This usually indicates the caller used the wrong
 
171
                /// type in a
 
172
                /// <see cref="RevWalk.LookupAny(NGit.AnyObjectId, int)">RevWalk.LookupAny(NGit.AnyObjectId, int)
 
173
                ///     </see>
 
174
                /// call.
 
175
                /// </exception>
 
176
                /// <exception cref="System.IO.IOException">a pack file or loose object could not be read.
 
177
                ///     </exception>
 
178
                public virtual void MarkStart(RevObject o)
 
179
                {
 
180
                        while (o is RevTag)
 
181
                        {
 
182
                                AddObject(o);
 
183
                                o = ((RevTag)o).GetObject();
 
184
                                ParseHeaders(o);
 
185
                        }
 
186
                        if (o is RevCommit)
 
187
                        {
 
188
                                base.MarkStart((RevCommit)o);
 
189
                        }
 
190
                        else
 
191
                        {
 
192
                                AddObject(o);
 
193
                        }
 
194
                }
 
195
 
 
196
                /// <summary>Mark an object to not produce in the output.</summary>
 
197
                /// <remarks>
 
198
                /// Mark an object to not produce in the output.
 
199
                /// <p>
 
200
                /// Uninteresting objects denote not just themselves but also their entire
 
201
                /// reachable chain, back until the merge base of an uninteresting commit and
 
202
                /// an otherwise interesting commit.
 
203
                /// <p>
 
204
                /// Callers are encouraged to use
 
205
                /// <see cref="RevWalk.ParseAny(NGit.AnyObjectId)">RevWalk.ParseAny(NGit.AnyObjectId)
 
206
                ///     </see>
 
207
                /// instead of
 
208
                /// <see cref="RevWalk.LookupAny(NGit.AnyObjectId, int)">RevWalk.LookupAny(NGit.AnyObjectId, int)
 
209
                ///     </see>
 
210
                /// , as this method
 
211
                /// requires the object to be parsed before it can be added as a root for the
 
212
                /// traversal.
 
213
                /// <p>
 
214
                /// The method will automatically parse an unparsed object, but error
 
215
                /// handling may be more difficult for the application to explain why a
 
216
                /// RevObject is not actually valid. The object pool of this walker would
 
217
                /// also be 'poisoned' by the invalid RevObject.
 
218
                /// <p>
 
219
                /// This method will automatically call
 
220
                /// <see cref="RevWalk.MarkStart(RevCommit)">RevWalk.MarkStart(RevCommit)</see>
 
221
                /// if passed RevCommit instance, or a RevTag that directly (or indirectly)
 
222
                /// references a RevCommit.
 
223
                /// </remarks>
 
224
                /// <param name="o">the object to start traversing from. The object passed must be</param>
 
225
                /// <exception cref="NGit.Errors.MissingObjectException">
 
226
                /// the object supplied is not available from the object
 
227
                /// database. This usually indicates the supplied object is
 
228
                /// invalid, but the reference was constructed during an earlier
 
229
                /// invocation to
 
230
                /// <see cref="RevWalk.LookupAny(NGit.AnyObjectId, int)">RevWalk.LookupAny(NGit.AnyObjectId, int)
 
231
                ///     </see>
 
232
                /// .
 
233
                /// </exception>
 
234
                /// <exception cref="NGit.Errors.IncorrectObjectTypeException">
 
235
                /// the object was not parsed yet and it was discovered during
 
236
                /// parsing that it is not actually the type of the instance
 
237
                /// passed in. This usually indicates the caller used the wrong
 
238
                /// type in a
 
239
                /// <see cref="RevWalk.LookupAny(NGit.AnyObjectId, int)">RevWalk.LookupAny(NGit.AnyObjectId, int)
 
240
                ///     </see>
 
241
                /// call.
 
242
                /// </exception>
 
243
                /// <exception cref="System.IO.IOException">a pack file or loose object could not be read.
 
244
                ///     </exception>
 
245
                public virtual void MarkUninteresting(RevObject o)
 
246
                {
 
247
                        while (o is RevTag)
 
248
                        {
 
249
                                o.flags |= UNINTERESTING;
 
250
                                if (HasRevSort(RevSort.BOUNDARY))
 
251
                                {
 
252
                                        AddObject(o);
 
253
                                }
 
254
                                o = ((RevTag)o).GetObject();
 
255
                                ParseHeaders(o);
 
256
                        }
 
257
                        if (o is RevCommit)
 
258
                        {
 
259
                                base.MarkUninteresting((RevCommit)o);
 
260
                        }
 
261
                        else
 
262
                        {
 
263
                                if (o is RevTree)
 
264
                                {
 
265
                                        MarkTreeUninteresting((RevTree)o);
 
266
                                }
 
267
                                else
 
268
                                {
 
269
                                        o.flags |= UNINTERESTING;
 
270
                                }
 
271
                        }
 
272
                        if (o.Type != Constants.OBJ_COMMIT && HasRevSort(RevSort.BOUNDARY))
 
273
                        {
 
274
                                AddObject(o);
 
275
                        }
 
276
                }
 
277
 
 
278
                /// <exception cref="NGit.Errors.MissingObjectException"></exception>
 
279
                /// <exception cref="NGit.Errors.IncorrectObjectTypeException"></exception>
 
280
                /// <exception cref="System.IO.IOException"></exception>
 
281
                public override RevCommit Next()
 
282
                {
 
283
                        for (; ; )
 
284
                        {
 
285
                                RevCommit r = base.Next();
 
286
                                if (r == null)
 
287
                                {
 
288
                                        return null;
 
289
                                }
 
290
                                if ((r.flags & UNINTERESTING) != 0)
 
291
                                {
 
292
                                        MarkTreeUninteresting(r.Tree);
 
293
                                        if (HasRevSort(RevSort.BOUNDARY))
 
294
                                        {
 
295
                                                return r;
 
296
                                        }
 
297
                                        continue;
 
298
                                }
 
299
                                if (firstCommit == null)
 
300
                                {
 
301
                                        firstCommit = r;
 
302
                                }
 
303
                                lastCommit = r;
 
304
                                pendingObjects.Add(r.Tree);
 
305
                                return r;
 
306
                        }
 
307
                }
 
308
 
 
309
                /// <summary>Pop the next most recent object.</summary>
 
310
                /// <remarks>Pop the next most recent object.</remarks>
 
311
                /// <returns>next most recent object; null if traversal is over.</returns>
 
312
                /// <exception cref="NGit.Errors.MissingObjectException">
 
313
                /// one or or more of the next objects are not available from the
 
314
                /// object database, but were thought to be candidates for
 
315
                /// traversal. This usually indicates a broken link.
 
316
                /// </exception>
 
317
                /// <exception cref="NGit.Errors.IncorrectObjectTypeException">
 
318
                /// one or or more of the objects in a tree do not match the type
 
319
                /// indicated.
 
320
                /// </exception>
 
321
                /// <exception cref="System.IO.IOException">a pack file or loose object could not be read.
 
322
                ///     </exception>
 
323
                public virtual RevObject NextObject()
 
324
                {
 
325
                        if (last != null)
 
326
                        {
 
327
                                treeWalk = last is RevTree ? Enter(last) : treeWalk.Next();
 
328
                        }
 
329
                        while (!treeWalk.Eof)
 
330
                        {
 
331
                                FileMode mode = treeWalk.EntryFileMode;
 
332
                                switch (mode.GetObjectType())
 
333
                                {
 
334
                                        case Constants.OBJ_BLOB:
 
335
                                        {
 
336
                                                treeWalk.GetEntryObjectId(idBuffer);
 
337
                                                RevBlob o = LookupBlob(idBuffer);
 
338
                                                if ((o.flags & SEEN) != 0)
 
339
                                                {
 
340
                                                        break;
 
341
                                                }
 
342
                                                o.flags |= SEEN;
 
343
                                                if (ShouldSkipObject(o))
 
344
                                                {
 
345
                                                        break;
 
346
                                                }
 
347
                                                last = o;
 
348
                                                return o;
 
349
                                        }
 
350
 
 
351
                                        case Constants.OBJ_TREE:
 
352
                                        {
 
353
                                                treeWalk.GetEntryObjectId(idBuffer);
 
354
                                                RevTree o = LookupTree(idBuffer);
 
355
                                                if ((o.flags & SEEN) != 0)
 
356
                                                {
 
357
                                                        break;
 
358
                                                }
 
359
                                                o.flags |= SEEN;
 
360
                                                if (ShouldSkipObject(o))
 
361
                                                {
 
362
                                                        break;
 
363
                                                }
 
364
                                                last = o;
 
365
                                                return o;
 
366
                                        }
 
367
 
 
368
                                        default:
 
369
                                        {
 
370
                                                if (FileMode.GITLINK.Equals(mode))
 
371
                                                {
 
372
                                                        break;
 
373
                                                }
 
374
                                                treeWalk.GetEntryObjectId(idBuffer);
 
375
                                                throw new CorruptObjectException(MessageFormat.Format(JGitText.Get().corruptObjectInvalidMode3
 
376
                                                        , mode, idBuffer.Name, treeWalk.EntryPathString, currentTree.Name));
 
377
                                        }
 
378
                                }
 
379
                                treeWalk = treeWalk.Next();
 
380
                        }
 
381
                        if (firstCommit != null)
 
382
                        {
 
383
                                reader.WalkAdviceBeginTrees(this, firstCommit, lastCommit);
 
384
                                firstCommit = null;
 
385
                                lastCommit = null;
 
386
                        }
 
387
                        last = null;
 
388
                        for (; ; )
 
389
                        {
 
390
                                RevObject o = pendingObjects.Next();
 
391
                                if (o == null)
 
392
                                {
 
393
                                        reader.WalkAdviceEnd();
 
394
                                        return null;
 
395
                                }
 
396
                                if ((o.flags & SEEN) != 0)
 
397
                                {
 
398
                                        continue;
 
399
                                }
 
400
                                o.flags |= SEEN;
 
401
                                if (ShouldSkipObject(o))
 
402
                                {
 
403
                                        continue;
 
404
                                }
 
405
                                if (o is RevTree)
 
406
                                {
 
407
                                        currentTree = (RevTree)o;
 
408
                                        treeWalk = treeWalk.ResetRoot(reader, currentTree);
 
409
                                }
 
410
                                return o;
 
411
                        }
 
412
                }
 
413
 
 
414
                /// <exception cref="System.IO.IOException"></exception>
 
415
                private CanonicalTreeParser Enter(RevObject tree)
 
416
                {
 
417
                        CanonicalTreeParser p = treeWalk.CreateSubtreeIterator0(reader, tree);
 
418
                        if (p.Eof)
 
419
                        {
 
420
                                // We can't tolerate the subtree being an empty tree, as
 
421
                                // that will break us out early before we visit all names.
 
422
                                // If it is, advance to the parent's next record.
 
423
                                //
 
424
                                return treeWalk.Next();
 
425
                        }
 
426
                        return p;
 
427
                }
 
428
 
 
429
                private bool ShouldSkipObject(RevObject o)
 
430
                {
 
431
                        return (o.flags & UNINTERESTING) != 0 && !HasRevSort(RevSort.BOUNDARY);
 
432
                }
 
433
 
 
434
                /// <summary>Verify all interesting objects are available, and reachable.</summary>
 
435
                /// <remarks>
 
436
                /// Verify all interesting objects are available, and reachable.
 
437
                /// <p>
 
438
                /// Callers should populate starting points and ending points with
 
439
                /// <see cref="MarkStart(RevObject)">MarkStart(RevObject)</see>
 
440
                /// and
 
441
                /// <see cref="MarkUninteresting(RevObject)">MarkUninteresting(RevObject)</see>
 
442
                /// and then use this method to verify all objects between those two points
 
443
                /// exist in the repository and are readable.
 
444
                /// <p>
 
445
                /// This method returns successfully if everything is connected; it throws an
 
446
                /// exception if there is a connectivity problem. The exception message
 
447
                /// provides some detail about the connectivity failure.
 
448
                /// </remarks>
 
449
                /// <exception cref="NGit.Errors.MissingObjectException">
 
450
                /// one or or more of the next objects are not available from the
 
451
                /// object database, but were thought to be candidates for
 
452
                /// traversal. This usually indicates a broken link.
 
453
                /// </exception>
 
454
                /// <exception cref="NGit.Errors.IncorrectObjectTypeException">
 
455
                /// one or or more of the objects in a tree do not match the type
 
456
                /// indicated.
 
457
                /// </exception>
 
458
                /// <exception cref="System.IO.IOException">a pack file or loose object could not be read.
 
459
                ///     </exception>
 
460
                public virtual void CheckConnectivity()
 
461
                {
 
462
                        for (; ; )
 
463
                        {
 
464
                                RevCommit c = Next();
 
465
                                if (c == null)
 
466
                                {
 
467
                                        break;
 
468
                                }
 
469
                        }
 
470
                        for (; ; )
 
471
                        {
 
472
                                RevObject o = NextObject();
 
473
                                if (o == null)
 
474
                                {
 
475
                                        break;
 
476
                                }
 
477
                                if (o is RevBlob && !reader.Has(o))
 
478
                                {
 
479
                                        throw new MissingObjectException(o, Constants.TYPE_BLOB);
 
480
                                }
 
481
                        }
 
482
                }
 
483
 
 
484
                /// <summary>Get the current object's complete path.</summary>
 
485
                /// <remarks>
 
486
                /// Get the current object's complete path.
 
487
                /// <p>
 
488
                /// This method is not very efficient and is primarily meant for debugging
 
489
                /// and final output generation. Applications should try to avoid calling it,
 
490
                /// and if invoked do so only once per interesting entry, where the name is
 
491
                /// absolutely required for correct function.
 
492
                /// </remarks>
 
493
                /// <returns>
 
494
                /// complete path of the current entry, from the root of the
 
495
                /// repository. If the current entry is in a subtree there will be at
 
496
                /// least one '/' in the returned string. Null if the current entry
 
497
                /// has no path, such as for annotated tags or root level trees.
 
498
                /// </returns>
 
499
                public virtual string GetPathString()
 
500
                {
 
501
                        return last != null ? treeWalk.EntryPathString : null;
 
502
                }
 
503
 
 
504
                /// <summary>Get the current object's path hash code.</summary>
 
505
                /// <remarks>
 
506
                /// Get the current object's path hash code.
 
507
                /// <p>
 
508
                /// This method computes a hash code on the fly for this path, the hash is
 
509
                /// suitable to cluster objects that may have similar paths together.
 
510
                /// </remarks>
 
511
                /// <returns>path hash code; any integer may be returned.</returns>
 
512
                public virtual int GetPathHashCode()
 
513
                {
 
514
                        return last != null ? treeWalk.GetEntryPathHashCode() : 0;
 
515
                }
 
516
 
 
517
                /// <returns>the internal buffer holding the current path.</returns>
 
518
                public virtual byte[] GetPathBuffer()
 
519
                {
 
520
                        return last != null ? treeWalk.GetEntryPathBuffer() : EMPTY_PATH;
 
521
                }
 
522
 
 
523
                /// <returns>
 
524
                /// length of the path in
 
525
                /// <see cref="GetPathBuffer()">GetPathBuffer()</see>
 
526
                /// .
 
527
                /// </returns>
 
528
                public virtual int GetPathLength()
 
529
                {
 
530
                        return last != null ? treeWalk.GetEntryPathLength() : 0;
 
531
                }
 
532
 
 
533
                public override void Dispose()
 
534
                {
 
535
                        base.Dispose();
 
536
                        pendingObjects = new BlockObjQueue();
 
537
                        treeWalk = new CanonicalTreeParser();
 
538
                        currentTree = null;
 
539
                        last = null;
 
540
                        firstCommit = null;
 
541
                        lastCommit = null;
 
542
                }
 
543
 
 
544
                protected internal override void Reset(int retainFlags)
 
545
                {
 
546
                        base.Reset(retainFlags);
 
547
                        foreach (RevObject obj in rootObjects)
 
548
                        {
 
549
                                obj.flags &= ~IN_PENDING;
 
550
                        }
 
551
                        rootObjects = new AList<RevObject>();
 
552
                        pendingObjects = new BlockObjQueue();
 
553
                        treeWalk = new CanonicalTreeParser();
 
554
                        currentTree = null;
 
555
                        last = null;
 
556
                        firstCommit = null;
 
557
                        lastCommit = null;
 
558
                }
 
559
 
 
560
                private void AddObject(RevObject o)
 
561
                {
 
562
                        if ((o.flags & IN_PENDING) == 0)
 
563
                        {
 
564
                                o.flags |= IN_PENDING;
 
565
                                rootObjects.AddItem(o);
 
566
                                pendingObjects.Add(o);
 
567
                        }
 
568
                }
 
569
 
 
570
                /// <exception cref="NGit.Errors.MissingObjectException"></exception>
 
571
                /// <exception cref="NGit.Errors.IncorrectObjectTypeException"></exception>
 
572
                /// <exception cref="System.IO.IOException"></exception>
 
573
                private void MarkTreeUninteresting(RevTree tree)
 
574
                {
 
575
                        if ((tree.flags & UNINTERESTING) != 0)
 
576
                        {
 
577
                                return;
 
578
                        }
 
579
                        tree.flags |= UNINTERESTING;
 
580
                        treeWalk = treeWalk.ResetRoot(reader, tree);
 
581
                        while (!treeWalk.Eof)
 
582
                        {
 
583
                                FileMode mode = treeWalk.EntryFileMode;
 
584
                                int sType = mode.GetObjectType();
 
585
                                switch (sType)
 
586
                                {
 
587
                                        case Constants.OBJ_BLOB:
 
588
                                        {
 
589
                                                treeWalk.GetEntryObjectId(idBuffer);
 
590
                                                LookupBlob(idBuffer).flags |= UNINTERESTING;
 
591
                                                break;
 
592
                                        }
 
593
 
 
594
                                        case Constants.OBJ_TREE:
 
595
                                        {
 
596
                                                treeWalk.GetEntryObjectId(idBuffer);
 
597
                                                RevTree t = LookupTree(idBuffer);
 
598
                                                if ((t.flags & UNINTERESTING) == 0)
 
599
                                                {
 
600
                                                        t.flags |= UNINTERESTING;
 
601
                                                        treeWalk = treeWalk.CreateSubtreeIterator0(reader, t);
 
602
                                                        continue;
 
603
                                                }
 
604
                                                break;
 
605
                                        }
 
606
 
 
607
                                        default:
 
608
                                        {
 
609
                                                if (FileMode.GITLINK.Equals(mode))
 
610
                                                {
 
611
                                                        break;
 
612
                                                }
 
613
                                                treeWalk.GetEntryObjectId(idBuffer);
 
614
                                                throw new CorruptObjectException(MessageFormat.Format(JGitText.Get().corruptObjectInvalidMode3
 
615
                                                        , mode, idBuffer.Name, treeWalk.EntryPathString, tree));
 
616
                                        }
 
617
                                }
 
618
                                treeWalk = treeWalk.Next();
 
619
                        }
 
620
                }
 
621
        }
 
622
}