BitmappedObjectReachabilityChecker.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.util.ArrayList;
  13. import java.util.Arrays;
  14. import java.util.Collection;
  15. import java.util.Iterator;
  16. import java.util.List;
  17. import java.util.Optional;
  18. import java.util.stream.Stream;

  19. import org.eclipse.jgit.errors.IncorrectObjectTypeException;
  20. import org.eclipse.jgit.errors.MissingObjectException;
  21. import org.eclipse.jgit.lib.BitmapIndex.BitmapBuilder;
  22. import org.eclipse.jgit.revwalk.BitmapWalker;
  23. import org.eclipse.jgit.revwalk.ObjectReachabilityChecker;
  24. import org.eclipse.jgit.revwalk.ObjectWalk;
  25. import org.eclipse.jgit.revwalk.RevObject;

  26. /**
  27.  * Checks if all objects are reachable from certain starting points using
  28.  * bitmaps.
  29.  */
  30. public class BitmappedObjectReachabilityChecker
  31.         implements ObjectReachabilityChecker {

  32.     private final ObjectWalk walk;

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

  42.     /**
  43.      * {@inheritDoc}
  44.      *
  45.      * This implementation tries to shortcut the check adding starters
  46.      * incrementally. Ordering the starters by relevance can improve performance
  47.      * in the average case.
  48.      */
  49.     @Override
  50.     public Optional<RevObject> areAllReachable(Collection<RevObject> targets,
  51.             Stream<RevObject> starters) throws IOException {

  52.         try {
  53.             List<RevObject> remainingTargets = new ArrayList<>(targets);
  54.             BitmapWalker bitmapWalker = new BitmapWalker(walk,
  55.                     walk.getObjectReader().getBitmapIndex(), null);

  56.             Iterator<RevObject> starterIt = starters.iterator();
  57.             BitmapBuilder seen = null;
  58.             while (starterIt.hasNext()) {
  59.                 List<RevObject> asList = Arrays.asList(starterIt.next());
  60.                 BitmapBuilder visited = bitmapWalker.findObjects(asList, seen,
  61.                         true);
  62.                 seen = seen == null ? visited : seen.or(visited);

  63.                 remainingTargets.removeIf(seen::contains);
  64.                 if (remainingTargets.isEmpty()) {
  65.                     return Optional.empty();
  66.                 }
  67.             }

  68.             return Optional.of(remainingTargets.get(0));
  69.         } catch (MissingObjectException | IncorrectObjectTypeException e) {
  70.             throw new IllegalStateException(e);
  71.         }
  72.     }
  73. }