Skip to content

Commit

Permalink
fix (jkube-kit) : lastModified timestamps should be preserved while p…
Browse files Browse the repository at this point in the history
…reparing assembly

We don't seem to be preserving lastModified timestamps of files that are
being copied while preparing the assembly for image. Make sure we're
copying all the metadata of files/directories as well while copying
them.

Signed-off-by: Rohan Kumar <[email protected]>
  • Loading branch information
rohanKanojia committed Sep 29, 2023
1 parent 0662bcc commit c77ce8d
Show file tree
Hide file tree
Showing 4 changed files with 88 additions and 2 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -169,8 +169,10 @@ private static List<AssemblyFileEntry> copy(Path sourceDirectory, File source, F
for (File sourceChild : Optional.ofNullable(source.listFiles()).orElse(new File[0])) {
copy(sourceDirectory, sourceChild, new File(target, sourceChild.getName()), assemblyFileSet);
}
FileUtil.updateLastModifiedTimestamp(target, source.lastModified());
} else {
FileUtil.copy(source, target);
FileUtil.updateLastModifiedTimestamp(target.getParentFile(), source.getParentFile().lastModified());
}
return calculateFilePermissions(source, target, assemblyFileSet);
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,7 @@
import java.util.stream.Collectors;
import java.util.stream.Stream;

import static java.nio.file.StandardCopyOption.COPY_ATTRIBUTES;
import static java.nio.file.StandardCopyOption.REPLACE_EXISTING;

/**
Expand Down Expand Up @@ -201,7 +202,7 @@ public static void copy(File sourceFile, File targetFile) throws IOException {
}

public static void copy(Path sourcePath, Path targetPath) throws IOException {
Files.copy(sourcePath, targetPath, REPLACE_EXISTING);
Files.copy(sourcePath, targetPath, REPLACE_EXISTING, COPY_ATTRIBUTES);
}

public static void copyDirectoryIfNotExists(File sourceDir, File targetDir) throws IOException {
Expand Down Expand Up @@ -252,5 +253,12 @@ public static void createDirectory(File directory) throws IOException {
throw new IOException("Failed to create directory: " + directory.getAbsolutePath());
}
}

public static void updateLastModifiedTimestamp(File file, long timestamp) {
boolean parentLastModifiedUpdated = file.setLastModified(timestamp);
if (!parentLastModifiedUpdated) {
throw new IllegalStateException("Not able to update last modified timestamp of " + file.getPath());
}
}
}

Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@
import java.io.File;
import java.io.IOException;
import java.nio.file.Files;
import java.util.Date;
import java.util.List;
import java.util.stream.Collectors;
import java.util.stream.Stream;
Expand Down Expand Up @@ -47,18 +48,22 @@ class AssemblyFileSetUtilsProcessAssemblyFileSetTest {
private File baseDirectory;
private File sourceDirectory;
private File outputDirectory;
private static long sourceFilesTimestamp;

@BeforeEach
public void setUp() throws Exception {
assumeFalse(isWindows());
baseDirectory = new File(temp, "base");
sourceFilesTimestamp = new Date().getTime() - 10;
sourceDirectory = new File(baseDirectory, "source-directory");
final List<File> sourceSubdirectories = Stream.of("one", "two", "three")
.map(s -> new File(sourceDirectory, s)).collect(Collectors.toList());
for (File directory : Stream.concat(Stream.of(baseDirectory, sourceDirectory), sourceSubdirectories.stream()).collect(Collectors.toList())) {
FileUtils.forceMkdir(directory);
populateSampleFiles(directory);
assertThat(directory.setLastModified(sourceFilesTimestamp)).isTrue();
}
assertThat(sourceDirectory.setLastModified(sourceFilesTimestamp)).isTrue();
outputDirectory = new File(temp, "output");
}

Expand All @@ -71,7 +76,9 @@ public void tearDown() {

private static void populateSampleFiles(File baseDirectory) throws IOException {
for (String fileName : new String[]{"1.txt", "3.other", "37"}) {
FileUtils.touch(new File(baseDirectory, fileName));
File file = new File(baseDirectory, fileName);
FileUtils.touch(file);
assertThat(file.setLastModified(sourceFilesTimestamp)).isTrue();
}
}

Expand Down Expand Up @@ -566,4 +573,26 @@ void withRelativeSourceAndDirectoryExcludes() throws Exception {
);
}

@Test
void timestampsPreservedWhilePreparingAssembly() throws IOException {
// Given
final AssemblyFileSet afs = AssemblyFileSet.builder()
.directory(sourceDirectory)
.build();
final Assembly layer = new Assembly();
final AssemblyConfiguration ac = AssemblyConfiguration.builder()
.targetDir("deployments")
.build();
// When
final List<AssemblyFileEntry> result = processAssemblyFileSet(baseDirectory, outputDirectory, afs, layer, ac);
// Then
assertThat(result).hasSize(16);
File assemblyFileSetOutput = new File(outputDirectory, "deployments");
FileAssertions.assertThat(assemblyFileSetOutput)
.exists()
.fileTree()
.filteredOn(p -> new File(assemblyFileSetOutput, p).lastModified() != sourceFilesTimestamp)
.isEmpty();
}

}
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,10 @@

import java.io.File;
import java.io.IOException;
import java.nio.charset.StandardCharsets;
import java.nio.file.Files;
import java.nio.file.Path;
import java.util.Date;
import java.util.List;

import org.junit.jupiter.api.Test;
Expand All @@ -25,6 +28,7 @@
import org.junit.jupiter.api.condition.OS;

import static org.assertj.core.api.Assertions.assertThat;
import static org.assertj.core.api.Assertions.assertThatIllegalStateException;
import static org.eclipse.jkube.kit.common.util.FileUtil.getRelativeFilePath;
import static org.eclipse.jkube.kit.common.util.FileUtil.getRelativePath;

Expand Down Expand Up @@ -151,6 +155,49 @@ void testGetRelativePath() throws IOException {
assertThat(relativeFile.getPath()).isEqualTo("foo" + File.separator + "fileInFoo1");
}

@Test
void copy_whenFileCopied_shouldPreserveLastModifiedTimestamp() throws IOException {
// Given
File sourceFile = new File(folder, "source");
Files.write(sourceFile.toPath(), "testdata".getBytes(StandardCharsets.UTF_8));
long originalTimestamp = new Date().getTime() - 10;
assertThat(sourceFile.setLastModified(originalTimestamp)).isTrue();
Path targetFilePath = folder.toPath().resolve("target");

// When
FileUtil.copy(sourceFile.toPath(), targetFilePath);

// Then
assertThat(targetFilePath.toFile()).hasSameTextualContentAs(sourceFile);
assertThat(targetFilePath.toFile().lastModified()).isEqualTo(originalTimestamp);
}

@Test
void updateLastModifiedTimestamp_whenInvokedOnValidFile_shouldUpdateLastModifiedAttribute() throws IOException {
// Given
File sourceFile = new File(folder, "source");
Files.createFile(sourceFile.toPath());
long timestamp = new Date().getTime() - 10;

// When
FileUtil.updateLastModifiedTimestamp(sourceFile, timestamp);

// Then
assertThat(sourceFile.lastModified()).isEqualTo(timestamp);
}

@Test
void updateLastModifiedTimestamp_whenInvokedOnNonExistentFile_shouldThrowException() {
// Given
File sourceFile = new File(folder, "source");
long timestamp = new Date().getTime() - 10;

// When + Then
assertThatIllegalStateException()
.isThrownBy(() -> FileUtil.updateLastModifiedTimestamp(sourceFile, timestamp))
.withMessage("Not able to update last modified timestamp of " + sourceFile.getPath());
}

private void prepareDirectory() throws IOException {
final File dir1 = Files.createDirectories(folder.toPath().resolve("foo")).toFile();
assertThat(new File(dir1, "fileInFoo1").createNewFile()).isTrue();
Expand Down

0 comments on commit c77ce8d

Please sign in to comment.