From 5530fad7140810df01ce57bbc0dec6fa7a8e146f Mon Sep 17 00:00:00 2001 From: Richard North Date: Sun, 29 Jul 2018 16:53:24 +0100 Subject: [PATCH 1/4] Fix #680: Ensure that tar entries for Dockerfile builder do not have trailing slashes --- .../java/org/testcontainers/utility/MountableFile.java | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/core/src/main/java/org/testcontainers/utility/MountableFile.java b/core/src/main/java/org/testcontainers/utility/MountableFile.java index 795917fffc4..f45209a18e7 100644 --- a/core/src/main/java/org/testcontainers/utility/MountableFile.java +++ b/core/src/main/java/org/testcontainers/utility/MountableFile.java @@ -301,7 +301,14 @@ private void recursiveTar(String entryFilename, String rootPath, String itemPath final File sourceRootFile = new File(rootPath).getCanonicalFile(); // e.g. /foo final String relativePathToSourceFile = sourceRootFile.toPath().relativize(sourceFile.toPath()).toFile().toString(); // e.g. /bar/baz - final TarArchiveEntry tarEntry = new TarArchiveEntry(sourceFile, entryFilename + "/" + relativePathToSourceFile); // entry filename e.g. /xyz/bar/baz + final String tarEntryFilename; + if (relativePathToSourceFile.isEmpty()) { + tarEntryFilename = entryFilename; // entry filename e.g. xyz => xyz + } else { + tarEntryFilename = entryFilename + "/" + relativePathToSourceFile; // entry filename e.g. /xyz/bar/baz => /foo/bar/baz + } + + final TarArchiveEntry tarEntry = new TarArchiveEntry(sourceFile, tarEntryFilename); // TarArchiveEntry automatically sets the mode for file/directory, but we can update to ensure that the mode is set exactly (inc executable bits) tarEntry.setMode(getUnixFileMode(itemPath)); From 5a68cb1640c68c2fab5457ed3fae1891dc646d1e Mon Sep 17 00:00:00 2001 From: Richard North Date: Sun, 29 Jul 2018 17:07:57 +0100 Subject: [PATCH 2/4] Add a regression test --- .../utility/MountableFileTest.java | 37 +++++++++++++++++-- 1 file changed, 33 insertions(+), 4 deletions(-) diff --git a/core/src/test/java/org/testcontainers/utility/MountableFileTest.java b/core/src/test/java/org/testcontainers/utility/MountableFileTest.java index 9b1fbb55a53..750cfab9088 100644 --- a/core/src/test/java/org/testcontainers/utility/MountableFileTest.java +++ b/core/src/test/java/org/testcontainers/utility/MountableFileTest.java @@ -1,16 +1,20 @@ package org.testcontainers.utility; +import org.apache.commons.compress.archivers.ArchiveEntry; +import org.apache.commons.compress.archivers.tar.TarArchiveInputStream; +import org.apache.commons.compress.archivers.tar.TarArchiveOutputStream; import org.jetbrains.annotations.NotNull; import org.junit.Test; +import java.io.ByteArrayInputStream; +import java.io.ByteArrayOutputStream; import java.io.File; import java.io.IOException; import java.nio.file.Files; import java.nio.file.Path; +import java.util.function.Consumer; -import static org.rnorth.visibleassertions.VisibleAssertions.assertEquals; -import static org.rnorth.visibleassertions.VisibleAssertions.assertFalse; -import static org.rnorth.visibleassertions.VisibleAssertions.assertTrue; +import static org.rnorth.visibleassertions.VisibleAssertions.*; public class MountableFileTest { @@ -79,7 +83,7 @@ public void forHostPathWithPlus() throws Exception { @Test public void forClasspathResourceWithPermission() throws Exception { final MountableFile mountableFile = MountableFile.forClasspathResource("mappable-resource/test-resource.txt", - TEST_FILE_MODE); + TEST_FILE_MODE); performChecks(mountableFile); assertEquals("Valid file mode.", BASE_FILE_MODE | TEST_FILE_MODE, mountableFile.getFileMode()); @@ -101,6 +105,31 @@ public void forHostDirPathWithPermission() throws Exception { assertEquals("Valid dir mode.", BASE_DIR_MODE | TEST_FILE_MODE, mountableFile.getFileMode()); } + @Test + public void noTrailingSlashesInTarEntryNames() throws Exception { + final MountableFile mountableFile = MountableFile.forClasspathResource("mappable-resource/test-resource.txt"); + + final TarArchiveInputStream tais = intoTarArchive((taos) -> { + mountableFile.transferTo(taos, "/some/path.txt"); + mountableFile.transferTo(taos, "/path.txt"); + mountableFile.transferTo(taos, "path.txt"); + }); + + ArchiveEntry entry; + while ((entry = tais.getNextEntry()) != null) { + assertFalse("no entries should have a trailing slash", entry.getName().endsWith("/")); + } + } + + private TarArchiveInputStream intoTarArchive(Consumer consumer) throws IOException { + final ByteArrayOutputStream baos = new ByteArrayOutputStream(); + final TarArchiveOutputStream taos = new TarArchiveOutputStream(baos); + consumer.accept(taos); + taos.close(); + + return new TarArchiveInputStream(new ByteArrayInputStream(baos.toByteArray())); + } + @SuppressWarnings("ResultOfMethodCallIgnored") @NotNull private Path createTempFile(final String name) throws IOException { From eb4b990aa5fc510bf60959d0075ec3bd38b6c0af Mon Sep 17 00:00:00 2001 From: Richard North Date: Sun, 29 Jul 2018 21:18:08 +0100 Subject: [PATCH 3/4] Add cleanup for streams in test --- .../java/org/testcontainers/utility/MountableFileTest.java | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/core/src/test/java/org/testcontainers/utility/MountableFileTest.java b/core/src/test/java/org/testcontainers/utility/MountableFileTest.java index 750cfab9088..c7dcaad2908 100644 --- a/core/src/test/java/org/testcontainers/utility/MountableFileTest.java +++ b/core/src/test/java/org/testcontainers/utility/MountableFileTest.java @@ -1,5 +1,6 @@ package org.testcontainers.utility; +import lombok.Cleanup; import org.apache.commons.compress.archivers.ArchiveEntry; import org.apache.commons.compress.archivers.tar.TarArchiveInputStream; import org.apache.commons.compress.archivers.tar.TarArchiveOutputStream; @@ -109,7 +110,7 @@ public void forHostDirPathWithPermission() throws Exception { public void noTrailingSlashesInTarEntryNames() throws Exception { final MountableFile mountableFile = MountableFile.forClasspathResource("mappable-resource/test-resource.txt"); - final TarArchiveInputStream tais = intoTarArchive((taos) -> { + @Cleanup final TarArchiveInputStream tais = intoTarArchive((taos) -> { mountableFile.transferTo(taos, "/some/path.txt"); mountableFile.transferTo(taos, "/path.txt"); mountableFile.transferTo(taos, "path.txt"); @@ -122,8 +123,8 @@ public void noTrailingSlashesInTarEntryNames() throws Exception { } private TarArchiveInputStream intoTarArchive(Consumer consumer) throws IOException { - final ByteArrayOutputStream baos = new ByteArrayOutputStream(); - final TarArchiveOutputStream taos = new TarArchiveOutputStream(baos); + @Cleanup final ByteArrayOutputStream baos = new ByteArrayOutputStream(); + @Cleanup final TarArchiveOutputStream taos = new TarArchiveOutputStream(baos); consumer.accept(taos); taos.close(); From 5b5a1d5a719e52c9666914a76319efeb561f2da7 Mon Sep 17 00:00:00 2001 From: Richard North Date: Sun, 29 Jul 2018 21:25:44 +0100 Subject: [PATCH 4/4] Remove leading slash just in case --- .../src/main/java/org/testcontainers/utility/MountableFile.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/core/src/main/java/org/testcontainers/utility/MountableFile.java b/core/src/main/java/org/testcontainers/utility/MountableFile.java index f45209a18e7..cd83a81781f 100644 --- a/core/src/main/java/org/testcontainers/utility/MountableFile.java +++ b/core/src/main/java/org/testcontainers/utility/MountableFile.java @@ -308,7 +308,7 @@ private void recursiveTar(String entryFilename, String rootPath, String itemPath tarEntryFilename = entryFilename + "/" + relativePathToSourceFile; // entry filename e.g. /xyz/bar/baz => /foo/bar/baz } - final TarArchiveEntry tarEntry = new TarArchiveEntry(sourceFile, tarEntryFilename); + final TarArchiveEntry tarEntry = new TarArchiveEntry(sourceFile, tarEntryFilename.replaceAll("^/", "")); // TarArchiveEntry automatically sets the mode for file/directory, but we can update to ensure that the mode is set exactly (inc executable bits) tarEntry.setMode(getUnixFileMode(itemPath));