blob: bcc89fc82ff131d928625bd0911dfb50d5909bc9 [file] [log] [blame]
Damien Martin-Guillerezf88f4d82015-09-25 13:56:55 +00001// Copyright 2014 The Bazel Authors. All rights reserved.
Han-Wen Nienhuysd08b27f2015-02-25 16:45:20 +01002//
3// Licensed under the Apache License, Version 2.0 (the "License");
4// you may not use this file except in compliance with the License.
5// You may obtain a copy of the License at
6//
7// http://www.apache.org/licenses/LICENSE-2.0
8//
9// Unless required by applicable law or agreed to in writing, software
10// distributed under the License is distributed on an "AS IS" BASIS,
11// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12// See the License for the specific language governing permissions and
13// limitations under the License.
14package com.google.devtools.build.lib.skyframe;
15
tomlua155b532017-11-08 20:12:47 +010016import com.google.common.base.Preconditions;
Kristina Chodorow73fa2032015-08-28 17:57:46 +000017import com.google.devtools.build.lib.cmdline.PackageIdentifier;
Han-Wen Nienhuysd08b27f2015-02-25 16:45:20 +010018import com.google.devtools.build.lib.collect.nestedset.NestedSet;
19import com.google.devtools.build.lib.collect.nestedset.NestedSetBuilder;
20import com.google.devtools.build.lib.collect.nestedset.Order;
21import com.google.devtools.build.lib.concurrent.ThreadSafety.Immutable;
22import com.google.devtools.build.lib.concurrent.ThreadSafety.ThreadSafe;
Han-Wen Nienhuysd08b27f2015-02-25 16:45:20 +010023import com.google.devtools.build.lib.vfs.PathFragment;
tomluee6a6862018-01-17 14:36:26 -080024import com.google.devtools.build.lib.vfs.Root;
Han-Wen Nienhuysd08b27f2015-02-25 16:45:20 +010025import com.google.devtools.build.lib.vfs.UnixGlob;
Han-Wen Nienhuysd08b27f2015-02-25 16:45:20 +010026import com.google.devtools.build.skyframe.SkyValue;
27
Janak Ramakrishnan29c5ab42015-05-14 19:38:12 +000028/** A value corresponding to a glob. */
Han-Wen Nienhuysd08b27f2015-02-25 16:45:20 +010029@Immutable
30@ThreadSafe
Janak Ramakrishnan29c5ab42015-05-14 19:38:12 +000031public final class GlobValue implements SkyValue {
Han-Wen Nienhuysd08b27f2015-02-25 16:45:20 +010032
Michajlo Matijkiwc3738b12015-10-14 23:36:38 +000033 public static final GlobValue EMPTY = new GlobValue(
Han-Wen Nienhuysd08b27f2015-02-25 16:45:20 +010034 NestedSetBuilder.<PathFragment>emptySet(Order.STABLE_ORDER));
35
36 private final NestedSet<PathFragment> matches;
37
Michajlo Matijkiwc3738b12015-10-14 23:36:38 +000038 /**
39 * Create a GlobValue wrapping {@code matches}. {@code matches} must have order
40 * {@link Order#STABLE_ORDER}.
41 */
42 public GlobValue(NestedSet<PathFragment> matches) {
Han-Wen Nienhuysd08b27f2015-02-25 16:45:20 +010043 this.matches = Preconditions.checkNotNull(matches);
Michajlo Matijkiwc3738b12015-10-14 23:36:38 +000044 Preconditions.checkState(matches.getOrder() == Order.STABLE_ORDER,
45 "Only STABLE_ORDER is supported, but got %s", matches.getOrder());
Han-Wen Nienhuysd08b27f2015-02-25 16:45:20 +010046 }
47
48 /**
Janak Ramakrishnan063b4882016-07-18 20:33:28 +000049 * Returns glob matches. The matches will be in a deterministic but unspecified order. If a
50 * particular order is required, the returned iterable should be sorted.
Han-Wen Nienhuysd08b27f2015-02-25 16:45:20 +010051 */
Janak Ramakrishnan29c5ab42015-05-14 19:38:12 +000052 public NestedSet<PathFragment> getMatches() {
Han-Wen Nienhuysd08b27f2015-02-25 16:45:20 +010053 return matches;
54 }
55
56 @Override
57 public boolean equals(Object other) {
58 if (other == this) {
59 return true;
60 }
61 if (!(other instanceof GlobValue)) {
62 return false;
63 }
64 // shallowEquals() may fail to detect that two equivalent (according to toString())
65 // NestedSets are equal, but will always detect when two NestedSets are different.
66 // This makes this implementation of equals() overly strict, but we only call this
67 // method when doing change pruning, which can accept false negatives.
68 return getMatches().shallowEquals(((GlobValue) other).getMatches());
69 }
70
71 @Override
72 public int hashCode() {
73 return matches.shallowHashCode();
74 }
75
76 /**
janakr43c642d2018-10-18 09:05:08 -070077 * Constructs a {@link GlobDescriptor} for a glob lookup. {@code packageName} is assumed to be an
78 * existing package. Trying to glob into a non-package is undefined behavior.
Han-Wen Nienhuysd08b27f2015-02-25 16:45:20 +010079 *
80 * @throws InvalidGlobPatternException if the pattern is not valid.
81 */
82 @ThreadSafe
janakr43c642d2018-10-18 09:05:08 -070083 public static GlobDescriptor key(
tomluee6a6862018-01-17 14:36:26 -080084 PackageIdentifier packageId,
85 Root packageRoot,
86 String pattern,
87 boolean excludeDirs,
88 PathFragment subdir)
89 throws InvalidGlobPatternException {
Han-Wen Nienhuysd08b27f2015-02-25 16:45:20 +010090 if (pattern.indexOf('?') != -1) {
91 throw new InvalidGlobPatternException(pattern, "wildcard ? forbidden");
92 }
93
94 String error = UnixGlob.checkPatternForError(pattern);
95 if (error != null) {
96 throw new InvalidGlobPatternException(pattern, error);
97 }
98
Nathan Harmatab795e6b2016-02-04 01:10:19 +000099 return internalKey(packageId, packageRoot, subdir, pattern, excludeDirs);
Han-Wen Nienhuysd08b27f2015-02-25 16:45:20 +0100100 }
101
102 /**
janakr43c642d2018-10-18 09:05:08 -0700103 * Constructs a {@link GlobDescriptor} for a glob lookup.
Han-Wen Nienhuysd08b27f2015-02-25 16:45:20 +0100104 *
105 * <p>Do not use outside {@code GlobFunction}.
106 */
107 @ThreadSafe
janakr43c642d2018-10-18 09:05:08 -0700108 static GlobDescriptor internalKey(
tomluee6a6862018-01-17 14:36:26 -0800109 PackageIdentifier packageId,
110 Root packageRoot,
111 PathFragment subdir,
112 String pattern,
113 boolean excludeDirs) {
michajlo19e42c92018-01-03 12:44:17 -0800114 return GlobDescriptor.create(packageId, packageRoot, subdir, pattern, excludeDirs);
Han-Wen Nienhuysd08b27f2015-02-25 16:45:20 +0100115 }
116
117 /**
Han-Wen Nienhuysd08b27f2015-02-25 16:45:20 +0100118 * An exception that indicates that a glob pattern is syntactically invalid.
119 */
120 @ThreadSafe
Janak Ramakrishnan29c5ab42015-05-14 19:38:12 +0000121 public static final class InvalidGlobPatternException extends Exception {
Han-Wen Nienhuysd08b27f2015-02-25 16:45:20 +0100122 private final String pattern;
123
124 InvalidGlobPatternException(String pattern, String error) {
125 super(error);
126 this.pattern = pattern;
127 }
128
129 @Override
130 public String toString() {
131 return String.format("invalid glob pattern '%s': %s", pattern, getMessage());
132 }
133 }
134}