From 4260c15aca7b627d7de7f7ce060d262f5fa59b2b Mon Sep 17 00:00:00 2001 From: Tiago Quelhas Date: Mon, 27 Nov 2023 15:29:51 +0100 Subject: [PATCH] [7.0.0] Follow symlinks for setLastModifiedTime. (#20321) The method is documented as such in FileSystem. PiperOrigin-RevId: 585581298 Change-Id: I9838d97747f820784db2f9fd68425d4d27b8b857 --- .../lib/remote/RemoteActionFileSystem.java | 2 + .../remote/RemoteActionFileSystemTest.java | 45 +++++++++++++++++++ 2 files changed, 47 insertions(+) diff --git a/src/main/java/com/google/devtools/build/lib/remote/RemoteActionFileSystem.java b/src/main/java/com/google/devtools/build/lib/remote/RemoteActionFileSystem.java index a140534a63f2df..755c8a04c3bf72 100644 --- a/src/main/java/com/google/devtools/build/lib/remote/RemoteActionFileSystem.java +++ b/src/main/java/com/google/devtools/build/lib/remote/RemoteActionFileSystem.java @@ -316,6 +316,8 @@ protected SeekableByteChannel createReadWriteByteChannel(PathFragment path) thro @Override public void setLastModifiedTime(PathFragment path, long newTime) throws IOException { + path = resolveSymbolicLinks(path).asFragment(); + FileNotFoundException remoteException = null; try { // We can't set mtime for a remote file, set mtime of in-memory file node instead. diff --git a/src/test/java/com/google/devtools/build/lib/remote/RemoteActionFileSystemTest.java b/src/test/java/com/google/devtools/build/lib/remote/RemoteActionFileSystemTest.java index 9cd140611c67c2..1f4dec4453dae8 100644 --- a/src/test/java/com/google/devtools/build/lib/remote/RemoteActionFileSystemTest.java +++ b/src/test/java/com/google/devtools/build/lib/remote/RemoteActionFileSystemTest.java @@ -460,6 +460,51 @@ public void statAndExists_notFound() throws Exception { FileNotFoundException.class, () -> actionFs.stat(path, /* followSymlinks= */ true)); } + @Test + public void setLastModifiedTime_forRemoteOutputTree() throws Exception { + RemoteActionFileSystem actionFs = (RemoteActionFileSystem) createActionFileSystem(); + Artifact artifact = ActionsTestUtil.createArtifact(outputRoot, "out"); + PathFragment path = artifact.getPath().asFragment(); + injectRemoteFile(actionFs, artifact.getPath().asFragment(), "remote contents"); + + actionFs.getPath(path).setLastModifiedTime(1234567890); + assertThat(actionFs.getPath(path).getLastModifiedTime()).isEqualTo(1234567890); + } + + @Test + public void setLastModifiedTime_forLocalFilesystem() throws Exception { + RemoteActionFileSystem actionFs = (RemoteActionFileSystem) createActionFileSystem(); + Artifact artifact = ActionsTestUtil.createArtifact(outputRoot, "out"); + PathFragment path = artifact.getPath().asFragment(); + writeLocalFile(actionFs, artifact.getPath().asFragment(), "local contents"); + + actionFs.getPath(path).setLastModifiedTime(1234567890); + assertThat(actionFs.getPath(path).getLastModifiedTime()).isEqualTo(1234567890); + } + + @Test + public void setLastModifiedTime_followSymlinks( + @TestParameter FilesystemTestParam from, @TestParameter FilesystemTestParam to) + throws Exception { + RemoteActionFileSystem actionFs = (RemoteActionFileSystem) createActionFileSystem(); + FileSystem fromFs = from.getFilesystem(actionFs); + FileSystem toFs = to.getFilesystem(actionFs); + + PathFragment linkPath = getOutputPath("sym"); + PathFragment targetPath = getOutputPath("target"); + fromFs.getPath(linkPath).createSymbolicLink(execRoot.getRelative(targetPath).asFragment()); + + if (toFs.equals(actionFs.getLocalFileSystem())) { + writeLocalFile(actionFs, targetPath, "content"); + } else { + injectRemoteFile(actionFs, targetPath, "content"); + } + + actionFs.getPath(linkPath).setLastModifiedTime(1234567890); + assertThat(actionFs.getPath(linkPath).getLastModifiedTime()).isEqualTo(1234567890); + assertThat(actionFs.getPath(targetPath).getLastModifiedTime()).isEqualTo(1234567890); + } + @Test public void getDigest_fromInputArtifactData_forLocalArtifact() throws Exception { ActionInputMap inputs = new ActionInputMap(1);