Allow RevWalk applications to add new starting roots during traversal
[egit/qmx.git] / org.spearce.jgit / src / org / spearce / jgit / revwalk / StartGenerator.java
blob94d532386f33706cd2cf4949048dae209ed0d3fc
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;
20 import java.util.EnumSet;
22 import org.spearce.jgit.errors.IncorrectObjectTypeException;
23 import org.spearce.jgit.errors.MissingObjectException;
24 import org.spearce.jgit.revwalk.filter.AndRevFilter;
25 import org.spearce.jgit.revwalk.filter.RevFilter;
26 import org.spearce.jgit.treewalk.filter.TreeFilter;
28 /**
29 * Initial RevWalk generator that bootstraps a new walk.
30 * <p>
31 * Initially RevWalk starts with this generator as its chosen implementation.
32 * The first request for a RevCommit from the RevWalk instance calls to our
33 * {@link #next()} method, and we replace ourselves with the best Generator
34 * implementation available based upon the current RevWalk configuration.
36 class StartGenerator extends Generator {
37 private final RevWalk walker;
39 StartGenerator(final RevWalk w) {
40 walker = w;
43 @Override
44 int outputType() {
45 return 0;
48 @Override
49 RevCommit next() throws MissingObjectException,
50 IncorrectObjectTypeException, IOException {
51 Generator g;
53 final RevWalk w = walker;
54 RevFilter rf = w.getRevFilter();
55 final TreeFilter tf = w.getTreeFilter();
56 final EnumSet<RevSort> sort = w.getRevSort();
57 AbstractRevQueue q = walker.queue;
58 boolean boundary = sort.contains(RevSort.BOUNDARY);
60 if (boundary && !q.anybodyHasFlag(RevWalk.UNINTERESTING)) {
61 // If we were not fed uninteresting commits we will never
62 // construct a boundary. There is no reason to include the
63 // extra overhead associated with that in our pipeline.
65 boundary = false;
68 int pendingOutputType = 0;
69 if (sort.contains(RevSort.COMMIT_TIME_DESC))
70 q = new DateRevQueue(q);
71 if (tf != TreeFilter.ALL) {
72 rf = AndRevFilter.create(rf, new RewriteTreeFilter(w, tf));
73 pendingOutputType |= HAS_REWRITE | NEEDS_REWRITE;
76 walker.queue = q;
77 g = new PendingGenerator(w, q, rf, pendingOutputType);
79 if (boundary) {
80 // Because the boundary generator may produce uninteresting
81 // commits we cannot allow the pending generator to dispose
82 // of them early.
84 ((PendingGenerator) g).canDispose = false;
87 if ((g.outputType() & NEEDS_REWRITE) != 0) {
88 // Correction for an upstream NEEDS_REWRITE is to buffer
89 // fully and then apply a rewrite generator that can
90 // pull through the rewrite chain and produce a dense
91 // output graph.
93 g = new FIFORevQueue(g);
94 g = new RewriteGenerator(g);
97 if (sort.contains(RevSort.TOPO) && (g.outputType() & SORT_TOPO) == 0)
98 g = new TopoSortGenerator(g);
99 if (sort.contains(RevSort.REVERSE))
100 g = new LIFORevQueue(q);
101 if (boundary)
102 g = new BoundaryGenerator(w, g);
104 w.pending = g;
105 return g.next();