diff --git a/pom.xml b/pom.xml index f9c9402..769e4da 100644 --- a/pom.xml +++ b/pom.xml @@ -4,7 +4,7 @@ org.jenkins-ci.plugins plugin - 1.400 + 2.32 hudson.plugins.filesystem_scm @@ -16,6 +16,10 @@ Using File System as SCM, done by checking file system last modified date. http://wiki.jenkins-ci.org/display/JENKINS/File+System+SCM + + 1.642.3 + + samngms @@ -31,6 +35,14 @@ + + + MIT License + http://www.opensource.org/licenses/mit-license.php + repo + + + @@ -46,7 +58,43 @@ http://repo.jenkins-ci.org/public/ + + + org.jenkins-ci.plugins + structs + 1.5 + + + org.jenkins-ci.plugins.workflow + workflow-cps + 2.4 + test + + + org.jenkins-ci.plugins.workflow + workflow-job + 2.4 + test + + + org.jenkins-ci.plugins.workflow + workflow-api + 2.1 + test + + + org.jenkins-ci.plugins.workflow + workflow-support + 2.1 + test + + + + org.jenkins-ci + annotation-indexer + 1.9 + diff --git a/src/main/java/hudson/plugins/filesystem_scm/Changelog.java b/src/main/java/hudson/plugins/filesystem_scm/Changelog.java index d08e829..bbd0a7e 100644 --- a/src/main/java/hudson/plugins/filesystem_scm/Changelog.java +++ b/src/main/java/hudson/plugins/filesystem_scm/Changelog.java @@ -8,6 +8,7 @@ import java.util.Collections; import java.util.Date; import java.util.List; +import javax.annotation.CheckForNull; /** Represents a Changelog record (ChangeLogSet.Entry) in ChangelogSet * @@ -102,12 +103,13 @@ protected void setParent(ChangeLogSet parent) { this.parent = (ChangelogSet)parent; } + @CheckForNull public Date getDate() { - return date; + return date != null ? (Date)date.clone() : null; } public void setDate(Date date) { - this.date = date; + this.date = date != null ? (Date)date.clone() : null; } @Override diff --git a/src/main/java/hudson/plugins/filesystem_scm/ChangelogSet.java b/src/main/java/hudson/plugins/filesystem_scm/ChangelogSet.java index 21ca837..03c3225 100644 --- a/src/main/java/hudson/plugins/filesystem_scm/ChangelogSet.java +++ b/src/main/java/hudson/plugins/filesystem_scm/ChangelogSet.java @@ -1,10 +1,13 @@ package hudson.plugins.filesystem_scm; -import hudson.model.*; +import hudson.model.Run; +import hudson.scm.ChangeLogSet; +import hudson.scm.RepositoryBrowser; import hudson.util.XStream2; import java.util.*; import java.io.*; import org.apache.commons.io.IOUtils; +import org.xml.sax.SAXException; /** * FileSystem base SCM ChangelogSet @@ -23,9 +26,9 @@ public class ChangelogSet extends hudson.scm.ChangeLogSet { // not like other SCM, e.g. SVN, there may be 2 or 3 committed changes between builds private List logs; - public ChangelogSet(AbstractBuild build, List changes) { - super(build); - logs = new ArrayList(); + public ChangelogSet(Run build, List changes) { + super(build, new FilesystemRepositoryBrowser()); + logs = new ArrayList<>(); if (!changes.isEmpty()) { logs.add(new Changelog(this, changes)); } @@ -93,9 +96,14 @@ private void initXStream() { //xstream.omitField(ChangelogSet.ChangeLog.class, "parent"); //xstream.omitField(ChangelogSet.Path.class, "changeLog"); } - - @SuppressWarnings("rawtypes") - public ChangelogSet parse(AbstractBuild build, java.io.File file) throws FileNotFoundException { + + @Override + public ChangeLogSet parse(Run build, RepositoryBrowser browser, File changelogFile) throws IOException, SAXException { + return parse(build, changelogFile); + } + + @SuppressWarnings("rawtypes") + public ChangelogSet parse(Run build, java.io.File file) throws FileNotFoundException { FileInputStream in = null; ChangelogSet out = null; try { diff --git a/src/main/java/hudson/plugins/filesystem_scm/FSSCM.java b/src/main/java/hudson/plugins/filesystem_scm/FSSCM.java index 331069b..b3399a9 100644 --- a/src/main/java/hudson/plugins/filesystem_scm/FSSCM.java +++ b/src/main/java/hudson/plugins/filesystem_scm/FSSCM.java @@ -8,9 +8,7 @@ import hudson.Extension; import hudson.FilePath; import hudson.Launcher; -import hudson.model.AbstractBuild; -import hudson.model.AbstractProject; -import hudson.model.BuildListener; +import hudson.model.Job; import hudson.model.Run; import hudson.model.TaskListener; import hudson.scm.ChangeLogParser; @@ -19,8 +17,14 @@ import hudson.scm.SCM; import hudson.scm.SCMDescriptor; import hudson.util.FormValidation; +import javax.annotation.CheckForNull; +import jenkins.model.Jenkins; import net.sf.json.JSONObject; import org.apache.commons.lang.StringUtils; +import org.jenkinsci.Symbol; +import org.kohsuke.accmod.Restricted; +import org.kohsuke.accmod.restrictions.NoExternalUse; +import org.kohsuke.stapler.DataBoundConstructor; /** * {@link SCM} implementation which watches a file system folder. @@ -38,60 +42,88 @@ public class FSSCM extends SCM { /** If true, will copy hidden files and folders. Default is false. * */ - private boolean copyHidden; - /** If we have include/exclude filter, then this is true - * - */ - private boolean filterEnabled; - /** Is this filter a include filter or exclude filter - * - */ - private boolean includeFilter; - /** filters will be passed to org.apache.commons.io.filefilter.WildcardFileFilter - * - */ - private String[] filters; - - // Don't use DataBoundConsturctor, it is still not mature enough, many HTML form elements are not binded - // @DataBoundConstructor + + private transient boolean copyHidden; + /** + * If we have include/exclude filter, then this is true. + * + * @deprecated Moved to {@link FilterSettings} + */ + @Deprecated + private transient boolean filterEnabled; + /** + * Is this filter a include filter or exclude filter + * + * @deprecated Moved to {@link FilterSettings} + */ + @Deprecated + private transient boolean includeFilter; + /** + * filters, which will be passed to {@link WildcardFileFilter}. + * + * @deprecated Moved to {@link FilterSettings} + */ + @Deprecated + private String[] filters; + + /** + * Filter settings. + * + * @since TODO + */ + @CheckForNull + private FilterSettings filterSettings; + + @DataBoundConstructor + public FSSCM(String path, boolean clearWorkspace, boolean copyHidden, FilterSettings filterSettings) { + this.path = path; + this.clearWorkspace = clearWorkspace; + this.copyHidden = copyHidden; + this.filterSettings = filterSettings; + } + + @Deprecated public FSSCM(String path, boolean clearWorkspace, boolean copyHidden, boolean filterEnabled, boolean includeFilter, String[] filters) { - this.path = path; - this.clearWorkspace = clearWorkspace; - this.copyHidden = copyHidden; - this.filterEnabled = filterEnabled; - this.includeFilter = includeFilter; - - // in hudson 1.337, in filters = null, XStream will throw NullPointerException - // this.filters = null; - this.filters = new String[0]; - if ( null != filters ) { - Vector v = new Vector(); - for(int i=0; i 0 ) { - this.filters = (String[]) v.toArray(new String[1]); - } - } + this.path = path; + this.clearWorkspace = clearWorkspace; + this.copyHidden = copyHidden; + + if (filterEnabled) { + List selectors = new ArrayList<>(); + if (null != filters) { + for (String filter : filters) { + // remove empty strings + if (StringUtils.isNotEmpty(filter)) { + selectors.add(new FilterSelector(filter)); + } + } + } + filterSettings = new FilterSettings(includeFilter, selectors); + } } - public String getPath() { - return path; - } + public String getPath() { + return path; + } - public String[] getFilters() { - return filters; - } + /** + * @deprecated Use {@link #getFilterSettings()}. + */ + @CheckForNull + public String[] getFilters() { + if (filterSettings == null) { + return null; + } + final List wildcards = filterSettings.getWildcards(); + return wildcards.toArray(new String[wildcards.size()]); + } public boolean isFilterEnabled() { - return filterEnabled; + return filterSettings != null; } public boolean isIncludeFilter() { - return includeFilter; + return filterSettings != null && filterSettings.isIncludeFilter(); } public boolean isClearWorkspace() { @@ -101,17 +133,39 @@ public boolean isClearWorkspace() { public boolean isCopyHidden() { return copyHidden; } - + + @CheckForNull + public FilterSettings getFilterSettings() { + return filterSettings; + } + + protected Object readResolve() { + if (filterEnabled && filterSettings == null) { + final List selectors; + if (filters != null) { + selectors = new ArrayList<>(filters.length); + for (String value : filters) { + selectors.add(new FilterSelector(value)); + } + } else { + selectors = Collections.emptyList(); + } + filterSettings = new FilterSettings(includeFilter, selectors); + } + return this; + } + @Override - public boolean checkout(AbstractBuild build, Launcher launcher, FilePath workspace, BuildListener listener, File changelogFile) - throws IOException, InterruptedException { + public void checkout(Run build, Launcher launcher, FilePath workspace, + TaskListener listener, File changelogFile, SCMRevisionState baseline) + throws IOException, InterruptedException { + long start = System.currentTimeMillis(); PrintStream log = launcher.getListener().getLogger(); log.println("FSSCM.checkout " + path + " to " + workspace); - Boolean b = Boolean.TRUE; - AllowDeleteList allowDeleteList = new AllowDeleteList(build.getProject().getRootDir()); + AllowDeleteList allowDeleteList = new AllowDeleteList(build.getParent().getRootDir()); if ( clearWorkspace ) { log.println("FSSCM.clearWorkspace..."); @@ -136,7 +190,7 @@ public boolean checkout(AbstractBuild build, Launcher launcher, FilePath w } RemoteFolderDiff.CheckOut callable = new RemoteFolderDiff.CheckOut(); - setupRemoteFolderDiff(callable, build.getProject(), allowDeleteList.getList()); + setupRemoteFolderDiff(callable, build.getParent(), allowDeleteList.getList()); List list = workspace.act(callable); // maintain the watch list @@ -159,7 +213,6 @@ public boolean checkout(AbstractBuild build, Launcher launcher, FilePath w handler.save(changeLogSet, changelogFile); log.println("FSSCM.check completed in " + formatDuration(System.currentTimeMillis()-start)); - return b; } @Override @@ -174,7 +227,7 @@ public ChangeLogParser createChangeLogParser() { *
  • file deleted since last build time, we have to compare source and destination folder
  • * */ - private boolean poll(AbstractProject project, Launcher launcher, FilePath workspace, TaskListener listener) + private boolean poll(Job project, Launcher launcher, FilePath workspace, TaskListener listener) throws IOException, InterruptedException { long start = System.currentTimeMillis(); @@ -208,7 +261,7 @@ private boolean poll(AbstractProject project, Launcher launcher, FilePath } @SuppressWarnings("rawtypes") - private void setupRemoteFolderDiff(RemoteFolderDiff diff, AbstractProject project, Set allowDeleteList) { + private void setupRemoteFolderDiff(RemoteFolderDiff diff, Job project, Set allowDeleteList) { Run lastBuild = project.getLastBuild(); if ( null == lastBuild ) { diff.setLastBuildTime(0); @@ -227,9 +280,12 @@ private void setupRemoteFolderDiff(RemoteFolderDiff diff, AbstractProject projec diff.setIgnoreHidden(!copyHidden); - if ( filterEnabled ) { - if ( includeFilter ) diff.setIncludeFilter(filters); - else diff.setExcludeFilter(filters); + if ( filterSettings != null ) { + if ( filterSettings.isIncludeFilter() ) { + diff.setIncludeFilter(getFilters()); + } else { + diff.setExcludeFilter(getFilters()); + } } diff.setAllowDeleteList(allowDeleteList); @@ -248,6 +304,7 @@ private static String formatDuration(long diff) { } @Extension + @Symbol("filesystem") public static final class DescriptorImpl extends SCMDescriptor { public DescriptorImpl() { super(FSSCM.class, null); @@ -259,58 +316,42 @@ public String getDisplayName() { return "File System"; } + /** + * @deprecated Use {@link FilterSelector.DescriptorImpl#doCheckWildcard(java.lang.String)} + */ + @Deprecated + @Restricted(NoExternalUse.class) public FormValidation doFilterCheck(@QueryParameter final String value) { - if ( null == value || value.trim().length() == 0 ) return FormValidation.ok(); - if ( value.startsWith("/") || value.startsWith("\\") || value.matches("[a-zA-Z]:.*") ) { - return FormValidation.error("Pattern can't be an absolute path"); - } else { - try { - SimpleAntWildcardFilter filter = new SimpleAntWildcardFilter(value); - } catch ( Exception e ) { - return FormValidation.error(e, "Invalid wildcard pattern"); - } - } - return FormValidation.ok(); + return Jenkins.getActiveInstance() + .getDescriptorByType(FilterSelector.DescriptorImpl.class) + .doCheckWildcard(value); } @Override public boolean configure(StaplerRequest req, JSONObject formData) throws FormException { return true; - } - - @Override - public FSSCM newInstance(StaplerRequest req, JSONObject formData) throws FormException { - String path = req.getParameter("fs_scm.path"); - String[] filters = req.getParameterValues("fs_scm.filters"); - Boolean filterEnabled = Boolean.valueOf("on".equalsIgnoreCase(req.getParameter("fs_scm.filterEnabled"))); - Boolean includeFilter = Boolean.valueOf(req.getParameter("fs_scm.includeFilter")); - Boolean clearWorkspace = Boolean.valueOf("on".equalsIgnoreCase(req.getParameter("fs_scm.clearWorkspace"))); - Boolean copyHidden = Boolean.valueOf("on".equalsIgnoreCase(req.getParameter("fs_scm.copyHidden"))); - return new FSSCM(path, clearWorkspace, copyHidden, filterEnabled, includeFilter, filters); } - - } + + @Override + public boolean isApplicable(Job project) { + // All job types are supported, the plugin does not depend on AbstractProject/AbstractBuild anymore + return true; + } + } @Override - public SCMRevisionState calcRevisionsFromBuild(AbstractBuild build, - Launcher launcher, TaskListener listener) throws IOException, - InterruptedException { + public SCMRevisionState calcRevisionsFromBuild(Run build, FilePath workspace, Launcher launcher, TaskListener listener) throws IOException, InterruptedException { // we cannot really calculate a sensible revision state for a filesystem folder // therefore we return NONE and simply ignore the baseline in compareRemoteRevisionWith return SCMRevisionState.NONE; } @Override - protected PollingResult compareRemoteRevisionWith( - AbstractProject project, Launcher launcher, - FilePath workspace, TaskListener listener, SCMRevisionState baseline) - throws IOException, InterruptedException { - + public PollingResult compareRemoteRevisionWith(Job project, Launcher launcher, FilePath workspace, TaskListener listener, SCMRevisionState baseline) throws IOException, InterruptedException { if(poll(project, launcher, workspace, listener)) { return PollingResult.SIGNIFICANT; } else { return PollingResult.NO_CHANGES; } } - } diff --git a/src/main/java/hudson/plugins/filesystem_scm/FilesystemRepositoryBrowser.java b/src/main/java/hudson/plugins/filesystem_scm/FilesystemRepositoryBrowser.java new file mode 100644 index 0000000..9865cb1 --- /dev/null +++ b/src/main/java/hudson/plugins/filesystem_scm/FilesystemRepositoryBrowser.java @@ -0,0 +1,47 @@ +/* + * The MIT License + * + * Copyright (c) 2017 Oleg Nenashev. + * + * 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. + */ +package hudson.plugins.filesystem_scm; + +//TODO: Just a stub, ideally needs to be implemented + +import hudson.scm.ChangeLogSet; +import hudson.scm.RepositoryBrowser; +import java.io.IOException; +import java.net.URL; +import org.kohsuke.accmod.Restricted; +import org.kohsuke.accmod.restrictions.NoExternalUse; + +/** + * Filesystem repository browser. + * @since TODO + * @author Oleg Nenashev + */ +@Restricted(NoExternalUse.class) +public class FilesystemRepositoryBrowser extends RepositoryBrowser { + + @Override + public URL getChangeSetLink(ChangeLogSet.Entry changeSet) throws IOException { + return null; + } +} diff --git a/src/main/java/hudson/plugins/filesystem_scm/FilterSelector.java b/src/main/java/hudson/plugins/filesystem_scm/FilterSelector.java new file mode 100644 index 0000000..e3886a1 --- /dev/null +++ b/src/main/java/hudson/plugins/filesystem_scm/FilterSelector.java @@ -0,0 +1,80 @@ +/* + * The MIT License + * + * Copyright (c) 2017 Oleg Nenashev + * + * 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. + */ +package hudson.plugins.filesystem_scm; + +import hudson.Extension; +import hudson.model.Describable; +import hudson.model.Descriptor; +import hudson.util.FormValidation; +import jenkins.model.Jenkins; +import org.kohsuke.accmod.Restricted; +import org.kohsuke.accmod.restrictions.NoExternalUse; +import org.kohsuke.stapler.DataBoundConstructor; +import org.kohsuke.stapler.QueryParameter; + +/** + * Manages particular wildcards. + * @since TODO + * @author Oleg Nenashev + */ +public class FilterSelector implements Describable { + + private final String wildcard; + + @DataBoundConstructor + public FilterSelector(String wildcard) { + this.wildcard = wildcard; + } + + public String getWildcard() { + return wildcard; + } + + @Override + public Descriptor getDescriptor() { + return Jenkins.getActiveInstance().getDescriptorByType(DescriptorImpl.class); + } + + @Extension + public static class DescriptorImpl extends Descriptor { + + @Restricted(NoExternalUse.class) + public FormValidation doCheckWildcard(@QueryParameter String value) { + if (null == value || value.trim().length() == 0) { + return FormValidation.ok(); + } + if (value.startsWith("/") || value.startsWith("\\") || value.matches("[a-zA-Z]:.*")) { + return FormValidation.error("Pattern can't be an absolute path"); + } else { + try { + SimpleAntWildcardFilter filter = new SimpleAntWildcardFilter(value); + return FormValidation.ok("Pattern is correct: " + filter.getPattern()); + } catch (Exception e) { + return FormValidation.error(e, "Invalid wildcard pattern"); + } + } + } + } + +} diff --git a/src/main/java/hudson/plugins/filesystem_scm/FilterSettings.java b/src/main/java/hudson/plugins/filesystem_scm/FilterSettings.java new file mode 100644 index 0000000..24c502c --- /dev/null +++ b/src/main/java/hudson/plugins/filesystem_scm/FilterSettings.java @@ -0,0 +1,83 @@ +/* + * The MIT License + * + * Copyright (c) 2017 Oleg Nenashev + * + * 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. + */ +package hudson.plugins.filesystem_scm; + +import hudson.Extension; +import hudson.model.Describable; +import hudson.model.Descriptor; +import java.util.ArrayList; +import java.util.Collections; +import java.util.List; +import javax.annotation.Nonnull; +import jenkins.model.Jenkins; +import org.kohsuke.stapler.DataBoundConstructor; + +/** + * Stores filter settings. + * @since TODO + * @author Oleg Nenashev + */ +public class FilterSettings implements Describable { + + private final boolean includeFilter; + @Nonnull + private final List selectors; + + @DataBoundConstructor + public FilterSettings(boolean includeFilter, List selectors) { + this.includeFilter = includeFilter; + this.selectors = selectors != null ? selectors : Collections.emptyList(); + } + + @Nonnull + public List getSelectors() { + return Collections.unmodifiableList(selectors); + } + + @Nonnull + public List getWildcards() { + if (selectors.isEmpty()) { + return Collections.emptyList(); + } + List res = new ArrayList<>(selectors.size()); + for (FilterSelector s : selectors) { + res.add(s.getWildcard()); + } + return res; + } + + public boolean isIncludeFilter() { + return includeFilter; + } + + @Override + public Descriptor getDescriptor() { + return Jenkins.getActiveInstance().getDescriptorByType(DescriptorImpl.class); + } + + @Extension + public static class DescriptorImpl extends Descriptor { + + } +} diff --git a/src/main/java/hudson/plugins/filesystem_scm/FolderDiff.java b/src/main/java/hudson/plugins/filesystem_scm/FolderDiff.java index 6c9ac6b..8835918 100644 --- a/src/main/java/hudson/plugins/filesystem_scm/FolderDiff.java +++ b/src/main/java/hudson/plugins/filesystem_scm/FolderDiff.java @@ -1,7 +1,10 @@ package hudson.plugins.filesystem_scm; +import edu.umd.cs.findbugs.annotations.SuppressFBWarnings; +import hudson.remoting.VirtualChannel; import java.io.*; import java.util.*; +import jenkins.MasterToSlaveFileCallable; import org.apache.commons.io.*; import org.apache.commons.io.filefilter.*; @@ -9,17 +12,16 @@ * *

    This is the core logic for detecting if we need to checkout or pollchanges

    * - *

    Two methods to detect if the two folders are the same + *

    Two methods to detect if the two folders are the same

    *
      *
    • check if there are new/modified files in the source folder
    • *
    • check if there are deleted files in the source folder
    • *
    - *

    - * + * @param Type of the item being returned by the callable * @author Sam NG * */ -public class FolderDiff implements Serializable { +public class FolderDiff extends MasterToSlaveFileCallable implements Serializable { private static final long serialVersionUID = 1L; @@ -46,13 +48,15 @@ public void setDstPath(String dstPath) { public void setIgnoreHidden(boolean ignoreHidden) { this.ignoreHidden = ignoreHidden; } - + + @SuppressFBWarnings(value = "EI_EXPOSE_REP2", justification = "Handled on the Changelog class level") public void setIncludeFilter(String[] filters) { filterEnabled = true; includeFilter = true; this.filters = filters; } - + + @SuppressFBWarnings(value = "EI_EXPOSE_REP2", justification = "Handled on the Changelog class level") public void setExcludeFilter(String[] filters) { filterEnabled = true; includeFilter = false; @@ -214,7 +218,6 @@ public List getDeletedFiles(long time, boolean breakOnceFound, boolean te /** This function will convert e.stackTrace to String and call log(String) * - * @param msg * @param e */ protected void log(Exception e ) { @@ -284,6 +287,12 @@ public static String getRelativeName(String fileName, String folderName) throws protected void copyFile(File src, File dst) throws IOException { FileUtils.copyFile(src, dst); } + + @Override + public T invoke(File f, VirtualChannel channel) throws IOException, InterruptedException { + // Just a default behavior to retain the compatibility + throw new IOException("The method has not been overridden. Cannot execute"); + } public static class Entry implements Serializable { diff --git a/src/main/java/hudson/plugins/filesystem_scm/RemoteCopyDir.java b/src/main/java/hudson/plugins/filesystem_scm/RemoteCopyDir.java index db8ba83..37a4526 100644 --- a/src/main/java/hudson/plugins/filesystem_scm/RemoteCopyDir.java +++ b/src/main/java/hudson/plugins/filesystem_scm/RemoteCopyDir.java @@ -1,14 +1,23 @@ package hudson.plugins.filesystem_scm; +import hudson.RestrictedSince; import java.io.File; import java.io.IOException; import org.apache.commons.io.FileUtils; -import hudson.FilePath.FileCallable; import hudson.remoting.VirtualChannel; +import jenkins.MasterToSlaveFileCallable; +import org.kohsuke.accmod.Restricted; +import org.kohsuke.accmod.restrictions.NoExternalUse; -public class RemoteCopyDir implements FileCallable { +/** + * @deprecated Not used anymore + */ +@Deprecated +@Restricted(NoExternalUse.class) +@RestrictedSince("1.21") +public class RemoteCopyDir extends MasterToSlaveFileCallable { private static final long serialVersionUID = 1L; diff --git a/src/main/java/hudson/plugins/filesystem_scm/RemoteFolderDiff.java b/src/main/java/hudson/plugins/filesystem_scm/RemoteFolderDiff.java index 78b97f0..a16bc37 100644 --- a/src/main/java/hudson/plugins/filesystem_scm/RemoteFolderDiff.java +++ b/src/main/java/hudson/plugins/filesystem_scm/RemoteFolderDiff.java @@ -1,7 +1,6 @@ package hudson.plugins.filesystem_scm; import hudson.FilePath; -import hudson.FilePath.FileCallable; import hudson.remoting.VirtualChannel; import hudson.tools.JDKInstaller.Platform; @@ -9,7 +8,7 @@ import java.util.ArrayList; import java.util.List; -public class RemoteFolderDiff extends FolderDiff { +public class RemoteFolderDiff extends FolderDiff { protected StringBuffer buf; protected long lastBuildTime; @@ -71,10 +70,11 @@ public String getLog() { return buf.toString(); } - public static class PollChange extends RemoteFolderDiff implements FileCallable { + public static class PollChange extends RemoteFolderDiff { private static final long serialVersionUID = 1L; - + + @Override public Boolean invoke(File workspace, VirtualChannel channel) throws IOException { setDstPath(workspace.getAbsolutePath()); List newFiles = getNewOrModifiedFiles(lastBuildTime, true, true); @@ -85,10 +85,11 @@ public Boolean invoke(File workspace, VirtualChannel channel) throws IOException } } - public static class CheckOut extends RemoteFolderDiff implements FileCallable< List > { + public static class CheckOut extends RemoteFolderDiff> { private static final long serialVersionUID = 1L; + @Override public List invoke(File workspace, VirtualChannel channel) throws IOException { setDstPath(workspace.getAbsolutePath()); List newFiles = getNewOrModifiedFiles(lastBuildTime, false, false); diff --git a/src/main/java/hudson/plugins/filesystem_scm/RemoteListDir.java b/src/main/java/hudson/plugins/filesystem_scm/RemoteListDir.java index 81e1c60..13f51ca 100644 --- a/src/main/java/hudson/plugins/filesystem_scm/RemoteListDir.java +++ b/src/main/java/hudson/plugins/filesystem_scm/RemoteListDir.java @@ -6,10 +6,10 @@ import org.apache.commons.io.FileUtils; -import hudson.FilePath.FileCallable; import hudson.remoting.VirtualChannel; +import jenkins.MasterToSlaveFileCallable; -public class RemoteListDir implements FileCallable< Set > { +public class RemoteListDir extends MasterToSlaveFileCallable< Set > { private static final long serialVersionUID = 1452212500874165127L; diff --git a/src/main/resources/hudson/plugins/filesystem_scm/ChangelogSet/digest.jelly b/src/main/resources/hudson/plugins/filesystem_scm/ChangelogSet/digest.jelly index efb35bc..b7463b7 100644 --- a/src/main/resources/hudson/plugins/filesystem_scm/ChangelogSet/digest.jelly +++ b/src/main/resources/hudson/plugins/filesystem_scm/ChangelogSet/digest.jelly @@ -1,3 +1,4 @@ + @@ -8,7 +9,7 @@
    1. - ${cs.msgAnnotated} (detail) + ${cs.msgAnnotated} (detail)
    diff --git a/src/main/resources/hudson/plugins/filesystem_scm/ChangelogSet/index.jelly b/src/main/resources/hudson/plugins/filesystem_scm/ChangelogSet/index.jelly index 37a4632..f957e6f 100644 --- a/src/main/resources/hudson/plugins/filesystem_scm/ChangelogSet/index.jelly +++ b/src/main/resources/hudson/plugins/filesystem_scm/ChangelogSet/index.jelly @@ -1,3 +1,4 @@ +

    ${%Summary}

    diff --git a/src/main/resources/hudson/plugins/filesystem_scm/FSSCM/config.jelly b/src/main/resources/hudson/plugins/filesystem_scm/FSSCM/config.jelly index 8925b9d..7a344d5 100644 --- a/src/main/resources/hudson/plugins/filesystem_scm/FSSCM/config.jelly +++ b/src/main/resources/hudson/plugins/filesystem_scm/FSSCM/config.jelly @@ -1,46 +1,13 @@ + - - + + - - + + - - - - - -
    - - -
    - - - - -
    - - - - - - - - -
    - - -
    -
    -
    -
    -
    - - - + + +
    diff --git a/src/main/webapp/help-clearWorkspace.html b/src/main/resources/hudson/plugins/filesystem_scm/FSSCM/help-clearWorkspace.html similarity index 100% rename from src/main/webapp/help-clearWorkspace.html rename to src/main/resources/hudson/plugins/filesystem_scm/FSSCM/help-clearWorkspace.html diff --git a/src/main/webapp/help-copyHidden.html b/src/main/resources/hudson/plugins/filesystem_scm/FSSCM/help-copyHidden.html similarity index 100% rename from src/main/webapp/help-copyHidden.html rename to src/main/resources/hudson/plugins/filesystem_scm/FSSCM/help-copyHidden.html diff --git a/src/main/webapp/help-path.html b/src/main/resources/hudson/plugins/filesystem_scm/FSSCM/help-path.html similarity index 100% rename from src/main/webapp/help-path.html rename to src/main/resources/hudson/plugins/filesystem_scm/FSSCM/help-path.html diff --git a/src/main/resources/hudson/plugins/filesystem_scm/FilterSelector/config.jelly b/src/main/resources/hudson/plugins/filesystem_scm/FilterSelector/config.jelly new file mode 100644 index 0000000..b93b09b --- /dev/null +++ b/src/main/resources/hudson/plugins/filesystem_scm/FilterSelector/config.jelly @@ -0,0 +1,6 @@ + + + + + + diff --git a/src/main/webapp/help-filterDetail.html b/src/main/resources/hudson/plugins/filesystem_scm/FilterSelector/help-wildcard.html similarity index 100% rename from src/main/webapp/help-filterDetail.html rename to src/main/resources/hudson/plugins/filesystem_scm/FilterSelector/help-wildcard.html diff --git a/src/main/resources/hudson/plugins/filesystem_scm/FilterSettings/config.jelly b/src/main/resources/hudson/plugins/filesystem_scm/FilterSettings/config.jelly new file mode 100644 index 0000000..18eb88f --- /dev/null +++ b/src/main/resources/hudson/plugins/filesystem_scm/FilterSettings/config.jelly @@ -0,0 +1,16 @@ + + + + + + + + +
    + +
    +
    +
    +
    +
    diff --git a/src/main/resources/hudson/plugins/filesystem_scm/FilterSettings/config.properties b/src/main/resources/hudson/plugins/filesystem_scm/FilterSettings/config.properties new file mode 100644 index 0000000..5052099 --- /dev/null +++ b/src/main/resources/hudson/plugins/filesystem_scm/FilterSettings/config.properties @@ -0,0 +1 @@ +includeFilter.title=Include filter (exclude otherwise) diff --git a/src/main/webapp/help-filter.html b/src/main/resources/hudson/plugins/filesystem_scm/FilterSettings/help-selectors.html similarity index 100% rename from src/main/webapp/help-filter.html rename to src/main/resources/hudson/plugins/filesystem_scm/FilterSettings/help-selectors.html diff --git a/src/main/resources/index.jelly b/src/main/resources/index.jelly index 5438e7a..cab9f30 100644 --- a/src/main/resources/index.jelly +++ b/src/main/resources/index.jelly @@ -1,3 +1,4 @@ +
    File System SCM
    \ No newline at end of file diff --git a/src/test/java/hudson/plugins/filesystem_scm/ChangelogSetXMLTest.java b/src/test/java/hudson/plugins/filesystem_scm/ChangelogSetXMLTest.java index 319746f..ef78f64 100644 --- a/src/test/java/hudson/plugins/filesystem_scm/ChangelogSetXMLTest.java +++ b/src/test/java/hudson/plugins/filesystem_scm/ChangelogSetXMLTest.java @@ -1,5 +1,6 @@ package hudson.plugins.filesystem_scm; +import hudson.model.Run; import java.util.*; import org.junit.*; import java.io.*; @@ -26,7 +27,7 @@ public void testToAndFromXML() throws IOException { handler.save(changeLogSet, tmp); - ChangelogSet out = handler.parse(null, tmp); + ChangelogSet out = handler.parse((Run)null, tmp); assertEquals(changeLogSet, out); } diff --git a/src/test/java/hudson/plugins/filesystem_scm/SimpleAntWildcardFilterTest.java b/src/test/java/hudson/plugins/filesystem_scm/SimpleAntWildcardFilterTest.java index 9a420b4..28a77aa 100644 --- a/src/test/java/hudson/plugins/filesystem_scm/SimpleAntWildcardFilterTest.java +++ b/src/test/java/hudson/plugins/filesystem_scm/SimpleAntWildcardFilterTest.java @@ -8,17 +8,18 @@ import org.apache.commons.io.filefilter.HiddenFileFilter; import org.apache.commons.io.filefilter.IOFileFilter; import org.junit.Assert; +import org.junit.Rule; import org.junit.Test; +import org.junit.rules.TemporaryFolder; public class SimpleAntWildcardFilterTest { + @Rule + public TemporaryFolder tmpDir = new TemporaryFolder(); + @Test - public void test1() throws IOException { - String tmp = System.getProperty("java.io.tmpdir"); - //System.out.println(tmp); - String sep = System.getProperty("file.separator"); - //System.out.println(sep); - File myDir = new File(tmp + sep + "abc001234" + sep + "def" + sep + "xyz.000"); + public void test1() throws IOException {; + File myDir = new File(tmpDir.getRoot(), "abc001234/def/xyz.000"); myDir.mkdirs(); File f1 = new File(myDir, "aa.txt"); f1.createNewFile(); @@ -27,8 +28,9 @@ public void test1() throws IOException { File f3 = new File(myDir.getParentFile(), "ab.tx1"); f3.createNewFile(); - IOFileFilter iof = new SimpleAntWildcardFilter("C:/users/samn/**/a?.tx?"); - Collection coll = (Collection)FileUtils.listFiles(new File(tmp + sep + "abc001234"), iof, HiddenFileFilter.VISIBLE); + IOFileFilter iof = new SimpleAntWildcardFilter(tmpDir.getRoot().getAbsolutePath() + "/**/a?.tx?"); + File checkDir = new File(tmpDir.getRoot(), "abc001234"); + Collection coll = FileUtils.listFiles(checkDir, iof, HiddenFileFilter.VISIBLE); Assert.assertEquals(2, coll.size()); } diff --git a/src/test/java/hudson/plugins/filesystem_scm/integration/pipeline/PipelineLibraryTest.java b/src/test/java/hudson/plugins/filesystem_scm/integration/pipeline/PipelineLibraryTest.java new file mode 100644 index 0000000..3277c4e --- /dev/null +++ b/src/test/java/hudson/plugins/filesystem_scm/integration/pipeline/PipelineLibraryTest.java @@ -0,0 +1,48 @@ +package hudson.plugins.filesystem_scm.integration.pipeline; + +import hudson.plugins.filesystem_scm.FSSCM; +import hudson.plugins.filesystem_scm.FilterSelector; +import hudson.plugins.filesystem_scm.FilterSettings; +import java.io.File; +import java.util.Collections; +import org.apache.commons.io.FileUtils; +import org.jenkinsci.plugins.workflow.cps.CpsScmFlowDefinition; +import org.jenkinsci.plugins.workflow.job.WorkflowJob; +import org.junit.Ignore; +import org.junit.Rule; +import org.junit.Test; +import org.junit.rules.TemporaryFolder; +import org.jvnet.hudson.test.JenkinsRule; + +/** + * Tests for Jenkins Pipeline integration. + * + * @author Oleg Nenashev + */ +public class PipelineLibraryTest { + + @Rule + public JenkinsRule j = new JenkinsRule(); + + @Rule + public TemporaryFolder tmpDir = new TemporaryFolder(); + + //TODO: JenkinsRule just hangs on mvn clean verify, passes for test file run + @Test + @Ignore + public void shouldSupportFSSCMsJenkinsfileSource() throws Exception { + + // Init repo + File fsscmDir = tmpDir.newFolder("fsscm"); + File jenkinsfile = new File(fsscmDir, "Jenkinsfile"); + FileUtils.write(jenkinsfile, "echo `Hello`"); + + // Create job + WorkflowJob job = new WorkflowJob(j.jenkins, "MyPipeline"); + job.setDefinition(new CpsScmFlowDefinition(new FSSCM(null, false, false, + new FilterSettings(true, Collections.emptyList())), "Jenkinsfile")); + + j.buildAndAssertSuccess(job); + } + +}