diff --git a/core/src/main/java/hudson/FilePath.java b/core/src/main/java/hudson/FilePath.java index e4172a306a91..6b22e21d8362 100644 --- a/core/src/main/java/hudson/FilePath.java +++ b/core/src/main/java/hudson/FilePath.java @@ -55,6 +55,7 @@ import hudson.remoting.Which; import hudson.security.AccessControlled; import hudson.slaves.WorkspaceList; +import hudson.tasks.ArtifactArchiver; import hudson.util.DaemonThreadFactory; import hudson.util.DirScanner; import hudson.util.ExceptionCatchingThreadFactory; @@ -3054,6 +3055,21 @@ public String validateAntFileMask(final String fileMasks, final boolean caseSens @SuppressFBWarnings(value = "MS_SHOULD_BE_FINAL", justification = "for script console") public static int VALIDATE_ANT_FILE_MASK_BOUND = SystemProperties.getInteger(FilePath.class.getName() + ".VALIDATE_ANT_FILE_MASK_BOUND", 10000); + /** + * A dedicated subtype of {@link InterruptedException} for when no matching Ant file mask + * matches are found. + * + * @see ArtifactArchiver + */ + @Restricted(NoExternalUse.class) + public static class FileMaskNoMatchesFoundException extends InterruptedException { + private FileMaskNoMatchesFoundException(String message) { + super(message); + } + + private static final long serialVersionUID = 1L; + } + /** * Validates the ant file mask (like "foo/bar/*.txt, zot/*.jar") against this directory, and try to point out the problem. * This performs only a bounded number of operations. @@ -3223,7 +3239,7 @@ class Cancel extends RuntimeException {} if (ds.getIncludedFilesCount() != 0 || ds.getIncludedDirsCount() != 0) { return true; } else { - throw (InterruptedException) new InterruptedException("no matches found within " + bound).initCause(c); + throw (FileMaskNoMatchesFoundException) new FileMaskNoMatchesFoundException("no matches found within " + bound).initCause(c); } } return ds.getIncludedFilesCount() != 0 || ds.getIncludedDirsCount() != 0; diff --git a/core/src/main/java/hudson/tasks/ArtifactArchiver.java b/core/src/main/java/hudson/tasks/ArtifactArchiver.java index 0f72c72319eb..efa0a63bed49 100644 --- a/core/src/main/java/hudson/tasks/ArtifactArchiver.java +++ b/core/src/main/java/hudson/tasks/ArtifactArchiver.java @@ -270,6 +270,8 @@ public void perform(Run build, FilePath ws, EnvVars environment, Launcher if (msg != null) { listener.getLogger().println(msg); } + } catch (FilePath.FileMaskNoMatchesFoundException e) { + listener.getLogger().println(e.getMessage()); } catch (Exception e) { Functions.printStackTrace(e, listener.getLogger()); } diff --git a/test/src/test/java/hudson/tasks/ArtifactArchiverTest.java b/test/src/test/java/hudson/tasks/ArtifactArchiverTest.java index 282efe49a70d..92dee288b429 100644 --- a/test/src/test/java/hudson/tasks/ArtifactArchiverTest.java +++ b/test/src/test/java/hudson/tasks/ArtifactArchiverTest.java @@ -131,6 +131,20 @@ public void testAllowEmptyArchive() throws Exception { assertFalse(project.getBuildByNumber(1).getHasArtifacts()); } + @Test + @Issue("JENKINS-51913") + public void testFileMaskNoMatchesFoundException() throws Exception { + FreeStyleProject project = j.createFreeStyleProject(); + String pattern = "dir/**"; + ArtifactArchiver aa = new ArtifactArchiver(pattern); + aa.setAllowEmptyArchive(true); + project.getPublishersList().replaceBy(Collections.singleton(aa)); + FreeStyleBuild build = j.buildAndAssertSuccess(project); + assertFalse(project.getBuildByNumber(1).getHasArtifacts()); + j.assertLogContains("No artifacts found that match the file pattern \"" + pattern + "\"", build); + assertThat("No stacktrace shown", build.getLog(31), Matchers.iterableWithSize(lessThan(30))); + } + @Issue("JENKINS-21958") @Test public void symlinks() throws Exception { FreeStyleProject p = j.createFreeStyleProject();