aboutsummaryrefslogtreecommitdiffhomepage
path: root/src/main/java/com/google/devtools/build/lib/skyframe/RecursiveFilesystemTraversalValue.java
diff options
context:
space:
mode:
authorGravatar Laszlo Csomor <laszlocsomor@google.com>2015-12-04 13:23:54 +0000
committerGravatar Kristina Chodorow <kchodorow@google.com>2015-12-04 21:06:32 +0000
commitb4d482bee65fbb83351fc562bca2a30e55a90a49 (patch)
tree03ee30b7609375cd92c9f1d0126759a8bf12f8a2 /src/main/java/com/google/devtools/build/lib/skyframe/RecursiveFilesystemTraversalValue.java
parentc3e5e2ac1a615131cf2d543375ac63102c40ec2f (diff)
Refactoring: RecursiveFilesystemTraversalValue.ResolvedFile is now an interface.
This CL changes the class structure, moving from inheritance to implementation and composition. In particular, it turns the abstract base class ResolvedFile into an interface which the earlier subclasses now simply implement rather than extending it. This change makes the code cleaner: implementors may write more complicated getters (and that's my plan to do in a subsequent CL) instead of just returning the members. -- MOS_MIGRATED_REVID=109405650
Diffstat (limited to 'src/main/java/com/google/devtools/build/lib/skyframe/RecursiveFilesystemTraversalValue.java')
-rw-r--r--src/main/java/com/google/devtools/build/lib/skyframe/RecursiveFilesystemTraversalValue.java669
1 files changed, 395 insertions, 274 deletions
diff --git a/src/main/java/com/google/devtools/build/lib/skyframe/RecursiveFilesystemTraversalValue.java b/src/main/java/com/google/devtools/build/lib/skyframe/RecursiveFilesystemTraversalValue.java
index e69de7274e..33ce1f14a6 100644
--- a/src/main/java/com/google/devtools/build/lib/skyframe/RecursiveFilesystemTraversalValue.java
+++ b/src/main/java/com/google/devtools/build/lib/skyframe/RecursiveFilesystemTraversalValue.java
@@ -204,362 +204,484 @@ public final class RecursiveFilesystemTraversalValue implements SkyValue {
}
}
- /**
- * Path and type information about a single file or symlink.
- *
- * <p>The object stores things such as the absolute path of the file or symlink, its exact type
- * and, if it's a symlink, the resolved and unresolved link target paths.
- */
- public abstract static class ResolvedFile {
- private static final class Symlink {
- private final RootedPath linkName;
- private final PathFragment unresolvedLinkTarget;
- // The resolved link target is stored in ResolvedFile.path
-
- private Symlink(RootedPath linkName, PathFragment unresolvedLinkTarget) {
- this.linkName = Preconditions.checkNotNull(linkName);
- this.unresolvedLinkTarget = Preconditions.checkNotNull(unresolvedLinkTarget);
- }
+ private static final class Symlink {
+ private final RootedPath linkName;
+ private final PathFragment unresolvedLinkTarget;
+ // The resolved link target is returned by ResolvedFile.getPath()
+
+ private Symlink(RootedPath linkName, PathFragment unresolvedLinkTarget) {
+ this.linkName = Preconditions.checkNotNull(linkName);
+ this.unresolvedLinkTarget = Preconditions.checkNotNull(unresolvedLinkTarget);
+ }
- PathFragment getNameInSymlinkTree() {
- return linkName.getRelativePath();
- }
+ PathFragment getNameInSymlinkTree() {
+ return linkName.getRelativePath();
+ }
- @Override
- public boolean equals(Object obj) {
- if (this == obj) {
- return true;
- }
- if (!(obj instanceof Symlink)) {
- return false;
- }
- Symlink o = (Symlink) obj;
- return linkName.equals(o.linkName) && unresolvedLinkTarget.equals(o.unresolvedLinkTarget);
+ @Override
+ public boolean equals(Object obj) {
+ if (this == obj) {
+ return true;
}
-
- @Override
- public int hashCode() {
- return Objects.hashCode(linkName, unresolvedLinkTarget);
+ if (!(obj instanceof Symlink)) {
+ return false;
}
+ Symlink o = (Symlink) obj;
+ return linkName.equals(o.linkName) && unresolvedLinkTarget.equals(o.unresolvedLinkTarget);
+ }
- @Override
- public String toString() {
- return String.format("Symlink(link_name=%s, unresolved_target=%s)",
- linkName, unresolvedLinkTarget);
- }
+ @Override
+ public int hashCode() {
+ return Objects.hashCode(linkName, unresolvedLinkTarget);
}
- private static final class RegularFile extends ResolvedFile {
- private RegularFile(RootedPath path) {
- super(FileType.FILE, Optional.of(path), Optional.<FileStateValue>absent());
- }
+ @Override
+ public String toString() {
+ return String.format("Symlink(link_name=%s, unresolved_target=%s)",
+ linkName, unresolvedLinkTarget);
+ }
+ }
- RegularFile(RootedPath path, FileStateValue metadata) {
- super(FileType.FILE, Optional.of(path), Optional.of(metadata));
- }
+ private static final class RegularFile implements ResolvedFile {
+ private final FileType type;
+ private final Optional<RootedPath> path;
+ private final Optional<FileStateValue> metadata;
- @Override
- public boolean equals(Object obj) {
- if (this == obj) {
- return true;
- }
- if (!(obj instanceof RegularFile)) {
- return false;
- }
- return super.isEqualTo((RegularFile) obj);
- }
+ private RegularFile(RootedPath path) {
+ this.type = FileType.FILE;
+ this.path = Optional.of(path);
+ this.metadata = Optional.<FileStateValue>absent();
+ }
- @Override
- public String toString() {
- return String.format("RegularFile(%s)", super.toString());
- }
+ RegularFile(RootedPath path, FileStateValue metadata) {
+ this.type = FileType.FILE;
+ this.path = Optional.of(path);
+ this.metadata = Optional.of(metadata);
+ }
- @Override
- ResolvedFile stripMetadataForTesting() {
- return new RegularFile(path.get());
- }
+ @Override
+ public FileType getType() {
+ return type;
+ }
- @Override
- public PathFragment getNameInSymlinkTree() {
- return path.get().getRelativePath();
- }
+ @Override
+ public Optional<RootedPath> getPath() {
+ return path;
+ }
- @Override
- public PathFragment getTargetInSymlinkTree(boolean followSymlinks) {
- return path.get().asPath().asFragment();
- }
+ @Override
+ public Optional<FileStateValue> getMetadata() {
+ return metadata;
}
- private static final class Directory extends ResolvedFile {
- Directory(RootedPath path) {
- super(FileType.DIRECTORY, Optional.of(path), Optional.<FileStateValue>of(
- FileStateValue.DIRECTORY_FILE_STATE_NODE));
+ @Override
+ public boolean equals(Object obj) {
+ if (this == obj) {
+ return true;
}
-
- @Override
- public boolean equals(Object obj) {
- if (this == obj) {
- return true;
- }
- if (!(obj instanceof Directory)) {
- return false;
- }
- return super.isEqualTo((Directory) obj);
+ if (!(obj instanceof RegularFile)) {
+ return false;
}
+ return ResolvedFileUtils.areObjectsEqual(this, (RegularFile) obj);
+ }
- @Override
- public String toString() {
- return String.format("Directory(%s)", super.toString());
- }
+ @Override
+ public int hashCode() {
+ return ResolvedFileUtils.hashCodeOf(this);
+ }
- @Override
- ResolvedFile stripMetadataForTesting() {
- return this;
- }
+ @Override
+ public String toString() {
+ return String.format("RegularFile(%s)", ResolvedFileUtils.asString(this));
+ }
- @Override
- public PathFragment getNameInSymlinkTree() {
- return path.get().getRelativePath();
- }
+ @Override
+ public ResolvedFile stripMetadataForTesting() {
+ return new RegularFile(path.get());
+ }
- @Override
- public PathFragment getTargetInSymlinkTree(boolean followSymlinks) {
- return path.get().asPath().asFragment();
- }
+ @Override
+ public PathFragment getNameInSymlinkTree() {
+ return path.get().getRelativePath();
}
- private static final class DanglingSymlink extends ResolvedFile {
- private final Symlink symlink;
+ @Override
+ public PathFragment getTargetInSymlinkTree(boolean followSymlinks) {
+ return path.get().asPath().asFragment();
+ }
+ }
- private DanglingSymlink(Symlink symlink) {
- super(FileType.DANGLING_SYMLINK, Optional.<RootedPath>absent(),
- Optional.<FileStateValue>absent());
- this.symlink = symlink;
- }
+ private static final class Directory implements ResolvedFile {
+ private final FileType type;
+ private final Optional<RootedPath> path;
- DanglingSymlink(RootedPath linkNamePath, PathFragment linkTargetPath,
- FileStateValue metadata) {
- super(FileType.DANGLING_SYMLINK, Optional.<RootedPath>absent(), Optional.of(metadata));
- this.symlink = new Symlink(linkNamePath, linkTargetPath);
- }
+ Directory(RootedPath path) {
+ this.type = FileType.DIRECTORY;
+ this.path = Optional.of(path);
+ }
- @Override
- public boolean equals(Object obj) {
- if (this == obj) {
- return true;
- }
- if (!(obj instanceof DanglingSymlink)) {
- return false;
- }
- DanglingSymlink o = (DanglingSymlink) obj;
- return super.isEqualTo(o) && symlink.equals(o.symlink);
- }
+ @Override
+ public FileType getType() {
+ return type;
+ }
- @Override
- public int hashCode() {
- return Objects.hashCode(super.hashCode(), symlink);
- }
+ @Override
+ public Optional<RootedPath> getPath() {
+ return path;
+ }
- @Override
- public String toString() {
- return String.format("DanglingSymlink(%s, %s)", super.toString(), symlink);
- }
+ @Override
+ public Optional<FileStateValue> getMetadata() {
+ return Optional.<FileStateValue>of(FileStateValue.DIRECTORY_FILE_STATE_NODE);
+ }
- @Override
- ResolvedFile stripMetadataForTesting() {
- return new DanglingSymlink(symlink);
+ @Override
+ public boolean equals(Object obj) {
+ if (this == obj) {
+ return true;
}
-
- @Override
- public PathFragment getNameInSymlinkTree() {
- return symlink.getNameInSymlinkTree();
+ if (!(obj instanceof Directory)) {
+ return false;
}
+ return ResolvedFileUtils.areObjectsEqual(this, (Directory) obj);
+ }
- @Override
- public PathFragment getTargetInSymlinkTree(boolean followSymlinks)
- throws DanglingSymlinkException {
- if (followSymlinks) {
- throw new DanglingSymlinkException(symlink.linkName.asPath().getPathString(),
- symlink.unresolvedLinkTarget.getPathString());
- } else {
- return symlink.unresolvedLinkTarget;
- }
- }
+ @Override
+ public int hashCode() {
+ return ResolvedFileUtils.hashCodeOf(this);
}
- private static final class SymlinkToFile extends ResolvedFile {
- private final Symlink symlink;
+ @Override
+ public String toString() {
+ return String.format("Directory(%s)", ResolvedFileUtils.asString(this));
+ }
- private SymlinkToFile(RootedPath targetPath, Symlink symlink) {
- super(FileType.SYMLINK_TO_FILE, Optional.of(targetPath), Optional.<FileStateValue>absent());
- this.symlink = symlink;
- }
+ @Override
+ public ResolvedFile stripMetadataForTesting() {
+ return this;
+ }
- SymlinkToFile(RootedPath targetPath, RootedPath linkNamePath,
- PathFragment linkTargetPath, FileStateValue metadata) {
- super(FileType.SYMLINK_TO_FILE, Optional.of(targetPath), Optional.of(metadata));
- this.symlink = new Symlink(linkNamePath, linkTargetPath);
- }
+ @Override
+ public PathFragment getNameInSymlinkTree() {
+ return path.get().getRelativePath();
+ }
- @Override
- public boolean equals(Object obj) {
- if (this == obj) {
- return true;
- }
- if (!(obj instanceof SymlinkToFile)) {
- return false;
- }
- SymlinkToFile o = (SymlinkToFile) obj;
- return super.isEqualTo(o) && symlink.equals(o.symlink);
- }
+ @Override
+ public PathFragment getTargetInSymlinkTree(boolean followSymlinks) {
+ return path.get().asPath().asFragment();
+ }
+ }
- @Override
- public int hashCode() {
- return Objects.hashCode(super.hashCode(), symlink);
- }
+ private static final class DanglingSymlink implements ResolvedFile {
+ private final FileType type;
+ private final Symlink symlink;
+ private final Optional<FileStateValue> metadata;
- @Override
- public String toString() {
- return String.format("SymlinkToFile(%s, %s)", super.toString(), symlink);
- }
+ private DanglingSymlink(Symlink symlink) {
+ this.type = FileType.DANGLING_SYMLINK;
+ this.symlink = symlink;
+ this.metadata = Optional.absent();
+ }
- @Override
- ResolvedFile stripMetadataForTesting() {
- return new SymlinkToFile(path.get(), symlink);
- }
+ DanglingSymlink(RootedPath linkNamePath, PathFragment linkTargetPath,
+ FileStateValue metadata) {
+ this.type = FileType.DANGLING_SYMLINK;
+ this.symlink = new Symlink(linkNamePath, linkTargetPath);
+ this.metadata = Optional.of(metadata);
+ }
- @Override
- public PathFragment getNameInSymlinkTree() {
- return symlink.getNameInSymlinkTree();
- }
+ @Override
+ public FileType getType() {
+ return type;
+ }
- @Override
- public PathFragment getTargetInSymlinkTree(boolean followSymlinks) {
- return followSymlinks ? path.get().asPath().asFragment() : symlink.unresolvedLinkTarget;
- }
+ @Override
+ public Optional<RootedPath> getPath() {
+ return Optional.absent();
}
- private static final class SymlinkToDirectory extends ResolvedFile {
- private final Symlink symlink;
+ @Override
+ public Optional<FileStateValue> getMetadata() {
+ return metadata;
+ }
- private SymlinkToDirectory(RootedPath targetPath, Symlink symlink) {
- super(FileType.SYMLINK_TO_DIRECTORY, Optional.of(targetPath),
- Optional.<FileStateValue>absent());
- this.symlink = symlink;
+ @Override
+ public boolean equals(Object obj) {
+ if (this == obj) {
+ return true;
}
-
- SymlinkToDirectory(RootedPath targetPath, RootedPath linkNamePath,
- PathFragment linkValue, FileStateValue metadata) {
- super(FileType.SYMLINK_TO_DIRECTORY, Optional.of(targetPath), Optional.of(metadata));
- this.symlink = new Symlink(linkNamePath, linkValue);
+ if (!(obj instanceof DanglingSymlink)) {
+ return false;
}
+ DanglingSymlink o = (DanglingSymlink) obj;
+ return ResolvedFileUtils.areObjectsEqual(this, o) && symlink.equals(o.symlink);
+ }
- @Override
- public boolean equals(Object obj) {
- if (this == obj) {
- return true;
- }
- if (!(obj instanceof SymlinkToDirectory)) {
- return false;
- }
- SymlinkToDirectory o = (SymlinkToDirectory) obj;
- return super.isEqualTo(o) && symlink.equals(o.symlink);
- }
+ @Override
+ public int hashCode() {
+ return Objects.hashCode(ResolvedFileUtils.hashCodeOf(this), symlink);
+ }
- @Override
- public int hashCode() {
- return Objects.hashCode(super.hashCode(), symlink);
- }
+ @Override
+ public String toString() {
+ return String.format("DanglingSymlink(%s, %s)", ResolvedFileUtils.asString(this), symlink);
+ }
- @Override
- public String toString() {
- return String.format("SymlinkToDirectory(%s, %s)", super.toString(), symlink);
- }
+ @Override
+ public ResolvedFile stripMetadataForTesting() {
+ return new DanglingSymlink(symlink);
+ }
+
+ @Override
+ public PathFragment getNameInSymlinkTree() {
+ return symlink.getNameInSymlinkTree();
+ }
- @Override
- ResolvedFile stripMetadataForTesting() {
- return new SymlinkToDirectory(path.get(), symlink);
+ @Override
+ public PathFragment getTargetInSymlinkTree(boolean followSymlinks)
+ throws DanglingSymlinkException {
+ if (followSymlinks) {
+ throw new DanglingSymlinkException(symlink.linkName.asPath().getPathString(),
+ symlink.unresolvedLinkTarget.getPathString());
+ } else {
+ return symlink.unresolvedLinkTarget;
}
+ }
+ }
+
+ private static final class SymlinkToFile implements ResolvedFile {
+ private final FileType type;
+ private final Optional<RootedPath> path;
+ private final Optional<FileStateValue> metadata;
+
+ private final Symlink symlink;
+
+ private SymlinkToFile(RootedPath targetPath, Symlink symlink) {
+ this.type = FileType.SYMLINK_TO_FILE;
+ this.path = Optional.of(targetPath);
+ this.metadata = Optional.<FileStateValue>absent();
+ this.symlink = symlink;
+ }
+
+ SymlinkToFile(RootedPath targetPath, RootedPath linkNamePath,
+ PathFragment linkTargetPath, FileStateValue metadata) {
+ this.type = FileType.SYMLINK_TO_FILE;
+ this.path = Optional.of(targetPath);
+ this.metadata = Optional.of(metadata);
+ this.symlink = new Symlink(linkNamePath, linkTargetPath);
+ }
+
+ @Override
+ public FileType getType() {
+ return type;
+ }
+
+ @Override
+ public Optional<RootedPath> getPath() {
+ return path;
+ }
- @Override
- public PathFragment getNameInSymlinkTree() {
- return symlink.getNameInSymlinkTree();
+ @Override
+ public Optional<FileStateValue> getMetadata() {
+ return metadata;
+ }
+
+ @Override
+ public boolean equals(Object obj) {
+ if (this == obj) {
+ return true;
+ }
+ if (!(obj instanceof SymlinkToFile)) {
+ return false;
}
+ SymlinkToFile o = (SymlinkToFile) obj;
+ return ResolvedFileUtils.areObjectsEqual(this, o) && symlink.equals(o.symlink);
+ }
+
+ @Override
+ public int hashCode() {
+ return Objects.hashCode(ResolvedFileUtils.hashCodeOf(this), symlink);
+ }
- @Override
- public PathFragment getTargetInSymlinkTree(boolean followSymlinks) {
- return followSymlinks ? path.get().asPath().asFragment() : symlink.unresolvedLinkTarget;
+ @Override
+ public String toString() {
+ return String.format("SymlinkToFile(%s, %s)", ResolvedFileUtils.asString(this), symlink);
+ }
+
+ @Override
+ public ResolvedFile stripMetadataForTesting() {
+ return new SymlinkToFile(path.get(), symlink);
+ }
+
+ @Override
+ public PathFragment getNameInSymlinkTree() {
+ return symlink.getNameInSymlinkTree();
+ }
+
+ @Override
+ public PathFragment getTargetInSymlinkTree(boolean followSymlinks) {
+ return followSymlinks ? path.get().asPath().asFragment() : symlink.unresolvedLinkTarget;
+ }
+ }
+
+ private static final class SymlinkToDirectory implements ResolvedFile {
+ private final FileType type;
+ private final Optional<RootedPath> path;
+ private final Optional<FileStateValue> metadata;
+ private final Symlink symlink;
+
+ private SymlinkToDirectory(RootedPath targetPath, Symlink symlink) {
+ this.type = FileType.SYMLINK_TO_DIRECTORY;
+ this.path = Optional.of(targetPath);
+ this.metadata = Optional.<FileStateValue>absent();
+ this.symlink = symlink;
+ }
+
+ SymlinkToDirectory(RootedPath targetPath, RootedPath linkNamePath,
+ PathFragment linkValue, FileStateValue metadata) {
+ this.type = FileType.SYMLINK_TO_DIRECTORY;
+ this.path = Optional.of(targetPath);
+ this.metadata = Optional.of(metadata);
+ this.symlink = new Symlink(linkNamePath, linkValue);
+ }
+
+ @Override
+ public FileType getType() {
+ return type;
+ }
+
+ @Override
+ public Optional<RootedPath> getPath() {
+ return path;
+ }
+
+ @Override
+ public Optional<FileStateValue> getMetadata() {
+ return metadata;
+ }
+
+ @Override
+ public boolean equals(Object obj) {
+ if (this == obj) {
+ return true;
+ }
+ if (!(obj instanceof SymlinkToDirectory)) {
+ return false;
}
+ SymlinkToDirectory o = (SymlinkToDirectory) obj;
+ return ResolvedFileUtils.areObjectsEqual(this, o) && symlink.equals(o.symlink);
}
- /** Type of the entity under {@link #path}. */
- final FileType type;
+ @Override
+ public int hashCode() {
+ return Objects.hashCode(ResolvedFileUtils.hashCodeOf(this), symlink);
+ }
- /**
- * Path of the file, directory or resolved target of the symlink.
- *
- * <p>May only be absent for dangling symlinks.
- */
- protected final Optional<RootedPath> path;
+ @Override
+ public String toString() {
+ return String.format("SymlinkToDirectory(%s, %s)", ResolvedFileUtils.asString(this), symlink);
+ }
- /**
- * Associated metadata.
- *
- * <p>This field must be stored so that this {@link ResolvedFile} is (also) the function of the
- * stat() of the file, but otherwise it is likely not something the consumer of the
- * {@link ResolvedFile} is directly interested in.
- *
- * <p>May only be absent if stripped for tests.
- */
- final Optional<FileStateValue> metadata;
+ @Override
+ public ResolvedFile stripMetadataForTesting() {
+ return new SymlinkToDirectory(path.get(), symlink);
+ }
+
+ @Override
+ public PathFragment getNameInSymlinkTree() {
+ return symlink.getNameInSymlinkTree();
+ }
- private ResolvedFile(FileType type, Optional<RootedPath> path,
- Optional<FileStateValue> metadata) {
- this.type = Preconditions.checkNotNull(type);
- this.path = Preconditions.checkNotNull(path);
- this.metadata = Preconditions.checkNotNull(metadata);
+ @Override
+ public PathFragment getTargetInSymlinkTree(boolean followSymlinks) {
+ return followSymlinks ? path.get().asPath().asFragment() : symlink.unresolvedLinkTarget;
}
+ }
- static ResolvedFile regularFile(RootedPath path, FileStateValue metadata) {
+ public static final class ResolvedFileFactory {
+ private ResolvedFileFactory() {}
+
+ public static ResolvedFile regularFile(RootedPath path, FileStateValue metadata) {
return new RegularFile(path, metadata);
}
- static ResolvedFile directory(RootedPath path) {
+ public static ResolvedFile directory(RootedPath path) {
return new Directory(path);
}
- static ResolvedFile symlinkToFile(RootedPath targetPath, RootedPath linkNamePath,
+ public static ResolvedFile symlinkToFile(RootedPath targetPath, RootedPath linkNamePath,
PathFragment linkTargetPath, FileStateValue metadata) {
return new SymlinkToFile(targetPath, linkNamePath, linkTargetPath, metadata);
}
- static ResolvedFile symlinkToDirectory(RootedPath targetPath,
+ public static ResolvedFile symlinkToDirectory(RootedPath targetPath,
RootedPath linkNamePath, PathFragment linkValue, FileStateValue metadata) {
return new SymlinkToDirectory(targetPath, linkNamePath, linkValue, metadata);
}
- static ResolvedFile danglingSymlink(RootedPath linkNamePath, PathFragment linkValue,
+ public static ResolvedFile danglingSymlink(RootedPath linkNamePath, PathFragment linkValue,
FileStateValue metadata) {
return new DanglingSymlink(linkNamePath, linkValue, metadata);
}
+ }
- private boolean isEqualTo(ResolvedFile o) {
- return type.equals(o.type) && path.equals(o.path) && metadata.equals(o.metadata);
- }
+ private static final class ResolvedFileUtils {
+ private ResolvedFileUtils() {}
- @Override
- public abstract boolean equals(Object obj);
+ static boolean areObjectsEqual(ResolvedFile a, ResolvedFile b) {
+ if (a == b) {
+ return true;
+ }
+ if ((a == null) != (b == null)) {
+ return false;
+ }
+ return a.getType().equals(b.getType())
+ && a.getPath().equals(b.getPath())
+ && a.getMetadata().equals(b.getMetadata());
+ }
- @Override
- public int hashCode() {
- return Objects.hashCode(type, path, metadata);
+ static int hashCodeOf(ResolvedFile f) {
+ return Objects.hashCode(f.getType(), f.getPath(), f.getMetadata());
}
- @Override
- public String toString() {
- return String.format("type=%s, path=%s, metadata=%s", type, path,
- metadata.isPresent() ? Integer.toHexString(metadata.get().hashCode()) : "(stripped)");
+ static String asString(ResolvedFile f) {
+ return String.format(
+ "type=%s, path=%s, metadata=%s",
+ f.getType(),
+ f.getPath(),
+ f.getMetadata().isPresent()
+ ? Integer.toHexString(f.getMetadata().get().hashCode())
+ : "(stripped)");
}
+ }
+
+ /**
+ * Path and type information about a single file or symlink.
+ *
+ * <p>The object stores things such as the absolute path of the file or symlink, its exact type
+ * and, if it's a symlink, the resolved and unresolved link target paths.
+ */
+ public static interface ResolvedFile {
+ /** Type of the entity under {@link #getPath()}. */
+ FileType getType();
+
+ /**
+ * Path of the file, directory or resolved target of the symlink.
+ *
+ * <p>May only be absent for dangling symlinks.
+ */
+ Optional<RootedPath> getPath();
+
+ /**
+ * Associated metadata.
+ *
+ * <p>This field must be stored so that this {@link ResolvedFile} is (also) the function of the
+ * stat() of the file, but otherwise it is likely not something the consumer of the
+ * {@link ResolvedFile} is directly interested in.
+ *
+ * <p>May only be absent if stripped for tests.
+ */
+ Optional<FileStateValue> getMetadata();
/**
* Returns the path of the Fileset-output symlink relative to the output directory.
@@ -567,7 +689,7 @@ public final class RecursiveFilesystemTraversalValue implements SkyValue {
* <p>The path should contain the FilesetEntry-specific destination directory (if any) and
* should have necessary prefixes stripped (if any).
*/
- public abstract PathFragment getNameInSymlinkTree();
+ PathFragment getNameInSymlinkTree();
/**
* Returns the path of the symlink target.
@@ -575,8 +697,7 @@ public final class RecursiveFilesystemTraversalValue implements SkyValue {
* @throws DanglingSymlinkException if the target cannot be resolved because the symlink is
* dangling
*/
- public abstract PathFragment getTargetInSymlinkTree(boolean followSymlinks)
- throws DanglingSymlinkException;
+ PathFragment getTargetInSymlinkTree(boolean followSymlinks) throws DanglingSymlinkException;
/**
* Returns a copy of this object with the metadata stripped away.
@@ -586,7 +707,7 @@ public final class RecursiveFilesystemTraversalValue implements SkyValue {
* asserting its actual contents (which the metadata is a function of).
*/
@VisibleForTesting
- abstract ResolvedFile stripMetadataForTesting();
+ ResolvedFile stripMetadataForTesting();
}
@Override