You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

StartGenerator.java 5.1KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169
  1. /*
  2. * Copyright (C) 2008-2009, Google Inc.
  3. * Copyright (C) 2008, Marek Zawirski <marek.zawirski@gmail.com>
  4. * Copyright (C) 2008, Shawn O. Pearce <spearce@spearce.org> and others
  5. *
  6. * This program and the accompanying materials are made available under the
  7. * terms of the Eclipse Distribution License v. 1.0 which is available at
  8. * https://www.eclipse.org/org/documents/edl-v10.php.
  9. *
  10. * SPDX-License-Identifier: BSD-3-Clause
  11. */
  12. package org.eclipse.jgit.revwalk;
  13. import java.io.IOException;
  14. import java.text.MessageFormat;
  15. import org.eclipse.jgit.errors.IncorrectObjectTypeException;
  16. import org.eclipse.jgit.errors.MissingObjectException;
  17. import org.eclipse.jgit.internal.JGitText;
  18. import org.eclipse.jgit.revwalk.filter.AndRevFilter;
  19. import org.eclipse.jgit.revwalk.filter.RevFilter;
  20. import org.eclipse.jgit.treewalk.filter.TreeFilter;
  21. /**
  22. * Initial RevWalk generator that bootstraps a new walk.
  23. * <p>
  24. * Initially RevWalk starts with this generator as its chosen implementation.
  25. * The first request for a RevCommit from the RevWalk instance calls to our
  26. * {@link #next()} method, and we replace ourselves with the best Generator
  27. * implementation available based upon the current RevWalk configuration.
  28. */
  29. class StartGenerator extends Generator {
  30. private final RevWalk walker;
  31. StartGenerator(RevWalk w) {
  32. super(w.isFirstParent());
  33. walker = w;
  34. }
  35. @Override
  36. int outputType() {
  37. return 0;
  38. }
  39. @Override
  40. RevCommit next() throws MissingObjectException,
  41. IncorrectObjectTypeException, IOException {
  42. Generator g;
  43. final RevWalk w = walker;
  44. RevFilter rf = w.getRevFilter();
  45. final TreeFilter tf = w.getTreeFilter();
  46. AbstractRevQueue q = walker.queue;
  47. if (rf == RevFilter.MERGE_BASE) {
  48. // Computing for merge bases is a special case and does not
  49. // use the bulk of the generator pipeline.
  50. //
  51. if (tf != TreeFilter.ALL) {
  52. throw new IllegalStateException(MessageFormat.format(
  53. JGitText.get().cannotCombineTreeFilterWithRevFilter, tf, rf));
  54. }
  55. if (w.isFirstParent()) {
  56. throw new IllegalStateException(
  57. JGitText.get().cannotFindMergeBaseUsingFirstParent);
  58. }
  59. final MergeBaseGenerator mbg = new MergeBaseGenerator(w);
  60. walker.pending = mbg;
  61. walker.queue = AbstractRevQueue.EMPTY_QUEUE;
  62. mbg.init(q);
  63. return mbg.next();
  64. }
  65. final boolean uninteresting = q.anybodyHasFlag(RevWalk.UNINTERESTING);
  66. boolean boundary = walker.hasRevSort(RevSort.BOUNDARY);
  67. if (!boundary && walker instanceof ObjectWalk) {
  68. // The object walker requires boundary support to color
  69. // trees and blobs at the boundary uninteresting so it
  70. // does not produce those in the result.
  71. //
  72. boundary = true;
  73. }
  74. if (boundary && !uninteresting) {
  75. // If we were not fed uninteresting commits we will never
  76. // construct a boundary. There is no reason to include the
  77. // extra overhead associated with that in our pipeline.
  78. //
  79. boundary = false;
  80. }
  81. final DateRevQueue pending;
  82. int pendingOutputType = 0;
  83. if (q instanceof DateRevQueue)
  84. pending = (DateRevQueue)q;
  85. else
  86. pending = new DateRevQueue(q);
  87. if (tf != TreeFilter.ALL) {
  88. int rewriteFlag;
  89. if (w.getRewriteParents()) {
  90. pendingOutputType |= HAS_REWRITE | NEEDS_REWRITE;
  91. rewriteFlag = RevWalk.REWRITE;
  92. } else
  93. rewriteFlag = 0;
  94. rf = AndRevFilter.create(new TreeRevFilter(w, tf, rewriteFlag), rf);
  95. }
  96. walker.queue = q;
  97. if (walker instanceof DepthWalk) {
  98. DepthWalk dw = (DepthWalk) walker;
  99. g = new DepthGenerator(dw, pending);
  100. } else {
  101. g = new PendingGenerator(w, pending, rf, pendingOutputType);
  102. if (walker.hasRevSort(RevSort.BOUNDARY)) {
  103. // Because the boundary generator may produce uninteresting
  104. // commits we cannot allow the pending generator to dispose
  105. // of them early.
  106. //
  107. ((PendingGenerator) g).canDispose = false;
  108. }
  109. }
  110. if ((g.outputType() & NEEDS_REWRITE) != 0) {
  111. // Correction for an upstream NEEDS_REWRITE is to buffer
  112. // fully and then apply a rewrite generator that can
  113. // pull through the rewrite chain and produce a dense
  114. // output graph.
  115. //
  116. g = new FIFORevQueue(g);
  117. g = new RewriteGenerator(g);
  118. }
  119. if (walker.hasRevSort(RevSort.TOPO)
  120. && walker.hasRevSort(RevSort.TOPO_KEEP_BRANCH_TOGETHER)) {
  121. throw new IllegalStateException(JGitText
  122. .get().cannotCombineTopoSortWithTopoNonIntermixSort);
  123. }
  124. if (walker.hasRevSort(RevSort.TOPO)
  125. && (g.outputType() & SORT_TOPO) == 0) {
  126. g = new TopoSortGenerator(g);
  127. } else if (walker.hasRevSort(RevSort.TOPO_KEEP_BRANCH_TOGETHER)
  128. && (g.outputType() & SORT_TOPO) == 0) {
  129. g = new TopoNonIntermixSortGenerator(g);
  130. }
  131. if (walker.hasRevSort(RevSort.REVERSE))
  132. g = new LIFORevQueue(g);
  133. if (boundary)
  134. g = new BoundaryGenerator(w, g);
  135. else if (uninteresting) {
  136. // Try to protect ourselves from uninteresting commits producing
  137. // due to clock skew in the commit time stamps. Delay such that
  138. // we have a chance at coloring enough of the graph correctly,
  139. // and then strip any UNINTERESTING nodes that may have leaked
  140. // through early.
  141. //
  142. if (pending.peek() != null)
  143. g = new DelayRevQueue(g);
  144. g = new FixUninterestingGenerator(g);
  145. }
  146. w.pending = g;
  147. return g.next();
  148. }
  149. }