Skip to content

Commit

Permalink
Browse files Browse the repository at this point in the history
JENKINS-13128: Preserve copied file permissions and mtime (#3400)
* JENKINS-13128: Preserve copied file permissions and mtime

This fixes a bug where files copied locally do not preserve file permissions or last modification time.

* Use IO utility methods for exception handling

* Fix invalid path exception propagation

* Revert hudson.Util
  • Loading branch information
jvz authored and dwnusbaum committed May 4, 2018
1 parent a9eafdb commit e229f37
Show file tree
Hide file tree
Showing 3 changed files with 40 additions and 2 deletions.
3 changes: 2 additions & 1 deletion core/src/main/java/hudson/FilePath.java
Expand Up @@ -2283,7 +2283,8 @@ public void visit(File f, String relativePath) throws IOException {
if (f.isFile()) {
File target = new File(dest, relativePath);
mkdirsE(target.getParentFile());
Util.copyFile(f, writing(target));
Files.copy(fileToPath(f), fileToPath(writing(target)),
StandardCopyOption.COPY_ATTRIBUTES, StandardCopyOption.REPLACE_EXISTING);
count.incrementAndGet();
}
}
Expand Down
5 changes: 4 additions & 1 deletion core/src/main/java/hudson/model/ItemGroupMixIn.java
Expand Up @@ -45,6 +45,8 @@
import java.io.FileFilter;
import java.io.IOException;
import java.io.InputStream;
import java.nio.file.Files;
import java.nio.file.StandardCopyOption;
import java.util.Map;
import java.util.logging.Level;
import java.util.logging.Logger;
Expand Down Expand Up @@ -239,7 +241,8 @@ public synchronized <T extends TopLevelItem> T copy(T src, String name) throws I
T result = (T)createProject(src.getDescriptor(),name,false);

// copy config
Util.copyFile(srcConfigFile.getFile(), Items.getConfigFile(result).getFile());
Files.copy(Util.fileToPath(srcConfigFile.getFile()), Util.fileToPath(Items.getConfigFile(result).getFile()),
StandardCopyOption.COPY_ATTRIBUTES, StandardCopyOption.REPLACE_EXISTING);

// reload from the new config
final File rootDir = result.getRootDir();
Expand Down
34 changes: 34 additions & 0 deletions core/src/test/java/hudson/FilePathTest.java
Expand Up @@ -43,15 +43,19 @@
import java.net.URLStreamHandler;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.attribute.FileTime;
import java.nio.file.attribute.PosixFilePermission;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.EnumSet;
import java.util.HashSet;
import java.util.List;
import java.util.Set;
import java.util.concurrent.Callable;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.Future;
import java.util.concurrent.TimeUnit;
import java.util.zip.ZipEntry;
import java.util.zip.ZipOutputStream;
import org.apache.commons.io.FileUtils;
Expand Down Expand Up @@ -845,4 +849,34 @@ public void testCreateTempDir() throws IOException, InterruptedException {
assertTrue("junction target contents should not be deleted", Files.exists(targetContents));
assertFalse("could not delete target", Files.exists(toDelete));
}

@Issue("JENKINS-13128")
@Test public void copyRecursivePreservesPosixFilePermissions() throws Exception {
assumeFalse("windows doesn't support posix file permissions", Functions.isWindows());
File src = temp.newFolder("src");
File dst = temp.newFolder("dst");
Path sourceFile = Files.createFile(src.toPath().resolve("test-file"));
Set<PosixFilePermission> allRWX = EnumSet.allOf(PosixFilePermission.class);
Files.setPosixFilePermissions(sourceFile, allRWX);
FilePath f = new FilePath(src);
f.copyRecursiveTo(new FilePath(dst));
Path destinationFile = dst.toPath().resolve("test-file");
assertTrue("file was not copied", Files.exists(destinationFile));
Set<PosixFilePermission> destinationPermissions = Files.getPosixFilePermissions(destinationFile);
assertEquals("file permissions not copied", allRWX, destinationPermissions);
}

@Issue("JENKINS-13128")
@Test public void copyRecursivePreservesLastModifiedTime() throws Exception {
File src = temp.newFolder("src");
File dst = temp.newFolder("dst");
Path sourceFile = Files.createFile(src.toPath().resolve("test-file"));
FileTime mtime = FileTime.from(42L, TimeUnit.SECONDS);
Files.setLastModifiedTime(sourceFile, mtime);
FilePath f = new FilePath(src);
f.copyRecursiveTo(new FilePath(dst));
Path destinationFile = dst.toPath().resolve("test-file");
assertTrue("file was not copied", Files.exists(destinationFile));
assertEquals("file mtime was not preserved", mtime, Files.getLastModifiedTime(destinationFile));
}
}

0 comments on commit e229f37

Please sign in to comment.