diff --git a/core/src/main/java/hudson/util/DirScanner.java b/core/src/main/java/hudson/util/DirScanner.java index a1c79c8c1a9b..4ca35ecb14e9 100644 --- a/core/src/main/java/hudson/util/DirScanner.java +++ b/core/src/main/java/hudson/util/DirScanner.java @@ -146,6 +146,12 @@ public void scan(File dir, FileVisitor visitor) throws IOException { File file = new File(dir, f); scanSingle(file, f, visitor); } + for (String d : ds.getIncludedDirectories()) { + if (!d.isEmpty()) { + File file = new File(dir, d); + scanSingle(file, d, visitor); + } + } } } diff --git a/core/src/main/java/jenkins/util/VirtualFile.java b/core/src/main/java/jenkins/util/VirtualFile.java index 36279a8ec6fa..42f21577ace0 100644 --- a/core/src/main/java/jenkins/util/VirtualFile.java +++ b/core/src/main/java/jenkins/util/VirtualFile.java @@ -327,9 +327,8 @@ public Collection call() throws IOException { private static void collectFiles(VirtualFile d, Collection names, String prefix) throws IOException { for (VirtualFile child : d.list()) { - if (child.isFile()) { - names.add(prefix + child.getName()); - } else if (child.isDirectory()) { + names.add(prefix + child.getName()); + if (child.isDirectory()) { collectFiles(child, names, prefix + child.getName() + "/"); } } diff --git a/core/src/test/java/hudson/FilePathTest.java b/core/src/test/java/hudson/FilePathTest.java index 54d37c2b3dcd..b287d7d84998 100644 --- a/core/src/test/java/hudson/FilePathTest.java +++ b/core/src/test/java/hudson/FilePathTest.java @@ -806,7 +806,7 @@ public void testEOFbrokenFlush() throws IOException, InterruptedException { // Compress archive final FilePath tmpDirPath = new FilePath(srcFolder); int tarred = tmpDirPath.tar(Files.newOutputStream(archive.toPath()), "**"); - assertEquals("One file should have been compressed", 3, tarred); + assertEquals("One file should have been compressed", 4, tarred); // Decompress final File dstFolder = temp.newFolder("dst"); diff --git a/core/src/test/java/hudson/util/io/TarArchiverTest.java b/core/src/test/java/hudson/util/io/TarArchiverTest.java index 2d7d9b5524cd..0d6d5e2d9e70 100644 --- a/core/src/test/java/hudson/util/io/TarArchiverTest.java +++ b/core/src/test/java/hudson/util/io/TarArchiverTest.java @@ -46,7 +46,6 @@ import java.util.Set; import org.apache.tools.tar.TarEntry; import org.apache.tools.tar.TarInputStream; -import org.junit.Ignore; import org.junit.Rule; import org.junit.Test; import org.junit.rules.TemporaryFolder; @@ -129,7 +128,6 @@ private static void run(FilePath dir, String... cmds) throws InterruptedExceptio } } - @Ignore("TODO fails to add empty directories to archive") @Issue("JENKINS-73837") @Test public void emptyDirectory() throws Exception { diff --git a/core/src/test/java/hudson/util/io/ZipArchiverTest.java b/core/src/test/java/hudson/util/io/ZipArchiverTest.java index a54fad193ecf..86a939ed1fc5 100644 --- a/core/src/test/java/hudson/util/io/ZipArchiverTest.java +++ b/core/src/test/java/hudson/util/io/ZipArchiverTest.java @@ -16,7 +16,6 @@ import java.util.zip.ZipFile; import java.util.zip.ZipInputStream; import org.junit.Assume; -import org.junit.Ignore; import org.junit.Rule; import org.junit.Test; import org.junit.rules.TemporaryFolder; @@ -81,7 +80,6 @@ public void huge64bitFile() throws IOException { } } - @Ignore("TODO fails to add empty directories to archive") @Issue("JENKINS-49296") @Test public void emptyDirectory() throws Exception { diff --git a/core/src/test/java/jenkins/util/VirtualFileTest.java b/core/src/test/java/jenkins/util/VirtualFileTest.java index af27d3a07ac4..b8db484b704e 100644 --- a/core/src/test/java/jenkins/util/VirtualFileTest.java +++ b/core/src/test/java/jenkins/util/VirtualFileTest.java @@ -132,16 +132,16 @@ private static String modeString(int mode) throws IOException { System.err.println("testing " + vf.getClass().getName()); assertEquals("[.hg/config.txt, sub/mid.txt, sub/subsub/lowest.txt, top.txt]", new TreeSet<>(vf.list("**/*.txt", null, false)).toString()); assertEquals("[sub/mid.txt, sub/subsub/lowest.txt, top.txt]", new TreeSet<>(vf.list("**/*.txt", null, true)).toString()); - assertEquals("[.hg/config.txt, sub/mid.txt, sub/subsub/lowest.txt, top.txt, very/deep/path/here]", new TreeSet<>(vf.list("**", null, false)).toString()); + assertEquals("[.hg, .hg/config.txt, sub, sub/mid.txt, sub/subsub, sub/subsub/lowest.txt, top.txt, very, very/deep, very/deep/path, very/deep/path/here]", new TreeSet<>(vf.list("**", null, false)).toString()); assertEquals("[]", new TreeSet<>(vf.list("", null, false)).toString()); - assertEquals("[sub/mid.txt, sub/subsub/lowest.txt]", new TreeSet<>(vf.list("sub/", null, false)).toString()); - assertEquals("[sub/mid.txt]", new TreeSet<>(vf.list("sub/", "sub/subsub/", false)).toString()); - assertEquals("[sub/mid.txt]", new TreeSet<>(vf.list("sub/", "sub/subsub/**", false)).toString()); - assertEquals("[sub/mid.txt]", new TreeSet<>(vf.list("sub/", "**/subsub/", false)).toString()); + assertEquals("[sub, sub/mid.txt, sub/subsub, sub/subsub/lowest.txt]", new TreeSet<>(vf.list("sub/", null, false)).toString()); + assertEquals("[sub, sub/mid.txt]", new TreeSet<>(vf.list("sub/", "sub/subsub/", false)).toString()); + assertEquals("[sub, sub/mid.txt]", new TreeSet<>(vf.list("sub/", "sub/subsub/**", false)).toString()); + assertEquals("[sub, sub/mid.txt]", new TreeSet<>(vf.list("sub/", "**/subsub/", false)).toString()); assertEquals("[.hg/config.txt, sub/mid.txt]", new TreeSet<>(vf.list("**/mid*,**/conf*", null, false)).toString()); - assertEquals("[sub/mid.txt, sub/subsub/lowest.txt]", new TreeSet<>(vf.list("sub/", "**/notthere/", false)).toString()); + assertEquals("[sub, sub/mid.txt, sub/subsub, sub/subsub/lowest.txt]", new TreeSet<>(vf.list("sub/", "**/notthere/", false)).toString()); assertEquals("[top.txt]", new TreeSet<>(vf.list("*.txt", null, false)).toString()); - assertEquals("[sub/subsub/lowest.txt, top.txt, very/deep/path/here]", new TreeSet<>(vf.list("**", "**/mid*,**/conf*", false)).toString()); + assertEquals("[.hg, sub, sub/subsub, sub/subsub/lowest.txt, top.txt, very, very/deep, very/deep/path, very/deep/path/here]", new TreeSet<>(vf.list("**", "**/mid*,**/conf*", false)).toString()); } } /** Roughly analogous to {@code org.jenkinsci.plugins.compress_artifacts.ZipStorage}. */ @@ -240,7 +240,13 @@ public void list_Glob_NoFollowLinks_FileVF() throws Exception { assertThat(children, containsInAnyOrder( "a/aa/aa.txt", "a/ab/ab.txt", - "b/ba/ba.txt" + "b/ba/ba.txt", + "a", + "a/aa", + "a/aa/aaa", + "a/ab", + "b", + "b/ba" )); } @@ -256,7 +262,13 @@ public void list_Glob_NoFollowLinks_FilePathVF() throws Exception { assertThat(children, containsInAnyOrder( "a/aa/aa.txt", "a/ab/ab.txt", - "b/ba/ba.txt" + "b/ba/ba.txt", + "a", + "a/aa", + "a/aa/aaa", + "a/ab", + "b", + "b/ba" )); } @@ -281,7 +293,7 @@ public void zip_NoFollowLinks_FilePathVF() throws Exception { assertTrue(unzipPath.isDirectory()); assertTrue(unzipPath.child("a").child("aa").child("aa.txt").exists()); assertTrue(unzipPath.child("a").child("ab").child("ab.txt").exists()); - assertFalse(unzipPath.child("a").child("aa").child("aaa").exists()); + assertTrue(unzipPath.child("a").child("aa").child("aaa").exists()); assertFalse(unzipPath.child("a").child("_b").exists()); assertTrue(unzipPath.child("b").child("ba").child("ba.txt").exists()); assertFalse(unzipPath.child("b").child("_a").exists()); @@ -311,7 +323,7 @@ public void zip_NoFollowLinks_FilePathVF_withPrefix() throws Exception { assertTrue(unzipPath.child(prefix).isDirectory()); assertTrue(unzipPath.child(prefix).child("a").child("aa").child("aa.txt").exists()); assertTrue(unzipPath.child(prefix).child("a").child("ab").child("ab.txt").exists()); - assertFalse(unzipPath.child(prefix).child("a").child("aa").child("aaa").exists()); + assertTrue(unzipPath.child(prefix).child("a").child("aa").child("aaa").exists()); assertFalse(unzipPath.child(prefix).child("a").child("_b").exists()); assertTrue(unzipPath.child(prefix).child("b").child("ba").child("ba.txt").exists()); assertFalse(unzipPath.child(prefix).child("b").child("_a").exists()); @@ -339,7 +351,7 @@ public void zip_NoFollowLinks_FileVF() throws Exception { assertTrue(unzipPath.isDirectory()); assertTrue(unzipPath.child("a").child("aa").child("aa.txt").exists()); assertTrue(unzipPath.child("a").child("ab").child("ab.txt").exists()); - assertFalse(unzipPath.child("a").child("aa").child("aaa").exists()); + assertTrue(unzipPath.child("a").child("aa").child("aaa").exists()); assertFalse(unzipPath.child("a").child("_b").exists()); assertTrue(unzipPath.child("b").child("ba").child("ba.txt").exists()); assertFalse(unzipPath.child("b").child("_a").exists()); @@ -369,7 +381,7 @@ public void zip_NoFollowLinks_FileVF_withPrefix() throws Exception { assertTrue(unzipPath.child(prefix).isDirectory()); assertTrue(unzipPath.child(prefix).child("a").child("aa").child("aa.txt").exists()); assertTrue(unzipPath.child(prefix).child("a").child("ab").child("ab.txt").exists()); - assertFalse(unzipPath.child(prefix).child("a").child("aa").child("aaa").exists()); + assertTrue(unzipPath.child(prefix).child("a").child("aa").child("aaa").exists()); assertFalse(unzipPath.child(prefix).child("a").child("_b").exists()); assertTrue(unzipPath.child(prefix).child("b").child("ba").child("ba.txt").exists()); assertFalse(unzipPath.child(prefix).child("b").child("_a").exists()); @@ -504,7 +516,7 @@ public void list_Glob_NoFollowLinks_ExternalSymlink_FilePathVF() throws Exceptio VirtualFile symlinkVirtualPath = VirtualFile.forFilePath(symlinkPath); VirtualFile symlinkChildVirtualPath = symlinkVirtualPath.child("aa"); Collection children = symlinkChildVirtualPath.list("**", null, true, LinkOption.NOFOLLOW_LINKS); - assertThat(children, contains("aa.txt")); + assertThat(children, containsInAnyOrder("aaa", "aa.txt")); } @Test @@ -519,7 +531,7 @@ public void list_Glob_NoFollowLinks_ExternalSymlink_FileVF() throws Exception { VirtualFile symlinkVirtualFile = VirtualFile.forFile(symlinkFile); VirtualFile symlinkChildVirtualFile = symlinkVirtualFile.child("aa"); Collection children = symlinkChildVirtualFile.list("**", null, true, LinkOption.NOFOLLOW_LINKS); - assertThat(children, contains("aa.txt")); + assertThat(children, containsInAnyOrder("aaa", "aa.txt")); } @Test diff --git a/test/src/test/java/hudson/model/DirectoryBrowserSupportTest.java b/test/src/test/java/hudson/model/DirectoryBrowserSupportTest.java index fbd1173909df..e0161fc3eeda 100644 --- a/test/src/test/java/hudson/model/DirectoryBrowserSupportTest.java +++ b/test/src/test/java/hudson/model/DirectoryBrowserSupportTest.java @@ -26,7 +26,6 @@ import static org.hamcrest.MatcherAssert.assertThat; import static org.hamcrest.Matchers.allOf; -import static org.hamcrest.Matchers.contains; import static org.hamcrest.Matchers.containsInAnyOrder; import static org.hamcrest.Matchers.containsString; import static org.hamcrest.Matchers.equalTo; @@ -687,7 +686,9 @@ public void symlink_outsideWorkspace_areNotAllowed() throws Exception { List entryNames = getListOfEntriesInDownloadedZip((UnexpectedPage) zipPage); assertThat(entryNames, containsInAnyOrder( p.getName() + "/intermediateFolder/public2.key", - p.getName() + "/public1.key" + p.getName() + "/public1.key", + p.getName() + "/intermediateFolder/", + p.getName() + "/intermediateFolder/otherFolder/" )); } { // workaround for JENKINS-19947 is still supported, i.e. no parent folder @@ -697,7 +698,10 @@ public void symlink_outsideWorkspace_areNotAllowed() throws Exception { List entryNames = getListOfEntriesInDownloadedZip((UnexpectedPage) zipPage); assertThat(entryNames, containsInAnyOrder( "intermediateFolder/public2.key", - "public1.key" + "public1.key", + "intermediateFolder/", + "intermediateFolder/otherFolder/" + )); } { // all the outside folders / files are not included in the zip @@ -705,14 +709,14 @@ public void symlink_outsideWorkspace_areNotAllowed() throws Exception { assertThat(zipPage.getWebResponse().getStatusCode(), equalTo(HttpURLConnection.HTTP_OK)); List entryNames = getListOfEntriesInDownloadedZip((UnexpectedPage) zipPage); - assertThat(entryNames, contains("intermediateFolder/public2.key")); + assertThat(entryNames, containsInAnyOrder("intermediateFolder/public2.key", "intermediateFolder/otherFolder/")); } { // workaround for JENKINS-19947 is still supported, i.e. no parent folder, even inside a sub-folder Page zipPage = wc.goTo(p.getUrl() + "ws/intermediateFolder/**/*zip*/intermediateFolder.zip", null); assertThat(zipPage.getWebResponse().getStatusCode(), equalTo(HttpURLConnection.HTTP_OK)); List entryNames = getListOfEntriesInDownloadedZip((UnexpectedPage) zipPage); - assertThat(entryNames, contains("public2.key")); + assertThat(entryNames, containsInAnyOrder("public2.key", "otherFolder/")); } } @@ -917,7 +921,9 @@ public void junctionAndSymlink_outsideWorkspace_areNotAllowed_windowsJunction() List entryNames = getListOfEntriesInDownloadedZip((UnexpectedPage) zipPage); assertThat(entryNames, containsInAnyOrder( p.getName() + "/intermediateFolder/public2.key", - p.getName() + "/public1.key" + p.getName() + "/public1.key", + p.getName() + "/intermediateFolder/", + p.getName() + "/intermediateFolder/otherFolder/" )); } { // all the outside folders / files are not included in the zip @@ -925,7 +931,7 @@ public void junctionAndSymlink_outsideWorkspace_areNotAllowed_windowsJunction() assertThat(zipPage.getWebResponse().getStatusCode(), equalTo(HttpURLConnection.HTTP_OK)); List entryNames = getListOfEntriesInDownloadedZip((UnexpectedPage) zipPage); - assertThat(entryNames, contains("intermediateFolder/public2.key")); + assertThat(entryNames, containsInAnyOrder("intermediateFolder/public2.key", "intermediateFolder/otherFolder/")); } // Explicitly delete everything including junctions, which TemporaryDirectoryAllocator.dispose may have trouble with: new Launcher.LocalLauncher(StreamTaskListener.fromStderr()).launch().cmds("cmd", "/c", "rmdir", "/s", "/q", j.jenkins.getRootDir().getAbsolutePath()).start().join(); @@ -987,7 +993,7 @@ public void directSymlink_forTestingZip() throws Exception { assertThat(zipPage.getWebResponse().getStatusCode(), equalTo(HttpURLConnection.HTTP_OK)); List entryNames = getListOfEntriesInDownloadedZip((UnexpectedPage) zipPage); - assertThat(entryNames, hasSize(0)); + assertThat(entryNames, hasSize(6)); } { Page zipPage = wc.goTo(p.getUrl() + "ws/a1/*zip*/a1.zip", null); @@ -1270,20 +1276,23 @@ public boolean perform(AbstractBuild build, Launcher launcher, BuildListen assertThat(zipPage.getWebResponse().getStatusCode(), equalTo(HttpURLConnection.HTTP_OK)); List entryNames = getListOfEntriesInDownloadedZip((UnexpectedPage) zipPage); - assertThat(entryNames, hasSize(2)); + assertThat(entryNames, hasSize(4)); assertThat(entryNames, containsInAnyOrder( "test0/anotherDir/one.txt", - "test0/anotherDir/insideDir/two.txt" + "test0/anotherDir/insideDir/two.txt", + "test0/anotherDir/", + "test0/anotherDir/insideDir/" )); zipPage = wc.goTo("job/" + p.getName() + "/ws/anotherDir/*zip*/" + p.getName(), null); assertThat(zipPage.getWebResponse().getStatusCode(), equalTo(HttpURLConnection.HTTP_OK)); entryNames = getListOfEntriesInDownloadedZip((UnexpectedPage) zipPage); - assertThat(entryNames, hasSize(2)); + assertThat(entryNames, hasSize(3)); assertThat(entryNames, containsInAnyOrder( "anotherDir/one.txt", - "anotherDir/insideDir/two.txt" + "anotherDir/insideDir/two.txt", + "anotherDir/insideDir/" )); }