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.internal.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. import org.eclipse.jgit.revwalk.ObjectReachabilityChecker;
  19. import org.eclipse.jgit.revwalk.ObjectWalk;
  20. import org.eclipse.jgit.revwalk.RevCommit;
  21. import org.eclipse.jgit.revwalk.RevObject;
  22. import org.eclipse.jgit.revwalk.RevSort;

  23. /**
  24.  * Checks if all objects are reachable from certain starting points doing a
  25.  * walk.
  26.  */
  27. public class PedestrianObjectReachabilityChecker
  28.         implements ObjectReachabilityChecker {
  29.     private final ObjectWalk walk;

  30.     /**
  31.      * New instance of the reachability checker using a existing walk.
  32.      *
  33.      * @param walk
  34.      *            ObjectWalk instance to reuse. Caller retains ownership.
  35.      */
  36.     public PedestrianObjectReachabilityChecker(ObjectWalk walk) {
  37.         this.walk = walk;
  38.     }

  39.     /**
  40.      * {@inheritDoc}
  41.      */
  42.     @Override
  43.     public Optional<RevObject> areAllReachable(Collection<RevObject> targets,
  44.             Stream<RevObject> starters) throws IOException {
  45.         try {
  46.             walk.reset();
  47.             walk.sort(RevSort.TOPO);
  48.             for (RevObject target : targets) {
  49.                 walk.markStart(target);
  50.             }

  51.             Iterator<RevObject> iterator = starters.iterator();
  52.             while (iterator.hasNext()) {
  53.                 RevObject o = iterator.next();
  54.                 walk.markUninteresting(o);

  55.                 RevObject peeled = walk.peel(o);
  56.                 if (peeled instanceof RevCommit) {
  57.                     // By default, for performance reasons, ObjectWalk does not
  58.                     // mark
  59.                     // a tree as uninteresting when we mark a commit. Mark it
  60.                     // ourselves so that we can determine reachability exactly.
  61.                     walk.markUninteresting(((RevCommit) peeled).getTree());
  62.                 }
  63.             }

  64.             RevCommit commit = walk.next();
  65.             if (commit != null) {
  66.                 return Optional.of(commit);
  67.             }

  68.             RevObject object = walk.nextObject();
  69.             if (object != null) {
  70.                 return Optional.of(object);
  71.             }

  72.             return Optional.empty();
  73.         } catch (MissingObjectException | InvalidObjectException e) {
  74.             throw new IllegalStateException(e);
  75.         }
  76.     }
  77. }