diff options
Diffstat (limited to 'src/main/java/com/google/devtools/build/lib/skyframe/GlobValue.java')
-rw-r--r-- | src/main/java/com/google/devtools/build/lib/skyframe/GlobValue.java | 132 |
1 files changed, 132 insertions, 0 deletions
diff --git a/src/main/java/com/google/devtools/build/lib/skyframe/GlobValue.java b/src/main/java/com/google/devtools/build/lib/skyframe/GlobValue.java new file mode 100644 index 0000000000..6de0fbdbc6 --- /dev/null +++ b/src/main/java/com/google/devtools/build/lib/skyframe/GlobValue.java @@ -0,0 +1,132 @@ +// Copyright 2014 Google Inc. All rights reserved. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +package com.google.devtools.build.lib.skyframe; + +import com.google.common.base.Preconditions; +import com.google.devtools.build.lib.collect.nestedset.NestedSet; +import com.google.devtools.build.lib.collect.nestedset.NestedSetBuilder; +import com.google.devtools.build.lib.collect.nestedset.Order; +import com.google.devtools.build.lib.concurrent.ThreadSafety.Immutable; +import com.google.devtools.build.lib.concurrent.ThreadSafety.ThreadSafe; +import com.google.devtools.build.lib.packages.PackageIdentifier; +import com.google.devtools.build.lib.vfs.PathFragment; +import com.google.devtools.build.lib.vfs.UnixGlob; +import com.google.devtools.build.skyframe.SkyKey; +import com.google.devtools.build.skyframe.SkyValue; + +/** + * A value corresponding to a glob. + */ +@Immutable +@ThreadSafe +final class GlobValue implements SkyValue { + + static final GlobValue EMPTY = new GlobValue( + NestedSetBuilder.<PathFragment>emptySet(Order.STABLE_ORDER)); + + private final NestedSet<PathFragment> matches; + + GlobValue(NestedSet<PathFragment> matches) { + this.matches = Preconditions.checkNotNull(matches); + } + + /** + * Returns glob matches. + */ + NestedSet<PathFragment> getMatches() { + return matches; + } + + @Override + public boolean equals(Object other) { + if (other == this) { + return true; + } + if (!(other instanceof GlobValue)) { + return false; + } + // shallowEquals() may fail to detect that two equivalent (according to toString()) + // NestedSets are equal, but will always detect when two NestedSets are different. + // This makes this implementation of equals() overly strict, but we only call this + // method when doing change pruning, which can accept false negatives. + return getMatches().shallowEquals(((GlobValue) other).getMatches()); + } + + @Override + public int hashCode() { + return matches.shallowHashCode(); + } + + /** + * Constructs a {@link SkyKey} for a glob lookup. {@code packageName} is assumed to be an + * existing package. Trying to glob into a non-package is undefined behavior. + * + * @throws InvalidGlobPatternException if the pattern is not valid. + */ + @ThreadSafe + static SkyKey key(PackageIdentifier packageId, String pattern, boolean excludeDirs) + throws InvalidGlobPatternException { + if (pattern.indexOf('?') != -1) { + throw new InvalidGlobPatternException(pattern, "wildcard ? forbidden"); + } + + String error = UnixGlob.checkPatternForError(pattern); + if (error != null) { + throw new InvalidGlobPatternException(pattern, error); + } + + return internalKey(packageId, PathFragment.EMPTY_FRAGMENT, pattern, excludeDirs); + } + + /** + * Constructs a {@link SkyKey} for a glob lookup. + * + * <p>Do not use outside {@code GlobFunction}. + */ + @ThreadSafe + static SkyKey internalKey(PackageIdentifier packageId, PathFragment subdir, String pattern, + boolean excludeDirs) { + return new SkyKey(SkyFunctions.GLOB, + new GlobDescriptor(packageId, subdir, pattern, excludeDirs)); + } + + /** + * Constructs a {@link SkyKey} for a glob lookup. + * + * <p>Do not use outside {@code GlobFunction}. + */ + @ThreadSafe + static SkyKey internalKey(GlobDescriptor glob, String subdirName) { + return internalKey(glob.packageId, glob.subdir.getRelative(subdirName), + glob.pattern, glob.excludeDirs); + } + + /** + * An exception that indicates that a glob pattern is syntactically invalid. + */ + @ThreadSafe + static final class InvalidGlobPatternException extends Exception { + private final String pattern; + + InvalidGlobPatternException(String pattern, String error) { + super(error); + this.pattern = pattern; + } + + @Override + public String toString() { + return String.format("invalid glob pattern '%s': %s", pattern, getMessage()); + } + } +} |