2 * Copyright (C) 2008, Shawn O. Pearce <spearce@spearce.org>
6 * Redistribution and use in source and binary forms, with or
7 * without modification, are permitted provided that the following
10 * - Redistributions of source code must retain the above copyright
11 * notice, this list of conditions and the following disclaimer.
13 * - Redistributions in binary form must reproduce the above
14 * copyright notice, this list of conditions and the following
15 * disclaimer in the documentation and/or other materials provided
16 * with the distribution.
18 * - Neither the name of the Git Development Community nor the
19 * names of its contributors may be used to endorse or promote
20 * products derived from this software without specific prior
23 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND
24 * CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES,
25 * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
26 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
27 * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
28 * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
29 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
30 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
31 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
32 * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
33 * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
34 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
35 * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
38 package org
.spearce
.jgit
.revwalk
;
40 import java
.io
.IOException
;
42 import org
.spearce
.jgit
.errors
.IncorrectObjectTypeException
;
43 import org
.spearce
.jgit
.errors
.MissingObjectException
;
44 import org
.spearce
.jgit
.errors
.StopWalkException
;
45 import org
.spearce
.jgit
.lib
.ObjectId
;
46 import org
.spearce
.jgit
.revwalk
.filter
.RevFilter
;
49 * Default (and first pass) RevCommit Generator implementation for RevWalk.
51 * This generator starts from a set of one or more commits and process them in
52 * descending (newest to oldest) commit time order. Commits automatically cause
53 * their parents to be enqueued for further processing, allowing the entire
54 * commit graph to be walked. A {@link RevFilter} may be used to select a subset
55 * of the commits and return them to the caller.
57 class PendingGenerator
extends Generator
{
58 private static final int PARSED
= RevWalk
.PARSED
;
60 private static final int SEEN
= RevWalk
.SEEN
;
62 private static final int UNINTERESTING
= RevWalk
.UNINTERESTING
;
65 * Number of additional commits to scan after we think we are done.
67 * This small buffer of commits is scanned to ensure we didn't miss anything
68 * as a result of clock skew when the commits were made. We need to set our
69 * constant to 1 additional commit due to the use of a pre-increment
70 * operator when accessing the value.
72 static final int OVER_SCAN
= 5 + 1;
74 /** A commit near the end of time, to initialize {@link #last} with. */
75 private static final RevCommit INIT_LAST
;
78 INIT_LAST
= new RevCommit(ObjectId
.zeroId());
79 INIT_LAST
.commitTime
= Integer
.MAX_VALUE
;
82 private final RevWalk walker
;
84 private final DateRevQueue pending
;
86 private final RevFilter filter
;
88 private final int output
;
90 /** Last commit produced to the caller from {@link #next()}. */
91 private RevCommit last
= INIT_LAST
;
94 * Number of commits we have remaining in our over-scan allotment.
96 * Only relevant if there are {@link #UNINTERESTING} commits in the
97 * {@link #pending} queue.
99 private int overScan
= OVER_SCAN
;
103 PendingGenerator(final RevWalk w
, final DateRevQueue p
,
104 final RevFilter f
, final int out
) {
114 return output
| SORT_COMMIT_TIME_DESC
;
118 RevCommit
next() throws MissingObjectException
,
119 IncorrectObjectTypeException
, IOException
{
122 final RevCommit c
= pending
.next();
124 walker
.curs
.release();
128 final boolean produce
;
129 if ((c
.flags
& UNINTERESTING
) != 0)
132 produce
= filter
.include(walker
, c
);
134 for (final RevCommit p
: c
.parents
) {
135 if ((p
.flags
& SEEN
) != 0)
137 if ((p
.flags
& PARSED
) == 0)
142 walker
.carryFlagsImpl(c
);
144 if ((c
.flags
& UNINTERESTING
) != 0) {
145 if (pending
.everbodyHasFlag(UNINTERESTING
)) {
146 final RevCommit n
= pending
.peek();
147 if (n
!= null && n
.commitTime
>= last
.commitTime
) {
148 // This is too close to call. The next commit we
149 // would pop is dated after the last one produced.
150 // We have to keep going to ensure that we carry
151 // flags as much as necessary.
153 overScan
= OVER_SCAN
;
154 } else if (--overScan
== 0)
155 throw StopWalkException
.INSTANCE
;
157 overScan
= OVER_SCAN
;
169 } catch (StopWalkException swe
) {
170 walker
.curs
.release();