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.io.InvalidObjectException;
14  import java.util.Collection;
15  import java.util.Iterator;
16  import java.util.Optional;
17  import java.util.stream.Stream;
18  
19  import org.eclipse.jgit.errors.MissingObjectException;
20  
21  /**
22   * Checks if all objects are reachable from certain starting points doing a
23   * walk.
24   */
25  class PedestrianObjectReachabilityChecker implements ObjectReachabilityChecker {
26  	private final ObjectWalk walk;
27  
28  	/**
29  	 * New instance of the reachability checker using a existing walk.
30  	 *
31  	 * @param walk
32  	 *            ObjectWalk instance to reuse. Caller retains ownership.
33  	 */
34  	PedestrianObjectReachabilityChecker(ObjectWalk walk) {
35  		this.walk = walk;
36  	}
37  
38  	/**
39  	 * {@inheritDoc}
40  	 */
41  	@Override
42  	public Optional<RevObject> areAllReachable(Collection<RevObject> targets,
43  			Stream<RevObject> starters) throws IOException {
44  		try {
45  			walk.reset();
46  			walk.sort(RevSort.TOPO);
47  			for (RevObject target : targets) {
48  				walk.markStart(target);
49  			}
50  
51  			Iterator<RevObject> iterator = starters.iterator();
52  			while (iterator.hasNext()) {
53  				RevObject o = iterator.next();
54  				walk.markUninteresting(o);
55  
56  				RevObject peeled = walk.peel(o);
57  				if (peeled instanceof RevCommit) {
58  					// By default, for performance reasons, ObjectWalk does not
59  					// mark
60  					// a tree as uninteresting when we mark a commit. Mark it
61  					// ourselves so that we can determine reachability exactly.
62  					walk.markUninteresting(((RevCommit) peeled).getTree());
63  				}
64  			}
65  
66  			RevCommit commit = walk.next();
67  			if (commit != null) {
68  				return Optional.of(commit);
69  			}
70  
71  			RevObject object = walk.nextObject();
72  			if (object != null) {
73  				return Optional.of(object);
74  			}
75  
76  			return Optional.empty();
77  		} catch (MissingObjectException | InvalidObjectException e) {
78  			throw new IllegalStateException(e);
79  		}
80  	}
81  }