Skip to content

Commit

Permalink
Merge pull request #1287 from nithril/master
Browse files Browse the repository at this point in the history
[FIXED JENKINS-20086] Allow disabling use of default exclude patterns (.git, .svn, etc.)
  • Loading branch information
oleg-nenashev committed Jun 28, 2014
2 parents 65bc0fb + c726667 commit 6d5c25a
Show file tree
Hide file tree
Showing 8 changed files with 183 additions and 9 deletions.
41 changes: 36 additions & 5 deletions core/src/main/java/hudson/tasks/ArtifactArchiver.java
Expand Up @@ -34,6 +34,8 @@
import hudson.remoting.VirtualChannel;
import hudson.util.FormValidation;
import java.io.File;

import org.apache.tools.ant.types.FileSet;
import org.kohsuke.stapler.StaplerRequest;
import org.kohsuke.stapler.DataBoundConstructor;
import org.kohsuke.stapler.AncestorInPath;
Expand Down Expand Up @@ -79,6 +81,14 @@ public class ArtifactArchiver extends Recorder {
*/
private boolean onlyIfSuccessful;


/**
* Default ant exclusion
*/
@Nonnull
private Boolean defaultExcludes;


public ArtifactArchiver(String artifacts, String excludes, boolean latestOnly) {
this(artifacts, excludes, latestOnly, false, false);
}
Expand All @@ -87,20 +97,30 @@ public ArtifactArchiver(String artifacts, String excludes, boolean latestOnly, b
this(artifacts, excludes, latestOnly, allowEmptyArchive, false);
}

@DataBoundConstructor

public ArtifactArchiver(String artifacts, String excludes, boolean latestOnly, boolean allowEmptyArchive, boolean onlyIfSuccessful) {
this(artifacts, excludes , latestOnly , allowEmptyArchive, onlyIfSuccessful , true);
}


@DataBoundConstructor
public ArtifactArchiver(String artifacts, String excludes, boolean latestOnly, boolean allowEmptyArchive, boolean onlyIfSuccessful, Boolean defaultExcludes) {
this.artifacts = artifacts.trim();
this.excludes = Util.fixEmptyAndTrim(excludes);
this.latestOnly = latestOnly;
this.allowEmptyArchive = allowEmptyArchive;
this.onlyIfSuccessful = onlyIfSuccessful;
this.defaultExcludes = defaultExcludes;
}

// Backwards compatibility for older builds
public Object readResolve() {
if (allowEmptyArchive == null) {
this.allowEmptyArchive = Boolean.getBoolean(ArtifactArchiver.class.getName()+".warnOnEmpty");
}
if (defaultExcludes == null){
defaultExcludes = true;
}
return this;
}

Expand All @@ -123,7 +143,11 @@ public boolean isOnlyIfSuccessful() {
public boolean getAllowEmptyArchive() {
return allowEmptyArchive;
}


public boolean isDefaultExcludes() {
return defaultExcludes;
}

private void listenerWarnOrError(BuildListener listener, String message) {
if (allowEmptyArchive) {
listener.getLogger().println(String.format("WARN: %s", message));
Expand Down Expand Up @@ -154,7 +178,7 @@ public boolean perform(AbstractBuild<?,?> build, Launcher launcher, BuildListene

String artifacts = build.getEnvironment(listener).expand(this.artifacts);

Map<String,String> files = ws.act(new ListFiles(artifacts, excludes));
Map<String,String> files = ws.act(new ListFiles(artifacts, excludes, defaultExcludes));
if (!files.isEmpty()) {
build.pickArtifactManager().archive(ws, launcher, listener, files);
} else {
Expand Down Expand Up @@ -191,13 +215,20 @@ public boolean perform(AbstractBuild<?,?> build, Launcher launcher, BuildListene
private static final class ListFiles implements FilePath.FileCallable<Map<String,String>> {
private static final long serialVersionUID = 1;
private final String includes, excludes;
ListFiles(String includes, String excludes) {
private final boolean defaultExcludes;

ListFiles(String includes, String excludes, boolean defaultExcludes) {
this.includes = includes;
this.excludes = excludes;
this.defaultExcludes = defaultExcludes;
}
@Override public Map<String,String> invoke(File basedir, VirtualChannel channel) throws IOException, InterruptedException {
Map<String,String> r = new HashMap<String,String>();
for (String f : Util.createFileSet(basedir, includes, excludes).getDirectoryScanner().getIncludedFiles()) {

FileSet fileSet = Util.createFileSet(basedir, includes, excludes);
fileSet.setDefaultexcludes(defaultExcludes);

for (String f : fileSet.getDirectoryScanner().getIncludedFiles()) {
f = f.replace(File.separatorChar, '/');
r.put(f, f);
}
Expand Down
Expand Up @@ -40,5 +40,8 @@ THE SOFTWARE.
<f:entry field="onlyIfSuccessful" >
<f:checkbox title="${%onlyIfSuccessful}"/>
</f:entry>
<f:entry field="defaultExcludes" >
<f:checkbox title="${%defaultExcludes}" default="true"/>
</f:entry>
</f:advanced>
</j:jelly>
Expand Up @@ -22,4 +22,5 @@

lastBuildOnly=Discard all but the last successful/stable artifact to save disk space
allowEmptyArchive=Do not fail build if archiving returns nothing
onlyIfSuccessful=Archive artifacts only if build is successful
onlyIfSuccessful=Archive artifacts only if build is successful
defaultExcludes=Use default excludes
Expand Up @@ -20,6 +20,9 @@
# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
# THE SOFTWARE.

Files\ to\ archive=Fichiers à archiver
Excludes=Excluant
lastBuildOnly=Supprime tous les artefacts, à l''exception du dernier artefact stable ou construit avec succès, afin de gagner de l''espace disque
Files\ to\ archive=Fichiers \u00E0 archiver
Excludes=Exclusions
lastBuildOnly=Supprime tous les artefacts, \u00E0 l''exception du dernier artefact stable ou construit avec succ\u00E8s, afin de gagner de l''espace disque
allowEmptyArchive=Ne pas faire \u00E9chouer la construction si l''archive retourn\u00E9e est vide
defaultExcludes=Utilise les exclusions par d\u00E9faut
onlyIfSuccessful=Archive les artifacts seulement si la construction est un succ\u00E8s
@@ -0,0 +1,38 @@
/*
* The MIT License
*
* Copyright (c) 2004-2009, Sun Microsystems, Inc., Kohsuke Kawaguchi, Brian Westrich, Jean-Baptiste Quenot
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE.
*/

import org.apache.commons.lang.StringUtils

div {
p {
raw(_("p1"))
br {}
code {
text(StringUtils.join(org.apache.tools.ant.DirectoryScanner.defaultExcludes, ','))
}
}
p {
raw(_("p2"))
}
}
@@ -0,0 +1,24 @@
# The MIT License
#
# Copyright (c) 2004-2009, Sun Microsystems, Inc., Kohsuke Kawaguchi
#
# Permission is hereby granted, free of charge, to any person obtaining a copy
# of this software and associated documentation files (the "Software"), to deal
# in the Software without restriction, including without limitation the rights
# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
# copies of the Software, and to permit persons to whom the Software is
# furnished to do so, subject to the following conditions:
#
# The above copyright notice and this permission notice shall be included in
# all copies or substantial portions of the Software.
#
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
# THE SOFTWARE.

p1=Artifact archiver uses Ant <code>org.apache.tools.ant.DirectoryScanner</code> which excludes by default the following patterns:
p2=This option allows to enable or disable the default Ant exclusions.
@@ -0,0 +1,24 @@
# The MIT License
#
# Copyright (c) 2004-2009, Sun Microsystems, Inc., Kohsuke Kawaguchi
#
# Permission is hereby granted, free of charge, to any person obtaining a copy
# of this software and associated documentation files (the "Software"), to deal
# in the Software without restriction, including without limitation the rights
# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
# copies of the Software, and to permit persons to whom the Software is
# furnished to do so, subject to the following conditions:
#
# The above copyright notice and this permission notice shall be included in
# all copies or substantial portions of the Software.
#
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
# THE SOFTWARE.

p1=L''archivage utilise le <code>org.apache.tools.ant.DirectoryScanner</code> de Ant qui exclue par d\u00E9faut les patterns suivants \:
p2=Cette option permet d''activer ou de d\u00E9sactiver les exclusions par d\u00E9faut de Ant
50 changes: 50 additions & 0 deletions test/src/test/java/hudson/tasks/ArtifactArchiverTest.java
Expand Up @@ -45,6 +45,7 @@
import jenkins.util.VirtualFile;
import static org.junit.Assert.*;
import static org.junit.Assume.*;

import org.junit.Rule;
import org.junit.Test;
import org.jvnet.hudson.test.Bug;
Expand Down Expand Up @@ -275,4 +276,53 @@ public void testArchivingSkippedWhenOnlyIfSuccessfulChecked() throws Exception {
assertFalse(project.getBuildByNumber(2).getHasArtifacts());
}




static class CreateDefaultExcludesArtifact extends TestBuilder {
public boolean perform(AbstractBuild<?,?> build, Launcher launcher, BuildListener listener) throws IOException, InterruptedException {
FilePath dir = build.getWorkspace().child("dir");
FilePath subSvnDir = dir.child(".svn");
subSvnDir.mkdirs();
subSvnDir.child("file").write("content", "UTF-8");

FilePath svnDir = build.getWorkspace().child(".svn");
svnDir.mkdirs();
svnDir.child("file").write("content", "UTF-8");

dir.child("file").write("content", "UTF-8");
return true;
}
}

@Test
@Bug(20086)
public void testDefaultExcludesOn() throws Exception {
FreeStyleProject project = j.createFreeStyleProject();

Publisher artifactArchiver = new ArtifactArchiver("**", "", false, false, true, true);
project.getPublishersList().replaceBy(Collections.singleton(artifactArchiver));
project.getBuildersList().replaceBy(Collections.singleton(new CreateDefaultExcludesArtifact()));

assertEquals(Result.SUCCESS, build(project)); // #1
VirtualFile artifacts = project.getBuildByNumber(1).getArtifactManager().root();
assertFalse(artifacts.child(".svn").child("file").exists());
assertFalse(artifacts.child("dir").child(".svn").child("file").exists());

}

@Test
@Bug(20086)
public void testDefaultExcludesOff() throws Exception {
FreeStyleProject project = j.createFreeStyleProject();

Publisher artifactArchiver = new ArtifactArchiver("**", "", false, false, true, false);
project.getPublishersList().replaceBy(Collections.singleton(artifactArchiver));
project.getBuildersList().replaceBy(Collections.singleton(new CreateDefaultExcludesArtifact()));

assertEquals(Result.SUCCESS, build(project)); // #1
VirtualFile artifacts = project.getBuildByNumber(1).getArtifactManager().root();
assertTrue(artifacts.child(".svn").child("file").exists());
assertTrue(artifacts.child("dir").child(".svn").child("file").exists());
}
}

0 comments on commit 6d5c25a

Please sign in to comment.