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 extends Entry> 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 @@
-
- ${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);
+ }
+
+}