Move FileStateValue.Type to Metadata; add Metadata.getType() This is in preparation for merging FileArtifactValue and FileStateValue. Progress on #3360. PiperOrigin-RevId: 179832948
diff --git a/src/main/java/com/google/devtools/build/lib/actions/AbstractAction.java b/src/main/java/com/google/devtools/build/lib/actions/AbstractAction.java index 0b272fb..c241c56 100644 --- a/src/main/java/com/google/devtools/build/lib/actions/AbstractAction.java +++ b/src/main/java/com/google/devtools/build/lib/actions/AbstractAction.java
@@ -428,10 +428,13 @@ for (Artifact input : getMandatoryInputs()) { // Assume that if the file did not exist, we would not have gotten here. try { - if (input.isSourceArtifact() && !metadataProvider.getMetadata(input).isFile()) { - eventHandler.handle(Event.warn(getOwner().getLocation(), "input '" - + input.prettyPrint() + "' to " + getOwner().getLabel() - + " is a directory; dependency checking of directories is unsound")); + if (input.isSourceArtifact() + && metadataProvider.getMetadata(input).getType().isDirectory()) { + // TODO(ulfjack): What about dependency checking of special files? + eventHandler.handle(Event.warn(getOwner().getLocation(), + String.format( + "input '%s' to %s is a directory; dependency checking of directories is unsound", + input.prettyPrint(), getOwner().getLabel()))); } } catch (IOException e) { throw new UserExecException(e);
diff --git a/src/main/java/com/google/devtools/build/lib/actions/ActionCacheChecker.java b/src/main/java/com/google/devtools/build/lib/actions/ActionCacheChecker.java index 8e4dc88..b6957cf 100644 --- a/src/main/java/com/google/devtools/build/lib/actions/ActionCacheChecker.java +++ b/src/main/java/com/google/devtools/build/lib/actions/ActionCacheChecker.java
@@ -51,15 +51,21 @@ * otherwise lightweight, and should be constructed anew and discarded for each build request. */ public class ActionCacheChecker { + private static final byte[] EMPTY_DIGEST = new byte[0]; private static final Metadata CONSTANT_METADATA = new Metadata() { @Override + public FileStateType getType() { + return FileStateType.REGULAR_FILE; + } + + @Override public boolean isFile() { - return false; + return true; } @Override public byte[] getDigest() { - throw new UnsupportedOperationException(); + return EMPTY_DIGEST; } @Override
diff --git a/src/main/java/com/google/devtools/build/lib/actions/FileStateType.java b/src/main/java/com/google/devtools/build/lib/actions/FileStateType.java new file mode 100644 index 0000000..8e339e4 --- /dev/null +++ b/src/main/java/com/google/devtools/build/lib/actions/FileStateType.java
@@ -0,0 +1,79 @@ +// Copyright 2017 The Bazel Authors. 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.actions; + +/** An enum indicating the type of a path on the file system. */ +public enum FileStateType { + REGULAR_FILE("file"), + /** + * A special file such as a socket, fifo, or device. See + * {@link com.google.devtools.build.lib.vfs.FileStatus#isSpecialFile}. + */ + SPECIAL_FILE("special file"), + DIRECTORY("directory"), + SYMLINK("symlink"), + NONEXISTENT("non-existent path"); + + private final String name; + + private FileStateType(String name) { + this.name = name; + } + + public String getHumanReadableName() { + return name; + } + + /** Returns true if this type does not correspond to a non-existent path. */ + public boolean exists() { + return this != NONEXISTENT; + } + + /** Returns true if this value corresponds to a symlink. */ + public boolean isSymlink() { + return this == SYMLINK; + } + + /** + * Returns true if this value corresponds to a regular file. If so, its parent directory is + * guaranteed to exist. + */ + public boolean isFile() { + return this == REGULAR_FILE; + } + + /** + * Returns true if this value corresponds to a special file. If so, its parent directory is + * guaranteed to exist. + */ + public boolean isSpecialFile() { + return this == SPECIAL_FILE; + } + + /** + * Returns true if this value corresponds to a regular or special file. If so, its parent + * directory is guaranteed to exist. + */ + public boolean isRegularOrSpecialFile() { + return this == REGULAR_FILE || this == FileStateType.SPECIAL_FILE; + } + + /** + * Returns true if the file is a directory. If so, its parent directory is guaranteed to exist. + */ + public boolean isDirectory() { + return this == DIRECTORY; + } +} \ No newline at end of file
diff --git a/src/main/java/com/google/devtools/build/lib/actions/MetadataProvider.java b/src/main/java/com/google/devtools/build/lib/actions/MetadataProvider.java index 40d54b6..1538286 100644 --- a/src/main/java/com/google/devtools/build/lib/actions/MetadataProvider.java +++ b/src/main/java/com/google/devtools/build/lib/actions/MetadataProvider.java
@@ -29,6 +29,10 @@ * then t >= p. Aside from these properties, t can be any value and may vary arbitrarily across * calls. * + * <p>Returned {@link Metadata} instance correspond to the final target of a symlink, and + * therefore must not have a type of + * {@link com.google.devtools.build.lib.actions.FileStateType#SYMLINK} themselves. + * * The return value is owned by the cache and must not be modified. * * @param input the input to retrieve the digest for
diff --git a/src/main/java/com/google/devtools/build/lib/actions/cache/Metadata.java b/src/main/java/com/google/devtools/build/lib/actions/cache/Metadata.java index 642bd29..c14cb03 100644 --- a/src/main/java/com/google/devtools/build/lib/actions/cache/Metadata.java +++ b/src/main/java/com/google/devtools/build/lib/actions/cache/Metadata.java
@@ -14,12 +14,12 @@ package com.google.devtools.build.lib.actions.cache; +import com.google.devtools.build.lib.actions.FileStateType; + /** - * An interface to represent the state of a file (or directory). This is used to determine whether a - * file has changed or not. - * - * <p>NB! Several other parts of Blaze are relying on the fact that metadata uses mtime and not - * ctime. If metadata is ever changed to use ctime, all uses of Metadata must be carefully examined. + * An interface to represent the state of a file system object for the execution phase. This is not + * used by Skyframe for invalidation, it is primarily used by the action cache and the various + * {@link com.google.devtools.build.lib.exec.SpawnRunner} implementations. */ public interface Metadata { /** @@ -30,6 +30,14 @@ } /** + * The type of the underlying file system object. If it is a regular file, then it is + * guaranteed to have a digest. Otherwise it does not have a digest. + */ + default FileStateType getType() { + return isFile() ? FileStateType.REGULAR_FILE : FileStateType.DIRECTORY; + } + + /** * Whether the underlying file system object is a file or a symlink to a file, rather than a * directory. All files are guaranteed to have a digest, and {@link #getDigest} must only be * called on files. @@ -40,7 +48,7 @@ * Returns the file's digest; must only be called on objects for which {@link #isFile} returns * true. * - * <p>The return value is owned by the cache and must not be modified. + * <p>The return value is owned by this object and must not be modified. */ byte[] getDigest();