PedestrianObjectReachabilityChecker.java

  1. /*
  2.  * Copyright (C) 2020, Google LLC and others
  3.  *
  4.  * This program and the accompanying materials are made available under the
  5.  * terms of the Eclipse Distribution License v. 1.0 which is available at
  6.  * https://www.eclipse.org/org/documents/edl-v10.php.
  7.  *
  8.  * SPDX-License-Identifier: BSD-3-Clause
  9.  */
  10. package org.eclipse.jgit.revwalk;

  11. import java.io.IOException;
  12. import java.io.InvalidObjectException;
  13. import java.util.Collection;
  14. import java.util.Iterator;
  15. import java.util.Optional;
  16. import java.util.stream.Stream;

  17. import org.eclipse.jgit.errors.MissingObjectException;

  18. /**
  19.  * Checks if all objects are reachable from certain starting points doing a
  20.  * walk.
  21.  */
  22. class PedestrianObjectReachabilityChecker implements ObjectReachabilityChecker {
  23.     private final ObjectWalk walk;

  24.     /**
  25.      * New instance of the reachability checker using a existing walk.
  26.      *
  27.      * @param walk
  28.      *            ObjectWalk instance to reuse. Caller retains ownership.
  29.      */
  30.     PedestrianObjectReachabilityChecker(ObjectWalk walk) {
  31.         this.walk = walk;
  32.     }

  33.     /**
  34.      * {@inheritDoc}
  35.      */
  36.     @Override
  37.     public Optional<RevObject> areAllReachable(Collection<RevObject> targets,
  38.             Stream<RevObject> starters) throws IOException {
  39.         try {
  40.             walk.reset();
  41.             walk.sort(RevSort.TOPO);
  42.             for (RevObject target : targets) {
  43.                 walk.markStart(target);
  44.             }

  45.             Iterator<RevObject> iterator = starters.iterator();
  46.             while (iterator.hasNext()) {
  47.                 RevObject o = iterator.next();
  48.                 walk.markUninteresting(o);

  49.                 RevObject peeled = walk.peel(o);
  50.                 if (peeled instanceof RevCommit) {
  51.                     // By default, for performance reasons, ObjectWalk does not
  52.                     // mark
  53.                     // a tree as uninteresting when we mark a commit. Mark it
  54.                     // ourselves so that we can determine reachability exactly.
  55.                     walk.markUninteresting(((RevCommit) peeled).getTree());
  56.                 }
  57.             }

  58.             RevCommit commit = walk.next();
  59.             if (commit != null) {
  60.                 return Optional.of(commit);
  61.             }

  62.             RevObject object = walk.nextObject();
  63.             if (object != null) {
  64.                 return Optional.of(object);
  65.             }

  66.             return Optional.empty();
  67.         } catch (MissingObjectException | InvalidObjectException e) {
  68.             throw new IllegalStateException(e);
  69.         }
  70.     }
  71. }