blob: ccd5cf1ecb66a786b3c88a5a008caef455cfc2ab [file] [log] [blame]
Ivan Fradeac7d5242019-05-23 15:32:11 -07001/*
2 * Copyright (C) 2019, Google LLC.
3 * and other copyright owners as documented in the project's IP log.
4 *
5 * This program and the accompanying materials are made available
6 * under the terms of the Eclipse Distribution License v1.0 which
7 * accompanies this distribution, is reproduced below, and is
8 * available at http://www.eclipse.org/org/documents/edl-v10.php
9 *
10 * All rights reserved.
11 *
12 * Redistribution and use in source and binary forms, with or
13 * without modification, are permitted provided that the following
14 * conditions are met:
15 *
16 * - Redistributions of source code must retain the above copyright
17 * notice, this list of conditions and the following disclaimer.
18 *
19 * - Redistributions in binary form must reproduce the above
20 * copyright notice, this list of conditions and the following
21 * disclaimer in the documentation and/or other materials provided
22 * with the distribution.
23 *
24 * - Neither the name of the Eclipse Foundation, Inc. nor the
25 * names of its contributors may be used to endorse or promote
26 * products derived from this software without specific prior
27 * written permission.
28 *
29 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND
30 * CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES,
31 * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
32 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
33 * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
34 * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
35 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
36 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
37 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
38 * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
39 * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
40 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
41 * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
42 */
43package com.google.gitiles;
44
45import java.io.IOException;
46import java.util.Collection;
47import org.eclipse.jgit.errors.IncorrectObjectTypeException;
48import org.eclipse.jgit.errors.MissingObjectException;
49import org.eclipse.jgit.lib.ObjectId;
Ivan Fradeac7d5242019-05-23 15:32:11 -070050import org.eclipse.jgit.lib.RefDatabase;
51import org.eclipse.jgit.revwalk.RevCommit;
52import org.eclipse.jgit.revwalk.RevSort;
53import org.eclipse.jgit.revwalk.RevWalk;
54
55/**
56 * Checks for object visibility
57 *
58 * <p>Objects are visible if they are reachable from any of the references visible to the user.
59 */
60public class VisibilityChecker {
61
Ivan Fraded45e2912019-06-07 10:14:35 +020062 private final boolean topoSort;
Ivan Fradeac7d5242019-05-23 15:32:11 -070063
64 /**
65 * @param topoSort whether to use a more thorough reachability check by sorting in topological
66 * order
67 */
68 public VisibilityChecker(boolean topoSort) {
69 this.topoSort = topoSort;
70 }
71
72 /**
73 * Check if any of the refs in {@code refDb} points to the object {@code id}.
74 *
75 * @param refDb a reference database
76 * @param id object we are looking for
77 * @return true if the any of the references in the db points directly to the id
78 * @throws IOException the reference space cannot be accessed
79 */
80 protected boolean isTipOfBranch(RefDatabase refDb, ObjectId id) throws IOException {
81 // If any reference directly points at the requested object, permit display. Common for displays
82 // of pending patch sets in Gerrit Code Review, or bookmarks to the commit a tag points at.
Ivan Frade13cb5172019-04-08 15:51:03 -070083 return !refDb.getTipsWithSha1(id).isEmpty();
Ivan Fradeac7d5242019-05-23 15:32:11 -070084 }
85
86 /**
87 * Check if {@code commit} is reachable starting from {@code starters}.
88 *
89 * @param description Description of the ids (e.g. "heads"). Mainly for tracing.
90 * @param walk The walk to use for the reachability check
91 * @param commit The starting commit. It *MUST* come from the walk in use
92 * @param starters visible commits. Anything reachable from these commits is visible. Missing ids
93 * or ids pointing to wrong kind of objects are ignored.
94 * @return true if we can get to {@code commit} from the {@code starters}
95 * @throws IOException a pack file or loose object could not be read
96 */
97 protected boolean isReachableFrom(
David Pursehoused79cca72019-06-10 12:32:46 +090098 String description, RevWalk walk, RevCommit commit, Collection<ObjectId> starters)
Ivan Fradeac7d5242019-05-23 15:32:11 -070099 throws IOException {
100 if (starters.isEmpty()) {
101 return false;
102 }
103
104 walk.reset();
105 if (topoSort) {
106 walk.sort(RevSort.TOPO);
107 }
108
109 walk.markStart(commit);
110 for (ObjectId id : starters) {
111 markUninteresting(walk, id);
112 }
113 // If the commit is reachable from any given tip, it will appear to be
114 // uninteresting to the RevWalk and no output will be produced.
115 return walk.next() == null;
116 }
117
118 private static void markUninteresting(RevWalk walk, ObjectId id) throws IOException {
119 if (id == null) {
120 return;
121 }
122 try {
123 walk.markUninteresting(walk.parseCommit(id));
124 } catch (IncorrectObjectTypeException | MissingObjectException e) {
125 // Do nothing, doesn't affect reachability.
126 }
127 }
128}