Carry uninteresting flags back through already processed parents
[egit/zawir.git] / org.spearce.jgit / src / org / spearce / jgit / revwalk / AbstractPendingGenerator.java
blob20f9632989af296376386ab81e647a1511bb3a21
1 /*
2 * Copyright (C) 2008 Shawn Pearce <spearce@spearce.org>
4 * This library is free software; you can redistribute it and/or
5 * modify it under the terms of the GNU General Public
6 * License, version 2, as published by the Free Software Foundation.
8 * This library is distributed in the hope that it will be useful,
9 * but WITHOUT ANY WARRANTY; without even the implied warranty of
10 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
11 * General Public License for more details.
13 * You should have received a copy of the GNU General Public
14 * License along with this library; if not, write to the Free Software
15 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301
17 package org.spearce.jgit.revwalk;
19 import java.io.IOException;
21 import org.spearce.jgit.errors.CorruptObjectException;
22 import org.spearce.jgit.errors.IncorrectObjectTypeException;
23 import org.spearce.jgit.errors.MissingObjectException;
24 import org.spearce.jgit.errors.StopWalkException;
25 import org.spearce.jgit.revwalk.filter.RevFilter;
27 /**
28 * Default (and first pass) RevCommit Generator implementation for RevWalk.
29 * <p>
30 * This generator starts from a set of one or more commits and process them in
31 * descending (newest to oldest) commit time order. Commits automatically cause
32 * their parents to be enqueued for further processing, allowing the entire
33 * commit graph to be walked. A {@link RevFilter} may be used to select a subset
34 * of the commits and return them to the caller.
36 abstract class AbstractPendingGenerator extends Generator {
37 private static final int PARSED = RevWalk.PARSED;
39 private static final int SEEN = RevWalk.SEEN;
41 protected final RevWalk walker;
43 private final AbstractRevQueue pending;
45 private final RevFilter filter;
47 AbstractPendingGenerator(final RevWalk w, final AbstractRevQueue p,
48 final RevFilter f) {
49 walker = w;
50 pending = p;
51 filter = f;
54 @Override
55 int outputType() {
56 if (pending instanceof DateRevQueue)
57 return SORT_COMMIT_TIME_DESC;
58 return 0;
61 @Override
62 RevCommit next() throws MissingObjectException,
63 IncorrectObjectTypeException, IOException {
64 try {
65 for (;;) {
66 final RevCommit c = pending.pop();
67 if (c == null) {
68 walker.curs.release();
69 return null;
72 final boolean produce;
73 if ((c.flags & RevWalk.UNINTERESTING) != 0)
74 produce = false;
75 else if (filter.include(walker, c))
76 produce = include(c);
77 else
78 produce = false;
80 final int carry = c.flags & RevWalk.CARRY_MASK;
81 for (final RevCommit p : c.parents) {
82 if ((p.flags & SEEN) != 0) {
83 if (carry != 0)
84 carryFlags(p, carry);
85 continue;
87 if ((p.flags & PARSED) == 0)
88 p.parse(walker);
89 p.flags |= SEEN;
90 if (carry != 0)
91 carryFlags(p, carry);
92 pending.add(p);
95 if ((c.flags & RevWalk.UNINTERESTING) != 0) {
96 if (pending.everbodyHasFlag(RevWalk.UNINTERESTING))
97 throw StopWalkException.INSTANCE;
98 c.dispose();
99 continue;
102 if (produce)
103 return c;
104 else
105 c.dispose();
107 } catch (StopWalkException swe) {
108 walker.curs.release();
109 pending.clear();
110 return null;
114 private static void carryFlags(RevCommit c, final int carry) {
115 // If we have seen the commit it is either about to enter our
116 // pending queue (first invocation) or one of its parents was
117 // possibly already visited by another path _before_ we came
118 // in through this path (topological order violated). We must
119 // still carry the flags through to the parents.
121 for (;;) {
122 c.flags |= carry;
123 if ((c.flags & SEEN) == 0)
124 return;
125 final RevCommit[] pList = c.parents;
126 final int n = pList.length;
127 if (n == 0)
128 return;
130 for (int i = 1; i < n; i++)
131 carryFlags(pList[i], carry);
132 c = pList[0];
137 * Determine if a commit should produce in the output.
139 * @param c
140 * the current commit.
141 * @return true if this commit should still be produced in the result (it
142 * looked interesting); false if this commit should be omitted from
143 * the result (it appeared boring).
144 * @throws MissingObjectException
145 * see TreeWalk for reasons.
146 * @throws IncorrectObjectTypeException
147 * see TreeWalk for reasons.
148 * @throws CorruptObjectException
149 * see TreeWalk for reasons.
150 * @throws IOException
151 * see TreeWalk for reasons.
153 abstract boolean include(final RevCommit c) throws MissingObjectException,
154 IncorrectObjectTypeException, IOException, CorruptObjectException;