View Javadoc
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  
12  import java.io.IOException;
13  import java.util.ArrayList;
14  import java.util.Arrays;
15  import java.util.Collection;
16  import java.util.Iterator;
17  import java.util.List;
18  import java.util.Optional;
19  import java.util.stream.Stream;
20  
21  import org.eclipse.jgit.errors.IncorrectObjectTypeException;
22  import org.eclipse.jgit.errors.MissingObjectException;
23  import org.eclipse.jgit.lib.BitmapIndex.BitmapBuilder;
24  
25  /**
26   * Checks if all objects are reachable from certain starting points using
27   * bitmaps.
28   */
29  class BitmappedObjectReachabilityChecker
30  		implements ObjectReachabilityChecker {
31  
32  	private final ObjectWalk walk;
33  
34  	/**
35  	 * New instance of the reachability checker using a existing walk.
36  	 *
37  	 * @param walk
38  	 *            ObjectWalk instance to reuse. Caller retains ownership.
39  	 */
40  	public BitmappedObjectReachabilityChecker(ObjectWalk walk) {
41  		this.walk = walk;
42  	}
43  
44  	/**
45  	 * {@inheritDoc}
46  	 *
47  	 * This implementation tries to shortcut the check adding starters
48  	 * incrementally. Ordering the starters by relevance can improve performance
49  	 * in the average case.
50  	 */
51  	@Override
52  	public Optional<RevObject> areAllReachable(Collection<RevObject> targets,
53  			Stream<RevObject> starters) throws IOException {
54  
55  		try {
56  			List<RevObject> remainingTargets = new ArrayList<>(targets);
57  			BitmapWalker bitmapWalker = new BitmapWalker(walk,
58  					walk.getObjectReader().getBitmapIndex(), null);
59  
60  			Iterator<RevObject> starterIt = starters.iterator();
61  			BitmapBuilder seen = null;
62  			while (starterIt.hasNext()) {
63  				List<RevObject> asList = Arrays.asList(starterIt.next());
64  				BitmapBuilder visited = bitmapWalker.findObjects(asList, seen,
65  						true);
66  				seen = seen == null ? visited : seen.or(visited);
67  
68  				remainingTargets.removeIf(seen::contains);
69  				if (remainingTargets.isEmpty()) {
70  					return Optional.empty();
71  				}
72  			}
73  
74  			return Optional.of(remainingTargets.get(0));
75  		} catch (MissingObjectException | IncorrectObjectTypeException e) {
76  			throw new IllegalStateException(e);
77  		}
78  	}
79  }