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
diff --git a/src/main/java/com/google/devtools/build/lib/skyframe/FilesetEntryFunction.java b/src/main/java/com/google/devtools/build/lib/skyframe/FilesetEntryFunction.java
index d2e0132..c157533 100644
--- a/src/main/java/com/google/devtools/build/lib/skyframe/FilesetEntryFunction.java
+++ b/src/main/java/com/google/devtools/build/lib/skyframe/FilesetEntryFunction.java
@@ -115,7 +115,7 @@
ResolvedFile resolvedRoot = rftv.getResolvedRoot().get();
// Handle dangling symlinks gracefully be returning empty results.
- if (!resolvedRoot.type.exists()) {
+ if (!resolvedRoot.getType().exists()) {
return FilesetEntryValue.EMPTY;
}
@@ -130,7 +130,7 @@
Iterable<ResolvedFile> results = null;
if (direct.isRecursive()
- || (resolvedRoot.type.isDirectory() && !resolvedRoot.type.isSymlink())) {
+ || (resolvedRoot.getType().isDirectory() && !resolvedRoot.getType().isSymlink())) {
// The traversal is recursive (requested for an entire FilesetEntry.srcdir) or it was
// requested for a FilesetEntry.files entry which turned out to be a directory. We need to
// create an output symlink for every file in it and all of its subdirectories. Only
@@ -182,7 +182,7 @@
}
// Metadata field must be present. It can only be absent when stripped by tests.
- String metadata = Integer.toHexString(f.metadata.get().hashCode());
+ String metadata = Integer.toHexString(f.getMetadata().get().hashCode());
maybeStoreSymlink(linkName, targetName, metadata, t.getDestPath(), outputSymlinks);
}
}
diff --git a/src/main/java/com/google/devtools/build/lib/skyframe/RecursiveFilesystemTraversalFunction.java b/src/main/java/com/google/devtools/build/lib/skyframe/RecursiveFilesystemTraversalFunction.java
index 7684a59..e6df059 100644
--- a/src/main/java/com/google/devtools/build/lib/skyframe/RecursiveFilesystemTraversalFunction.java
+++ b/src/main/java/com/google/devtools/build/lib/skyframe/RecursiveFilesystemTraversalFunction.java
@@ -21,6 +21,7 @@
import com.google.devtools.build.lib.events.Event;
import com.google.devtools.build.lib.events.EventKind;
import com.google.devtools.build.lib.skyframe.RecursiveFilesystemTraversalValue.ResolvedFile;
+import com.google.devtools.build.lib.skyframe.RecursiveFilesystemTraversalValue.ResolvedFileFactory;
import com.google.devtools.build.lib.skyframe.RecursiveFilesystemTraversalValue.TraversalRequest;
import com.google.devtools.build.lib.vfs.Dirent;
import com.google.devtools.build.lib.vfs.Path;
@@ -342,7 +343,7 @@
Preconditions.checkState(info.type.isSymlink() && !info.type.exists(), "{%s} {%s}", linkName,
info.type);
return RecursiveFilesystemTraversalValue.of(
- ResolvedFile.danglingSymlink(linkName, info.unresolvedSymlinkTarget, info.metadata));
+ ResolvedFileFactory.danglingSymlink(linkName, info.unresolvedSymlinkTarget, info.metadata));
}
/**
@@ -356,10 +357,12 @@
Preconditions.checkState(info.type.isFile() && info.type.exists(), "{%s} {%s}", path,
info.type);
if (info.type.isSymlink()) {
- return RecursiveFilesystemTraversalValue.of(ResolvedFile.symlinkToFile(info.realPath, path,
- info.unresolvedSymlinkTarget, info.metadata));
+ return RecursiveFilesystemTraversalValue.of(
+ ResolvedFileFactory.symlinkToFile(
+ info.realPath, path, info.unresolvedSymlinkTarget, info.metadata));
} else {
- return RecursiveFilesystemTraversalValue.of(ResolvedFile.regularFile(path, info.metadata));
+ return RecursiveFilesystemTraversalValue.of(
+ ResolvedFileFactory.regularFile(path, info.metadata));
}
}
@@ -372,11 +375,15 @@
}
ResolvedFile root;
if (rootInfo.type.isSymlink()) {
- root = ResolvedFile.symlinkToDirectory(rootInfo.realPath, traversal.path,
- rootInfo.unresolvedSymlinkTarget, rootInfo.metadata);
+ root =
+ ResolvedFileFactory.symlinkToDirectory(
+ rootInfo.realPath,
+ traversal.path,
+ rootInfo.unresolvedSymlinkTarget,
+ rootInfo.metadata);
paths.add(root);
} else {
- root = ResolvedFile.directory(rootInfo.realPath);
+ root = ResolvedFileFactory.directory(rootInfo.realPath);
}
return RecursiveFilesystemTraversalValue.of(root, paths.build());
}
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 e69de72..33ce1f1 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,303 +204,473 @@
}
}
+ 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();
+ }
+
+ @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 int hashCode() {
+ return Objects.hashCode(linkName, unresolvedLinkTarget);
+ }
+
+ @Override
+ public String toString() {
+ return String.format("Symlink(link_name=%s, unresolved_target=%s)",
+ linkName, unresolvedLinkTarget);
+ }
+ }
+
+ private static final class RegularFile implements ResolvedFile {
+ private final FileType type;
+ private final Optional<RootedPath> path;
+ private final Optional<FileStateValue> metadata;
+
+ private RegularFile(RootedPath path) {
+ this.type = FileType.FILE;
+ this.path = Optional.of(path);
+ this.metadata = Optional.<FileStateValue>absent();
+ }
+
+ RegularFile(RootedPath path, FileStateValue metadata) {
+ this.type = FileType.FILE;
+ this.path = Optional.of(path);
+ this.metadata = Optional.of(metadata);
+ }
+
+ @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 RegularFile)) {
+ return false;
+ }
+ return ResolvedFileUtils.areObjectsEqual(this, (RegularFile) obj);
+ }
+
+ @Override
+ public int hashCode() {
+ return ResolvedFileUtils.hashCodeOf(this);
+ }
+
+ @Override
+ public String toString() {
+ return String.format("RegularFile(%s)", ResolvedFileUtils.asString(this));
+ }
+
+ @Override
+ public ResolvedFile stripMetadataForTesting() {
+ return new RegularFile(path.get());
+ }
+
+ @Override
+ public PathFragment getNameInSymlinkTree() {
+ return path.get().getRelativePath();
+ }
+
+ @Override
+ public PathFragment getTargetInSymlinkTree(boolean followSymlinks) {
+ return path.get().asPath().asFragment();
+ }
+ }
+
+ private static final class Directory implements ResolvedFile {
+ private final FileType type;
+ private final Optional<RootedPath> path;
+
+ Directory(RootedPath path) {
+ this.type = FileType.DIRECTORY;
+ this.path = Optional.of(path);
+ }
+
+ @Override
+ public FileType getType() {
+ return type;
+ }
+
+ @Override
+ public Optional<RootedPath> getPath() {
+ return path;
+ }
+
+ @Override
+ public Optional<FileStateValue> getMetadata() {
+ return Optional.<FileStateValue>of(FileStateValue.DIRECTORY_FILE_STATE_NODE);
+ }
+
+ @Override
+ public boolean equals(Object obj) {
+ if (this == obj) {
+ return true;
+ }
+ if (!(obj instanceof Directory)) {
+ return false;
+ }
+ return ResolvedFileUtils.areObjectsEqual(this, (Directory) obj);
+ }
+
+ @Override
+ public int hashCode() {
+ return ResolvedFileUtils.hashCodeOf(this);
+ }
+
+ @Override
+ public String toString() {
+ return String.format("Directory(%s)", ResolvedFileUtils.asString(this));
+ }
+
+ @Override
+ public ResolvedFile stripMetadataForTesting() {
+ return this;
+ }
+
+ @Override
+ public PathFragment getNameInSymlinkTree() {
+ return path.get().getRelativePath();
+ }
+
+ @Override
+ public PathFragment getTargetInSymlinkTree(boolean followSymlinks) {
+ return path.get().asPath().asFragment();
+ }
+ }
+
+ private static final class DanglingSymlink implements ResolvedFile {
+ private final FileType type;
+ private final Symlink symlink;
+ private final Optional<FileStateValue> metadata;
+
+ private DanglingSymlink(Symlink symlink) {
+ this.type = FileType.DANGLING_SYMLINK;
+ this.symlink = symlink;
+ this.metadata = Optional.absent();
+ }
+
+ 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 FileType getType() {
+ return type;
+ }
+
+ @Override
+ public Optional<RootedPath> getPath() {
+ return Optional.absent();
+ }
+
+ @Override
+ public Optional<FileStateValue> getMetadata() {
+ return metadata;
+ }
+
+ @Override
+ public boolean equals(Object obj) {
+ if (this == obj) {
+ return true;
+ }
+ if (!(obj instanceof DanglingSymlink)) {
+ return false;
+ }
+ DanglingSymlink o = (DanglingSymlink) obj;
+ return ResolvedFileUtils.areObjectsEqual(this, o) && symlink.equals(o.symlink);
+ }
+
+ @Override
+ public int hashCode() {
+ return Objects.hashCode(ResolvedFileUtils.hashCodeOf(this), symlink);
+ }
+
+ @Override
+ public String toString() {
+ return String.format("DanglingSymlink(%s, %s)", ResolvedFileUtils.asString(this), symlink);
+ }
+
+ @Override
+ public ResolvedFile stripMetadataForTesting() {
+ return new DanglingSymlink(symlink);
+ }
+
+ @Override
+ public PathFragment getNameInSymlinkTree() {
+ return symlink.getNameInSymlinkTree();
+ }
+
+ @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 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 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);
+ }
+
+ @Override
+ public int hashCode() {
+ return Objects.hashCode(ResolvedFileUtils.hashCodeOf(this), symlink);
+ }
+
+ @Override
+ public String toString() {
+ return String.format("SymlinkToDirectory(%s, %s)", ResolvedFileUtils.asString(this), symlink);
+ }
+
+ @Override
+ public ResolvedFile stripMetadataForTesting() {
+ return new SymlinkToDirectory(path.get(), symlink);
+ }
+
+ @Override
+ public PathFragment getNameInSymlinkTree() {
+ return symlink.getNameInSymlinkTree();
+ }
+
+ @Override
+ public PathFragment getTargetInSymlinkTree(boolean followSymlinks) {
+ return followSymlinks ? path.get().asPath().asFragment() : symlink.unresolvedLinkTarget;
+ }
+ }
+
+ public static final class ResolvedFileFactory {
+ private ResolvedFileFactory() {}
+
+ public static ResolvedFile regularFile(RootedPath path, FileStateValue metadata) {
+ return new RegularFile(path, metadata);
+ }
+
+ public static ResolvedFile directory(RootedPath path) {
+ return new Directory(path);
+ }
+
+ public static ResolvedFile symlinkToFile(RootedPath targetPath, RootedPath linkNamePath,
+ PathFragment linkTargetPath, FileStateValue metadata) {
+ return new SymlinkToFile(targetPath, linkNamePath, linkTargetPath, metadata);
+ }
+
+ public static ResolvedFile symlinkToDirectory(RootedPath targetPath,
+ RootedPath linkNamePath, PathFragment linkValue, FileStateValue metadata) {
+ return new SymlinkToDirectory(targetPath, linkNamePath, linkValue, metadata);
+ }
+
+ public static ResolvedFile danglingSymlink(RootedPath linkNamePath, PathFragment linkValue,
+ FileStateValue metadata) {
+ return new DanglingSymlink(linkNamePath, linkValue, metadata);
+ }
+ }
+
+ private static final class ResolvedFileUtils {
+ private ResolvedFileUtils() {}
+
+ 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());
+ }
+
+ static int hashCodeOf(ResolvedFile f) {
+ return Objects.hashCode(f.getType(), f.getPath(), f.getMetadata());
+ }
+
+ 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 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);
- }
-
- 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 int hashCode() {
- return Objects.hashCode(linkName, unresolvedLinkTarget);
- }
-
- @Override
- public String toString() {
- return String.format("Symlink(link_name=%s, unresolved_target=%s)",
- linkName, unresolvedLinkTarget);
- }
- }
-
- private static final class RegularFile extends ResolvedFile {
- private RegularFile(RootedPath path) {
- super(FileType.FILE, Optional.of(path), Optional.<FileStateValue>absent());
- }
-
- RegularFile(RootedPath path, FileStateValue metadata) {
- super(FileType.FILE, Optional.of(path), Optional.of(metadata));
- }
-
- @Override
- public boolean equals(Object obj) {
- if (this == obj) {
- return true;
- }
- if (!(obj instanceof RegularFile)) {
- return false;
- }
- return super.isEqualTo((RegularFile) obj);
- }
-
- @Override
- public String toString() {
- return String.format("RegularFile(%s)", super.toString());
- }
-
- @Override
- ResolvedFile stripMetadataForTesting() {
- return new RegularFile(path.get());
- }
-
- @Override
- public PathFragment getNameInSymlinkTree() {
- return path.get().getRelativePath();
- }
-
- @Override
- public PathFragment getTargetInSymlinkTree(boolean followSymlinks) {
- return path.get().asPath().asFragment();
- }
- }
-
- 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;
- }
- if (!(obj instanceof Directory)) {
- return false;
- }
- return super.isEqualTo((Directory) obj);
- }
-
- @Override
- public String toString() {
- return String.format("Directory(%s)", super.toString());
- }
-
- @Override
- ResolvedFile stripMetadataForTesting() {
- return this;
- }
-
- @Override
- public PathFragment getNameInSymlinkTree() {
- return path.get().getRelativePath();
- }
-
- @Override
- public PathFragment getTargetInSymlinkTree(boolean followSymlinks) {
- return path.get().asPath().asFragment();
- }
- }
-
- private static final class DanglingSymlink extends ResolvedFile {
- private final Symlink symlink;
-
- private DanglingSymlink(Symlink symlink) {
- super(FileType.DANGLING_SYMLINK, Optional.<RootedPath>absent(),
- Optional.<FileStateValue>absent());
- this.symlink = symlink;
- }
-
- DanglingSymlink(RootedPath linkNamePath, PathFragment linkTargetPath,
- FileStateValue metadata) {
- super(FileType.DANGLING_SYMLINK, Optional.<RootedPath>absent(), Optional.of(metadata));
- this.symlink = new Symlink(linkNamePath, linkTargetPath);
- }
-
- @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 int hashCode() {
- return Objects.hashCode(super.hashCode(), symlink);
- }
-
- @Override
- public String toString() {
- return String.format("DanglingSymlink(%s, %s)", super.toString(), symlink);
- }
-
- @Override
- ResolvedFile stripMetadataForTesting() {
- return new DanglingSymlink(symlink);
- }
-
- @Override
- public PathFragment getNameInSymlinkTree() {
- return symlink.getNameInSymlinkTree();
- }
-
- @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 extends ResolvedFile {
- private final Symlink symlink;
-
- private SymlinkToFile(RootedPath targetPath, Symlink symlink) {
- super(FileType.SYMLINK_TO_FILE, Optional.of(targetPath), Optional.<FileStateValue>absent());
- this.symlink = symlink;
- }
-
- 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 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 int hashCode() {
- return Objects.hashCode(super.hashCode(), symlink);
- }
-
- @Override
- public String toString() {
- return String.format("SymlinkToFile(%s, %s)", super.toString(), symlink);
- }
-
- @Override
- 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 extends ResolvedFile {
- private final Symlink symlink;
-
- private SymlinkToDirectory(RootedPath targetPath, Symlink symlink) {
- super(FileType.SYMLINK_TO_DIRECTORY, Optional.of(targetPath),
- Optional.<FileStateValue>absent());
- this.symlink = symlink;
- }
-
- 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);
- }
-
- @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(super.hashCode(), symlink);
- }
-
- @Override
- public String toString() {
- return String.format("SymlinkToDirectory(%s, %s)", super.toString(), symlink);
- }
-
- @Override
- ResolvedFile stripMetadataForTesting() {
- return new SymlinkToDirectory(path.get(), symlink);
- }
-
- @Override
- public PathFragment getNameInSymlinkTree() {
- return symlink.getNameInSymlinkTree();
- }
-
- @Override
- public PathFragment getTargetInSymlinkTree(boolean followSymlinks) {
- return followSymlinks ? path.get().asPath().asFragment() : symlink.unresolvedLinkTarget;
- }
- }
-
- /** Type of the entity under {@link #path}. */
- final FileType type;
+ 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.
*/
- protected final Optional<RootedPath> path;
+ Optional<RootedPath> getPath();
/**
* Associated metadata.
@@ -511,55 +681,7 @@
*
* <p>May only be absent if stripped for tests.
*/
- final Optional<FileStateValue> metadata;
-
- 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);
- }
-
- static ResolvedFile regularFile(RootedPath path, FileStateValue metadata) {
- return new RegularFile(path, metadata);
- }
-
- static ResolvedFile directory(RootedPath path) {
- return new Directory(path);
- }
-
- static ResolvedFile symlinkToFile(RootedPath targetPath, RootedPath linkNamePath,
- PathFragment linkTargetPath, FileStateValue metadata) {
- return new SymlinkToFile(targetPath, linkNamePath, linkTargetPath, metadata);
- }
-
- 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,
- 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);
- }
-
- @Override
- public abstract boolean equals(Object obj);
-
- @Override
- public int hashCode() {
- return Objects.hashCode(type, path, metadata);
- }
-
- @Override
- public String toString() {
- return String.format("type=%s, path=%s, metadata=%s", type, path,
- metadata.isPresent() ? Integer.toHexString(metadata.get().hashCode()) : "(stripped)");
- }
+ Optional<FileStateValue> getMetadata();
/**
* Returns the path of the Fileset-output symlink relative to the output directory.
@@ -567,7 +689,7 @@
* <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 @@
* @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 @@
* asserting its actual contents (which the metadata is a function of).
*/
@VisibleForTesting
- abstract ResolvedFile stripMetadataForTesting();
+ ResolvedFile stripMetadataForTesting();
}
@Override
diff --git a/src/test/java/com/google/devtools/build/lib/skyframe/RecursiveFilesystemTraversalFunctionTest.java b/src/test/java/com/google/devtools/build/lib/skyframe/RecursiveFilesystemTraversalFunctionTest.java
index d94b8dd..05fdbc7 100644
--- a/src/test/java/com/google/devtools/build/lib/skyframe/RecursiveFilesystemTraversalFunctionTest.java
+++ b/src/test/java/com/google/devtools/build/lib/skyframe/RecursiveFilesystemTraversalFunctionTest.java
@@ -30,6 +30,7 @@
import com.google.devtools.build.lib.events.NullEventHandler;
import com.google.devtools.build.lib.pkgcache.PathPackageLocator;
import com.google.devtools.build.lib.skyframe.RecursiveFilesystemTraversalValue.ResolvedFile;
+import com.google.devtools.build.lib.skyframe.RecursiveFilesystemTraversalValue.ResolvedFileFactory;
import com.google.devtools.build.lib.skyframe.RecursiveFilesystemTraversalValue.TraversalRequest;
import com.google.devtools.build.lib.testutil.FoundationTestCaseForJunit4;
import com.google.devtools.build.lib.util.BlazeClock;
@@ -295,26 +296,26 @@
}
private ResolvedFile resolvedFile(RootedPath path) throws Exception {
- return ResolvedFile.regularFile(path, FileStateValue.create(path, tsgm));
+ return ResolvedFileFactory.regularFile(path, FileStateValue.create(path, tsgm));
}
private ResolvedFile resolvedDanglingSymlink(RootedPath linkNamePath, PathFragment linkTargetPath)
throws Exception {
- return ResolvedFile.danglingSymlink(
+ return ResolvedFileFactory.danglingSymlink(
linkNamePath, linkTargetPath, FileStateValue.create(linkNamePath, tsgm));
}
private ResolvedFile resolvedSymlinkToFile(
RootedPath targetPath, RootedPath linkNamePath, PathFragment linkTargetPath)
throws Exception {
- return ResolvedFile.symlinkToFile(
+ return ResolvedFileFactory.symlinkToFile(
targetPath, linkNamePath, linkTargetPath, FileStateValue.create(linkNamePath, tsgm));
}
private ResolvedFile resolvedSymlinkToDir(
RootedPath targetPath, RootedPath linkNamePath, PathFragment linkTargetPath)
throws Exception {
- return ResolvedFile.symlinkToDirectory(
+ return ResolvedFileFactory.symlinkToDirectory(
targetPath, linkNamePath, linkTargetPath, FileStateValue.create(linkNamePath, tsgm));
}