Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with HTTPS or Subversion.

Download ZIP

Comparing changes

Choose two branches to see what's changed or to start a new pull request. If you need to, you can also compare across forks.

Open a pull request

Create a new pull request by comparing changes across two branches. If you need to, you can also compare across forks.
base fork: jenkinsci/perforce-plugin
...
head fork: jenkinsci/perforce-plugin
Checking mergeability… Don't worry, you can still create the pull request.
  • 5 commits
  • 16 files changed
  • 0 commit comments
  • 2 contributors
Showing with 546 additions and 35 deletions.
  1. +3 −0  .gitignore
  2. +1 −1  pom.xml
  3. +92 −14 src/main/java/hudson/plugins/perforce/PerforceSCM.java
  4. +158 −0 src/main/java/hudson/plugins/perforce/PerforceToolInstallation.java
  5. +1 −0  src/main/resources/hudson/plugins/perforce/Messages.properties
  6. +23 −15 src/main/resources/hudson/plugins/perforce/PerforceSCM/config.jelly
  7. +8 −0 src/main/resources/hudson/plugins/perforce/PerforceToolInstallation/config.jelly
  8. +3 −0  src/main/webapp/help/globalConfig.html
  9. +55 −5 src/test/java/hudson/plugins/perforce/PerforceSCMTest.java
  10. +49 −0 src/test/resources/hudson/plugins/perforce/PerforceSCMTest/testP4ExeMigration/config.xml
  11. +50 −0 ...resources/hudson/plugins/perforce/PerforceSCMTest/testP4ExeMigration/jobs/test_p4exe_migration_1/config.xml
  12. +1 −0  ...rces/hudson/plugins/perforce/PerforceSCMTest/testP4ExeMigration/jobs/test_p4exe_migration_1/nextBuildNumber
  13. +50 −0 ...resources/hudson/plugins/perforce/PerforceSCMTest/testP4ExeMigration/jobs/test_p4exe_migration_2/config.xml
  14. +1 −0  ...rces/hudson/plugins/perforce/PerforceSCMTest/testP4ExeMigration/jobs/test_p4exe_migration_2/nextBuildNumber
  15. +50 −0 ...resources/hudson/plugins/perforce/PerforceSCMTest/testP4ExeMigration/jobs/test_p4exe_migration_3/config.xml
  16. +1 −0  ...rces/hudson/plugins/perforce/PerforceSCMTest/testP4ExeMigration/jobs/test_p4exe_migration_3/nextBuildNumber
View
3  .gitignore
@@ -3,3 +3,6 @@
*.iws
target
work
+.classpath
+.settings
+.project
View
2  pom.xml
@@ -11,7 +11,7 @@
<artifactId>perforce</artifactId>
<name>Perforce Plugin</name>
<packaging>hpi</packaging>
- <version>1.3.8</version>
+ <version>1.3.9</version>
<url>http://wiki.jenkins-ci.org/display/JENKINS/Perforce+Plugin</url>
<developers>
View
106 src/main/java/hudson/plugins/perforce/PerforceSCM.java
@@ -90,7 +90,11 @@
String p4Counter;
String p4Stream;
- String p4Exe = "C:\\Program Files\\Perforce\\p4.exe";
+ /**
+ * Transient so that old XML data will be read but not saved.
+ * @deprecated Replaced by {@link #p4Tool}
+ */
+ transient String p4Exe;
String p4SysDrive = "C:";
String p4SysRoot = "C:\\WINDOWS";
@@ -100,6 +104,11 @@
private static final int MAX_CHANGESETS_ON_FIRST_BUILD = 50;
+ /**
+ * Name of the p4 tool installation
+ */
+ String p4Tool;
+
/**
* Use ClientSpec text file from depot to prepare the workspace view
*/
@@ -143,7 +152,7 @@
/**
* If true, we will create the workspace view within the plugin. If false, we will not.
*/
- boolean createWorkspace = true;
+ Boolean createWorkspace = true;
/**
* If true, we will manage the workspace view within the plugin. If false, we will leave the
* view alone.
@@ -250,7 +259,7 @@ public PerforceSCM(
String p4Client,
String p4Port,
String projectOptions,
- String p4Exe,
+ String p4Tool,
String p4SysRoot,
String p4SysDrive,
String p4Label,
@@ -283,6 +292,7 @@ public PerforceSCM(
this.exposeP4Passwd = exposeP4Passwd;
this.p4Client = p4Client;
this.p4Port = p4Port;
+ this.p4Tool = p4Tool;
this.pollOnlyOnMaster = pollOnlyOnMaster;
this.projectOptions = (projectOptions != null)
? projectOptions
@@ -300,9 +310,6 @@ public PerforceSCM(
this.projectPath = Util.fixEmptyAndTrim(projectPath);
- if (p4Exe != null)
- this.p4Exe = Util.fixEmptyAndTrim(p4Exe);
-
if (p4SysRoot != null && p4SysRoot.length() != 0)
this.p4SysRoot = Util.fixEmptyAndTrim(p4SysRoot);
@@ -346,7 +353,7 @@ public PerforceSCM(
this.browser = browser;
this.wipeBeforeBuild = wipeBeforeBuild;
this.wipeRepoBeforeBuild = wipeRepoBeforeBuild;
- this.createWorkspace = createWorkspace;
+ this.createWorkspace = Boolean.valueOf(createWorkspace);
this.updateView = updateView;
this.dontUpdateClient = dontUpdateClient;
this.slaveClientNameFormat = slaveClientNameFormat;
@@ -392,7 +399,7 @@ else if(project != null)
depot.setPassword(getDecryptedP4Passwd());
}
- depot.setExecutable(p4Exe);
+ depot.setExecutable(getP4Executable(p4Tool));
depot.setSystemDrive(p4SysDrive);
depot.setSystemRoot(p4SysRoot);
@@ -446,6 +453,43 @@ else if (pta.getTag() != null) {
}
}
+ /**
+ * Get the path to p4 executable from a Perforce tool installation.
+ *
+ * @param tool the p4 tool installation
+ * @return path to p4 executable or empty string if there are no tool installations
+ */
+ public String getP4Executable(String tool) {
+ PerforceToolInstallation[] installations = ((hudson.plugins.perforce.PerforceToolInstallation.DescriptorImpl)Hudson.getInstance().
+ getDescriptorByType(PerforceToolInstallation.DescriptorImpl.class)).getInstallations();
+ for(PerforceToolInstallation i : installations) {
+ if(i.getName().equals(tool)) {
+ return i.getP4Exe();
+ }
+ }
+ return "";
+ }
+
+ /**
+ * Use the old job configuration data. This method is called after the object is read by XStream.
+ * We want to create tool installations for each individual "p4Exe" path as field "p4Exe" has been removed.
+ *
+ * @return the new object which is an instance of PerforceSCM
+ */
+ public Object readResolve() {
+ if (createWorkspace == null)
+ {
+ createWorkspace = Boolean.TRUE;
+ }
+
+ if (p4Exe != null)
+ {
+ PerforceToolInstallation.migrateOldData(p4Exe);
+ p4Tool = p4Exe;
+ }
+ return this;
+ }
+
private Hashtable<String, String> getDefaultSubstitutions(AbstractProject project) {
Hashtable<String, String> subst = new Hashtable<String, String>();
subst.put("JOB_NAME", getSafeJobName(project));
@@ -1437,6 +1481,16 @@ public SCM newInstance(StaplerRequest req, JSONObject formData) throws FormExcep
return newInstance;
}
+ /**
+ * List available tool installations.
+ *
+ * @return list of available p4 tool installations
+ */
+ public List<PerforceToolInstallation> getP4Tools() {
+ PerforceToolInstallation[] p4ToolInstallations = Hudson.getInstance().getDescriptorByType(PerforceToolInstallation.DescriptorImpl.class).getInstallations();
+ return Arrays.asList(p4ToolInstallations);
+ }
+
public String isValidProjectPath(String path) {
if (!path.startsWith("//")) {
return "Path must start with '//' (Example: //depot/ProjectName/...)";
@@ -1451,11 +1505,11 @@ public String isValidProjectPath(String path) {
protected Depot getDepotFromRequest(StaplerRequest request) {
String port = fixNull(request.getParameter("port")).trim();
- String exe = fixNull(request.getParameter("exe")).trim();
+ String tool = fixNull(request.getParameter("tool")).trim();
String user = fixNull(request.getParameter("user")).trim();
String pass = fixNull(request.getParameter("pass")).trim();
- if (port.length() == 0 || exe.length() == 0) { // Not enough entered yet
+ if (port.length() == 0 || tool.length() == 0) { // Not enough entered yet
return null;
}
Depot depot = new Depot();
@@ -1468,7 +1522,17 @@ protected Depot getDepotFromRequest(StaplerRequest request) {
depot.setPassword(pass);
}
depot.setPort(port);
+
+ String exe = "";
+ PerforceToolInstallation[] installations = ((hudson.plugins.perforce.PerforceToolInstallation.DescriptorImpl)Hudson.getInstance().
+ getDescriptorByType(PerforceToolInstallation.DescriptorImpl.class)).getInstallations();
+ for(PerforceToolInstallation i : installations) {
+ if(i.getName().equals(tool)) {
+ exe = i.getP4Exe();
+ }
+ }
depot.setExecutable(exe);
+
try {
Counter counter = depot.getCounters().getCounter("change");
if (counter != null)
@@ -2117,18 +2181,32 @@ public void setP4SysRoot(String sysRoot) {
}
/**
- * @return the p4Exe
+ * @deprecated Replaced by {@link #getP4Tool()}
*/
public String getP4Exe() {
return p4Exe;
}
/**
- * @param exe the p4Exe to set
+ * @deprecated Replaced by {@link #setP4Tool(String)}
*/
public void setP4Exe(String exe) {
p4Exe = exe;
}
+
+ /**
+ * @return the p4Tool
+ */
+ public String getP4Tool() {
+ return p4Tool;
+ }
+
+ /**
+ * @param tool the p4 tool installation to set
+ */
+ public void setP4Tool(String tool) {
+ p4Tool = tool;
+ }
/**
* @return the p4Label
@@ -2206,14 +2284,14 @@ public void setProjectOptions(String projectOptions) {
* @param createWorkspace True to let the plugin create the workspace, false to let the user manage it
*/
public void setCreateWorkspace(boolean val) {
- this.createWorkspace = val;
+ this.createWorkspace = Boolean.valueOf(val);
}
/**
* @return True if the plugin manages the view, false if the user does.
*/
public boolean isCreateWorkspace() {
- return createWorkspace;
+ return createWorkspace.booleanValue();
}
/**
View
158 src/main/java/hudson/plugins/perforce/PerforceToolInstallation.java
@@ -0,0 +1,158 @@
+package hudson.plugins.perforce;
+
+import hudson.CopyOnWrite;
+import hudson.EnvVars;
+import hudson.Extension;
+import hudson.init.InitMilestone;
+import hudson.init.Initializer;
+import hudson.model.EnvironmentSpecific;
+import hudson.model.Hudson;
+import hudson.model.Node;
+import hudson.model.TaskListener;
+import hudson.slaves.NodeSpecific;
+import hudson.tools.ToolDescriptor;
+import hudson.tools.ToolInstallation;
+import hudson.tools.ToolProperty;
+import hudson.util.FormValidation;
+import net.sf.json.JSONObject;
+import org.kohsuke.stapler.DataBoundConstructor;
+import org.kohsuke.stapler.QueryParameter;
+import org.kohsuke.stapler.StaplerRequest;
+
+import javax.servlet.ServletException;
+import java.io.File;
+import java.io.IOException;
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.List;
+
+
+/**
+ * Information about Perforce installation. This includes the path to p4 executable.
+ *
+ */
+public final class PerforceToolInstallation extends ToolInstallation implements NodeSpecific<PerforceToolInstallation>, EnvironmentSpecific<PerforceToolInstallation> {
+
+ //To store migrated data as all the tool installations are created on one go.
+ static transient ArrayList<PerforceToolInstallation> p4Tools = new ArrayList<PerforceToolInstallation>();
+
+ /**
+ * Default constructor.
+ *
+ * @param name Installation name
+ * @param home Path to p4.exe
+ * @param properties Additional tool installation data
+ */
+ @DataBoundConstructor
+ public PerforceToolInstallation(String name, String home, List<? extends ToolProperty<?>> properties) {
+ super(name, home, properties);
+ }
+
+ /**
+ * Get the path to p4.exe
+ *
+ * @return Path to p4.exe
+ */
+ public String getP4Exe() {
+ return getHome();
+ }
+
+ /**
+ * Migrate old data into new tool installations if needed.
+ */
+ @Initializer(after=InitMilestone.JOB_LOADED)
+ public static void onLoaded() {
+ DescriptorImpl descriptor = (DescriptorImpl) Hudson.getInstance().getDescriptor(PerforceToolInstallation.class);
+ PerforceToolInstallation[] installations = descriptor.getInstallations();
+
+ //Allow only one migration round. Old "p4Exe" field is kept in job configuration until the job is saved.
+ if (installations.length > 0) {
+ return;
+ }
+
+ if (!p4Tools.isEmpty()) {
+ Hudson.getInstance().getDescriptorByType(DescriptorImpl.class).setInstallations(p4Tools.toArray(new PerforceToolInstallation[p4Tools.size()]));
+ }
+ }
+
+ /**
+ * Migrate data from old job specific "p4Exe" field. Create a tool installation for each
+ * individual path with the path as the tool name.
+ *
+ * @param exe The path to p4 executable
+ */
+ public static void migrateOldData(String exe) {
+ for (PerforceToolInstallation tool : p4Tools) {
+ //Tool installation already exists, Unix case
+ if (File.separatorChar == '/' && tool.getName().equals(exe)) {
+ return;
+ }
+ //Tool installation already exists, Windows case
+ if (File.separatorChar != '/' && tool.getName().equalsIgnoreCase(exe)) {
+ return;
+ }
+ }
+ p4Tools.add(new PerforceToolInstallation(exe, exe, Collections.<ToolProperty<?>>emptyList()));
+ }
+
+ public PerforceToolInstallation forNode(Node node, TaskListener log) throws IOException, InterruptedException {
+ return new PerforceToolInstallation(getName(), translateFor(node, log), Collections.<ToolProperty<?>>emptyList());
+ }
+
+ public PerforceToolInstallation forEnvironment(EnvVars environment) {
+ return new PerforceToolInstallation(getName(), environment.expand(getHome()), Collections.<ToolProperty<?>>emptyList());
+ }
+
+ @Override
+ public DescriptorImpl getDescriptor() {
+ return (DescriptorImpl) Hudson.getInstance().getDescriptor(PerforceToolInstallation.class);
+ }
+
+ @Extension
+ public static class DescriptorImpl extends ToolDescriptor<PerforceToolInstallation> {
+ @CopyOnWrite
+ private volatile PerforceToolInstallation[] installations = new PerforceToolInstallation[0];
+
+ public DescriptorImpl() {
+ super();
+ load();
+ }
+
+ @Override
+ public String getDisplayName() {
+ return "Perforce";
+ }
+
+ @Override
+ public boolean configure(StaplerRequest req, JSONObject json) throws FormException {
+ super.configure(req, json);
+ save();
+ return true;
+ }
+
+ @Override
+ public PerforceToolInstallation[] getInstallations() {
+ return installations;
+ }
+
+ @Override
+ public void setInstallations(PerforceToolInstallation... installations) {
+ this.installations = installations;
+ save();
+ }
+
+ /**
+ * Checks if the path to p4 executable exists.
+ */
+ public FormValidation doCheckHome(@QueryParameter File value)
+ throws IOException, ServletException {
+
+ Hudson.getInstance().checkPermission(Hudson.ADMINISTER);
+ String path = value.getPath();
+
+ return FormValidation.validateExecutable(path);
+ }
+ }
+
+}
+
View
1  src/main/resources/hudson/plugins/perforce/Messages.properties
@@ -0,0 +1 @@
+PerforceToolInstallation.onLoaded=Checking p4 executable migration
View
38 src/main/resources/hudson/plugins/perforce/PerforceSCM/config.jelly
@@ -7,14 +7,6 @@
<j:set var="streamDepotUsed" value="${instance.useStreamDepot}"/>
</j:if>
- <f:entry title="Setup" help="/plugin/perforce/help/setup.html">
- <table width="100%">
- <f:entry title="Path to p4 executable">
- <f:textbox field="p4Exe" id="p4Exe"/>
- </f:entry>
- </table>
- </f:entry>
-
<f:entry title="Depot" help="/plugin/perforce/help/depot.html">
<table width="100%">
<f:entry title="P4PORT (hostname:port)">
@@ -27,7 +19,7 @@
<f:entry title="Password">
<f:password field="p4Passwd" id="p4Passwd"
- checkUrl="'${rootURL}/scm/PerforceSCM/validatePerforceLogin?port='+escape(this.form.elements['p4Port'].value)+'&amp;exe='+escape(this.form.elements['p4Exe'].value)+'&amp;user='+escape(this.form.elements['p4User'].value)+'&amp;pass='+escape(this.form.elements['p4Passwd'].value)"/>
+ checkUrl="'${rootURL}/scm/PerforceSCM/validatePerforceLogin?port='+escape(this.form.elements['p4Port'].value)+'&amp;tool='+escape(this.form.elements['p4Tool'].value)+'&amp;user='+escape(this.form.elements['p4User'].value)+'&amp;pass='+escape(this.form.elements['p4Passwd'].value)"/>
</f:entry>
<f:entry title="Expose P4PASSWD in environment" help="/plugin/perforce/help/exposeP4Passwd.html">
@@ -40,7 +32,7 @@
<table width="100%">
<f:entry title="Workspace (client)" help="/plugin/perforce/help/p4Client.html">
<f:textbox field="p4Client" id="p4Client"
- checkUrl="'${rootURL}/scm/PerforceSCM/validateP4Client?port='+escape(this.form.elements['p4Port'].value)+'&amp;exe='+escape(this.form.elements['p4Exe'].value)+'&amp;user='+escape(this.form.elements['p4User'].value)+'&amp;pass='+escape(this.form.elements['p4Passwd'].value)+'&amp;client='+escape(this.form.elements['p4Client'].value)"/>
+ checkUrl="'${rootURL}/scm/PerforceSCM/validateP4Client?port='+escape(this.form.elements['p4Port'].value)+'&amp;tool='+escape(this.form.elements['p4Tool'].value)+'&amp;user='+escape(this.form.elements['p4User'].value)+'&amp;pass='+escape(this.form.elements['p4Passwd'].value)+'&amp;client='+escape(this.form.elements['p4Client'].value)"/>
</f:entry>
<f:entry title="Let ${descriptor['appName']} Create Workspace" help="/plugin/perforce/help/createWorkspace.html">
<f:checkbox field="createWorkspace" default="true" value="True"/>
@@ -54,13 +46,13 @@
<f:radioBlock name="p4.depotType" title="Stream" value="stream" checked="${instance.useStreamDepot}" help="/plugin/perforce/help/streamDepot.html">
<f:entry title="Stream" help="/plugin/perforce/help/p4Stream.html">
<f:textbox name="p4Stream" field="p4Stream"
- checkUrl="'${rootURL}/scm/PerforceSCM/validateStream?port='+escape(this.form.elements['p4Port'].value)+'&amp;exe='+escape(this.form.elements['p4Exe'].value)+'&amp;user='+escape(this.form.elements['p4User'].value)+'&amp;pass='+escape(this.form.elements['p4Passwd'].value)+'&amp;client='+escape(this.form.elements['p4Client'].value)+'&amp;stream='+escape(this.form.elements['p4Stream'].value)"/>
+ checkUrl="'${rootURL}/scm/PerforceSCM/validateStream?port='+escape(this.form.elements['p4Port'].value)+'&amp;tool='+escape(this.form.elements['p4Tool'].value)+'&amp;user='+escape(this.form.elements['p4User'].value)+'&amp;pass='+escape(this.form.elements['p4Passwd'].value)+'&amp;client='+escape(this.form.elements['p4Client'].value)+'&amp;stream='+escape(this.form.elements['p4Stream'].value)"/>
</f:entry>
</f:radioBlock>
<f:radioBlock name="p4.depotType" title="View Map from File" value="file" checked="${instance.useClientSpec and !instance.useStreamDepot}" help="/plugin/perforce/help/clientSpec.html">
<f:entry>
<f:textbox name="clientSpec" field="clientSpec"
- checkUrl="'${rootURL}/scm/PerforceSCM/validateClientSpec?port='+escape(this.form.elements['p4Port'].value)+'&amp;exe='+escape(this.form.elements['p4Exe'].value)+'&amp;user='+escape(this.form.elements['p4User'].value)+'&amp;pass='+escape(this.form.elements['p4Passwd'].value)+'&amp;client='+escape(this.form.elements['p4Client'].value)+'&amp;clientSpec='+escape(this.form.elements['clientSpec'].value)"/>
+ checkUrl="'${rootURL}/scm/PerforceSCM/validateClientSpec?port='+escape(this.form.elements['p4Port'].value)+'&amp;tool='+escape(this.form.elements['p4Tool'].value)+'&amp;user='+escape(this.form.elements['p4User'].value)+'&amp;pass='+escape(this.form.elements['p4Passwd'].value)+'&amp;client='+escape(this.form.elements['p4Client'].value)+'&amp;clientSpec='+escape(this.form.elements['clientSpec'].value)"/>
</f:entry>
</f:radioBlock>
<f:radioBlock name="p4.depotType" title="View Map" value="map" checked="${!instance.useClientSpec and !instance.useStreamDepot}" help="/plugin/perforce/help/projectPath.html">
@@ -75,6 +67,22 @@
</f:entry>
<f:advanced>
+
+ <f:entry title="P4 executable" field="p4Tool">
+ <select name="p4Tool">
+ <j:forEach var="p4Tool" items="${descriptor.P4Tools}" varStatus="current">
+ <j:choose>
+ <j:when test="${instance.p4Tool==p4Tool.name}">
+ <option value="${p4Tool.name}" selected="SELECTED">${p4Tool.name}</option>
+ </j:when>
+ <j:otherwise>
+ <option value="${p4Tool.name}">${p4Tool.name}</option>
+ </j:otherwise>
+ </j:choose>
+ </j:forEach>
+ </select>
+ </f:entry>
+
<f:entry title="Clean Workspace Before Each Build" help="/plugin/perforce/help/wipeBeforeBuild.html">
<f:checkbox field="wipeBeforeBuild" default="false" value="False"/>
</f:entry>
@@ -110,7 +118,7 @@
<f:entry title="First Changelist to Track" help="/plugin/perforce/help/firstChange.html">
<f:textbox field="firstChange"
- checkUrl="'${rootURL}/scm/PerforceSCM/checkChangeList?port='+escape(this.form.elements['p4Port'].value)+'&amp;exe='+escape(this.form.elements['p4Exe'].value)+'&amp;user='+escape(this.form.elements['p4User'].value)+'&amp;pass='+escape(this.form.elements['p4Passwd'].value)+'&amp;change='+escape(this.value)"/>
+ checkUrl="'${rootURL}/scm/PerforceSCM/checkChangeList?port='+escape(this.form.elements['p4Port'].value)+'&amp;tool='+escape(this.form.elements['p4Tool'].value)+'&amp;user='+escape(this.form.elements['p4User'].value)+'&amp;pass='+escape(this.form.elements['p4Passwd'].value)+'&amp;change='+escape(this.value)"/>
</f:entry>
<f:entry title="Client Line Endings" help="/plugin/perforce/help/lineEnd.html">
@@ -123,12 +131,12 @@
<f:entry title="P4 Label" help="/plugin/perforce/help/p4label.html">
<f:textbox field="p4Label" id="p4Label"
- checkUrl="'${rootURL}/scm/PerforceSCM/validateP4Label?label='+escape(this.form.elements['p4Label'].value)+'&amp;port='+escape(this.form.elements['p4Port'].value)+'&amp;exe='+escape(this.form.elements['p4Exe'].value)+'&amp;user='+escape(this.form.elements['p4User'].value)+'&amp;pass='+escape(this.form.elements['p4Passwd'].value)"/>
+ checkUrl="'${rootURL}/scm/PerforceSCM/validateP4Label?label='+escape(this.form.elements['p4Label'].value)+'&amp;port='+escape(this.form.elements['p4Port'].value)+'&amp;tool='+escape(this.form.elements['p4Tool'].value)+'&amp;user='+escape(this.form.elements['p4User'].value)+'&amp;pass='+escape(this.form.elements['p4Passwd'].value)"/>
</f:entry>
<f:entry title="P4 Counter" help="/plugin/perforce/help/p4counter.html">
<f:textbox field="p4Counter" id="p4Counter"
- checkUrl="'${rootURL}/scm/PerforceSCM/validateP4Counter?counter='+escape(this.form.elements['p4Counter'].value)+'&amp;port='+escape(this.form.elements['p4Port'].value)+'&amp;exe='+escape(this.form.elements['p4Exe'].value)+'&amp;user='+escape(this.form.elements['p4User'].value)+'&amp;pass='+escape(this.form.elements['p4Passwd'].value)"/>
+ checkUrl="'${rootURL}/scm/PerforceSCM/validateP4Counter?counter='+escape(this.form.elements['p4Counter'].value)+'&amp;port='+escape(this.form.elements['p4Port'].value)+'&amp;tool='+escape(this.form.elements['p4Tool'].value)+'&amp;user='+escape(this.form.elements['p4User'].value)+'&amp;pass='+escape(this.form.elements['p4Passwd'].value)"/>
</f:entry>
<f:entry title="Update counter to most recent changeset" help="/plugin/perforce/help/updateCounterValue.html">
View
8 src/main/resources/hudson/plugins/perforce/PerforceToolInstallation/config.jelly
@@ -0,0 +1,8 @@
+<j:jelly xmlns:j="jelly:core" xmlns:st="jelly:stapler" xmlns:d="jelly:define" xmlns:l="/lib/layout" xmlns:t="/lib/hudson" xmlns:f="/lib/form">
+ <f:entry title="Name" field="name">
+ <f:textbox />
+ </f:entry>
+ <f:entry title="Path to p4.exe" field="home" help="/plugin/perforce/help/globalConfig.html">
+ <f:textbox />
+ </f:entry>
+</j:jelly>
View
3  src/main/webapp/help/globalConfig.html
@@ -0,0 +1,3 @@
+<div>
+ Set path to p4 executable. This can be just "p4" or complete path.
+</div>
View
60 src/test/java/hudson/plugins/perforce/PerforceSCMTest.java
@@ -1,13 +1,18 @@
package hudson.plugins.perforce;
import hudson.model.FreeStyleProject;
+import hudson.model.Hudson;
+import hudson.plugins.perforce.PerforceToolInstallation.DescriptorImpl;
import hudson.plugins.perforce.browsers.P4Web;
+import hudson.tools.ToolProperty;
import java.net.URL;
import java.util.Arrays;
+import java.util.Collections;
import java.util.List;
import org.jvnet.hudson.test.HudsonTestCase;
+import org.jvnet.hudson.test.recipes.LocalData;
/**
* @author Kohsuke Kawaguchi
@@ -62,9 +67,13 @@ public void testConfigRoundtripWithStream() throws Exception {
public void testConfigPasswordEnctyptionAndDecription() throws Exception {
FreeStyleProject project = createFreeStyleProject();
P4Web browser = new P4Web(new URL("http://localhost/"));
+ PerforceToolInstallation tool = new PerforceToolInstallation("test_installation", "p4.exe", Collections.<ToolProperty<?>>emptyList());
+ DescriptorImpl descriptor = (DescriptorImpl) Hudson.getInstance().getDescriptor(PerforceToolInstallation.class);
+ descriptor.setInstallations(new PerforceToolInstallation[] { tool });
+ descriptor.save();
String password = "pass";
PerforceSCM scm = new PerforceSCM(
- "user", password, "client", "port", "", "exe", "sysRoot",
+ "user", password, "client", "port", "", "test_installation", "sysRoot",
"sysDrive", "label", "counter", "shared", "charset", "charset2", false, true, true, true, true, true, false,
false, true, false, false, false, false, "${basename}", 0, browser, "exclude_user", "exclude_file");
scm.setProjectPath("path");
@@ -75,7 +84,7 @@ public void testConfigPasswordEnctyptionAndDecription() throws Exception {
// verify that the data is intact
assertEqualBeans(scm, project.getScm(),
- "p4User,p4Client,p4Port,p4Label,projectPath,p4Exe,p4SysRoot,p4SysDrive,forceSync,alwaysForceSync,dontUpdateClient,createWorkspace,updateView,slaveClientNameFormat,lineEndValue,firstChange,p4Counter,updateCounterValue,exposeP4Passwd,useViewMaskForPolling,viewMask,useViewMaskForSyncing,p4Charset,p4CommandCharset,p4Stream,useStreamDepot");
+ "p4User,p4Client,p4Port,p4Label,projectPath,p4Tool,p4SysRoot,p4SysDrive,forceSync,alwaysForceSync,dontUpdateClient,updateView,slaveClientNameFormat,lineEndValue,firstChange,p4Counter,updateCounterValue,exposeP4Passwd,useViewMaskForPolling,viewMask,useViewMaskForSyncing,p4Charset,p4CommandCharset,p4Stream,useStreamDepot");
assertEquals("exclude_user", scm.getExcludedUsers());
assertEquals("exclude_file", scm.getExcludedFiles());
@@ -87,9 +96,13 @@ public void testConfigPasswordEnctyptionAndDecription() throws Exception {
public void testDepotContainsUnencryptedPassword() throws Exception {
FreeStyleProject project = createFreeStyleProject();
P4Web browser = new P4Web(new URL("http://localhost/"));
+ PerforceToolInstallation tool = new PerforceToolInstallation("test_installation", "p4.exe", Collections.<ToolProperty<?>>emptyList());
+ DescriptorImpl descriptor = (DescriptorImpl) Hudson.getInstance().getDescriptor(PerforceToolInstallation.class);
+ descriptor.setInstallations(new PerforceToolInstallation[] { tool });
+ descriptor.save();
String password = "pass";
PerforceSCM scm = new PerforceSCM(
- "user", password, "client", "port", "", "exe", "sysRoot",
+ "user", password, "client", "port", "", "test_installation", "sysRoot",
"sysDrive", "label", "counter", "shared", "charset", "charset2", false, true, true, true, true, true, false,
false, true, false, false, false, false, "${basename}", 0, browser, "exclude_user", "exclude_file");
scm.setProjectPath("path");
@@ -101,9 +114,13 @@ public void testDepotContainsUnencryptedPassword() throws Exception {
public void testConfigSaveReloadAndSaveDoesNotDoubleEncryptThePassword() throws Exception {
FreeStyleProject project = createFreeStyleProject();
P4Web browser = new P4Web(new URL("http://localhost/"));
+ PerforceToolInstallation tool = new PerforceToolInstallation("test_installation", "p4.exe", Collections.<ToolProperty<?>>emptyList());
+ DescriptorImpl descriptor = (DescriptorImpl) Hudson.getInstance().getDescriptor(PerforceToolInstallation.class);
+ descriptor.setInstallations(new PerforceToolInstallation[] { tool });
+ descriptor.save();
String password = "pass";
PerforceSCM scm = new PerforceSCM(
- "user", password, "client", "port", "", "exe", "sysRoot",
+ "user", password, "client", "port", "", "test_installation", "sysRoot",
"sysDrive", "label", "counter", "shared", "charset", "charset2", false, true, true, true, true, true, false,
false, true, false, false, false, false, "${basename}", 0, browser, "exclude_user", "exclude_file");
scm.setProjectPath("path");
@@ -115,7 +132,7 @@ public void testConfigSaveReloadAndSaveDoesNotDoubleEncryptThePassword() throws
// verify that the data is intact
assertEqualBeans(scm, project.getScm(),
- "p4User,p4Client,p4Port,p4Label,projectPath,p4Exe,p4SysRoot,p4SysDrive,forceSync,alwaysForceSync,dontUpdateClient,createWorkspace,updateView,slaveClientNameFormat,lineEndValue,firstChange,p4Counter,updateCounterValue,exposeP4Passwd,useViewMaskForPolling,viewMask,useViewMaskForSyncing,p4Charset,p4CommandCharset,p4Stream,useStreamDepot");
+ "p4User,p4Client,p4Port,p4Label,projectPath,p4Tool,p4SysRoot,p4SysDrive,forceSync,alwaysForceSync,dontUpdateClient,updateView,slaveClientNameFormat,lineEndValue,firstChange,p4Counter,updateCounterValue,exposeP4Passwd,useViewMaskForPolling,viewMask,useViewMaskForSyncing,p4Charset,p4CommandCharset,p4Stream,useStreamDepot");
assertEquals("exclude_user", scm.getExcludedUsers());
assertEquals("exclude_file", scm.getExcludedFiles());
@@ -224,4 +241,37 @@ public void testFilenameP4PatternMatcher() throws Exception {
"//depot/.../file*"));
}
+ /** Test migration from "p4Exe" field to tool installation.
+ *
+ * @throws Exception
+ */
+ @LocalData
+ public void testP4ExeMigration() throws Exception {
+ DescriptorImpl descriptor = (DescriptorImpl) Hudson.getInstance().getDescriptor(PerforceToolInstallation.class);
+ PerforceToolInstallation[] expected = new PerforceToolInstallation[] {
+ new PerforceToolInstallation("c:\\program files\\perforce\\p4.exe", "c:\\program files\\perforce\\p4.exe", Collections.<ToolProperty<?>>emptyList()),
+ new PerforceToolInstallation("p4.exe", "p4.exe", Collections.<ToolProperty<?>>emptyList())
+ };
+ assertEquals(expected, descriptor.getInstallations());
+ }
+
+ /**
+ * Helper method to check that PerforceToolInstallations match.
+ *
+ * @param expected Expected PerforceToolInstallation
+ * @param actual Actual PerforceToolInstallation
+ */
+ static void assertEquals(PerforceToolInstallation[] expected, PerforceToolInstallation[] actual) {
+ assertEquals("Was expecting " + expected.length + " tool installations but got " + actual.length + " instead.", expected.length, actual.length);
+ for (PerforceToolInstallation actualTool : actual) {
+ boolean found = false;
+ for (PerforceToolInstallation expectedTool : expected) {
+ if (expectedTool.getName().equals(actualTool.getName()) && expectedTool.getHome().equals(actualTool.getHome())) {
+ found = true;
+ break;
+ }
+ }
+ assertTrue("Was not expecting tool installation '" + actualTool.getName() + "'.", found);
+ }
+ }
}
View
49 src/test/resources/hudson/plugins/perforce/PerforceSCMTest/testP4ExeMigration/config.xml
@@ -0,0 +1,49 @@
+<?xml version='1.0' encoding='UTF-8'?>
+<hudson>
+ <disabledAdministrativeMonitors/>
+ <version>1.428</version>
+ <numExecutors>2</numExecutors>
+ <mode>NORMAL</mode>
+ <useSecurity>false</useSecurity>
+ <workspaceDir>${JENKINS_HOME}/workspace/${ITEM_FULLNAME}</workspaceDir>
+ <buildsDir>${ITEM_ROOTDIR}/builds</buildsDir>
+ <markupFormatter class="hudson.markup.RawHtmlMarkupFormatter">
+ <disableSyntaxHighlighting>false</disableSyntaxHighlighting>
+ </markupFormatter>
+ <jdks/>
+ <viewsTabBar class="hudson.views.DefaultViewsTabBar"/>
+ <myViewsTabBar class="hudson.views.DefaultMyViewsTabBar"/>
+ <clouds/>
+ <slaves/>
+ <quietPeriod>5</quietPeriod>
+ <scmCheckoutRetryCount>0</scmCheckoutRetryCount>
+ <views>
+ <hudson.model.AllView>
+ <owner class="hudson" reference="../../.."/>
+ <name>All</name>
+ <filterExecutors>false</filterExecutors>
+ <filterQueue>false</filterQueue>
+ <properties class="hudson.model.View$PropertyList"/>
+ </hudson.model.AllView>
+ </views>
+ <primaryView>All</primaryView>
+ <slaveAgentPort>0</slaveAgentPort>
+ <label></label>
+ <nodeProperties/>
+ <globalNodeProperties>
+ <hudson.slaves.EnvironmentVariablesNodeProperty>
+ <envVars serialization="custom">
+ <unserializable-parents/>
+ <tree-map>
+ <default>
+ <comparator class="hudson.util.CaseInsensitiveComparator"/>
+ </default>
+ <int>1</int>
+ <string>HOME</string>
+ <string>${JENKINS_HOME}</string>
+ </tree-map>
+ </envVars>
+ </hudson.slaves.EnvironmentVariablesNodeProperty>
+ </globalNodeProperties>
+ <noUsageStatistics>true</noUsageStatistics>
+</hudson>
View
50 ...ources/hudson/plugins/perforce/PerforceSCMTest/testP4ExeMigration/jobs/test_p4exe_migration_1/config.xml
@@ -0,0 +1,50 @@
+<?xml version='1.0' encoding='UTF-8'?>
+<project>
+ <actions/>
+ <description></description>
+ <keepDependencies>false</keepDependencies>
+ <properties/>
+ <scm class="hudson.plugins.perforce.PerforceSCM">
+ <p4User>user</p4User>
+ <p4Passwd>password</p4Passwd>
+ <p4Port>port</p4Port>
+ <p4Client>client</p4Client>
+ <projectOptions>noallwrite clobber nocompress unlocked nomodtime rmdir</projectOptions>
+ <p4Stream>//stream_depot/stream</p4Stream>
+ <p4Exe>c:\program files\perforce\p4.exe</p4Exe>
+ <p4SysDrive>C:</p4SysDrive>
+ <p4SysRoot>C:\windows</p4SysRoot>
+ <useClientSpec>false</useClientSpec>
+ <useStreamDepot>true</useStreamDepot>
+ <forceSync>false</forceSync>
+ <alwaysForceSync>false</alwaysForceSync>
+ <dontUpdateServer>false</dontUpdateServer>
+ <disableAutoSync>false</disableAutoSync>
+ <disableSyncOnly>false</disableSyncOnly>
+ <useOldClientName>false</useOldClientName>
+ <createWorkspace>true</createWorkspace>
+ <updateView>true</updateView>
+ <dontRenameClient>false</dontRenameClient>
+ <updateCounterValue>false</updateCounterValue>
+ <dontUpdateClient>false</dontUpdateClient>
+ <exposeP4Passwd>false</exposeP4Passwd>
+ <wipeBeforeBuild>false</wipeBeforeBuild>
+ <wipeRepoBeforeBuild>false</wipeRepoBeforeBuild>
+ <firstChange>0</firstChange>
+ <slaveClientNameFormat>${basename}-${hash}</slaveClientNameFormat>
+ <lineEndValue>local</lineEndValue>
+ <useViewMask>false</useViewMask>
+ <useViewMaskForPolling>false</useViewMaskForPolling>
+ <useViewMaskForSyncing>false</useViewMaskForSyncing>
+ <pollOnlyOnMaster>false</pollOnlyOnMaster>
+ </scm>
+ <canRoam>true</canRoam>
+ <disabled>false</disabled>
+ <blockBuildWhenDownstreamBuilding>false</blockBuildWhenDownstreamBuilding>
+ <blockBuildWhenUpstreamBuilding>false</blockBuildWhenUpstreamBuilding>
+ <triggers class="vector"/>
+ <concurrentBuild>false</concurrentBuild>
+ <builders/>
+ <publishers/>
+ <buildWrappers/>
+</project>
View
1  ...s/hudson/plugins/perforce/PerforceSCMTest/testP4ExeMigration/jobs/test_p4exe_migration_1/nextBuildNumber
@@ -0,0 +1 @@
+2
View
50 ...ources/hudson/plugins/perforce/PerforceSCMTest/testP4ExeMigration/jobs/test_p4exe_migration_2/config.xml
@@ -0,0 +1,50 @@
+<?xml version='1.0' encoding='UTF-8'?>
+<project>
+ <actions/>
+ <description></description>
+ <keepDependencies>false</keepDependencies>
+ <properties/>
+ <scm class="hudson.plugins.perforce.PerforceSCM">
+ <p4User>user</p4User>
+ <p4Passwd>password</p4Passwd>
+ <p4Port>port</p4Port>
+ <p4Client>client</p4Client>
+ <projectOptions>noallwrite clobber nocompress unlocked nomodtime rmdir</projectOptions>
+ <p4Stream>//stream_depot/stream</p4Stream>
+ <p4Exe>c:\program files\perforce\p4.exe</p4Exe>
+ <p4SysDrive>C:</p4SysDrive>
+ <p4SysRoot>C:\windows</p4SysRoot>
+ <useClientSpec>false</useClientSpec>
+ <useStreamDepot>true</useStreamDepot>
+ <forceSync>false</forceSync>
+ <alwaysForceSync>false</alwaysForceSync>
+ <dontUpdateServer>false</dontUpdateServer>
+ <disableAutoSync>false</disableAutoSync>
+ <disableSyncOnly>false</disableSyncOnly>
+ <useOldClientName>false</useOldClientName>
+ <createWorkspace>true</createWorkspace>
+ <updateView>true</updateView>
+ <dontRenameClient>false</dontRenameClient>
+ <updateCounterValue>false</updateCounterValue>
+ <dontUpdateClient>false</dontUpdateClient>
+ <exposeP4Passwd>false</exposeP4Passwd>
+ <wipeBeforeBuild>false</wipeBeforeBuild>
+ <wipeRepoBeforeBuild>false</wipeRepoBeforeBuild>
+ <firstChange>0</firstChange>
+ <slaveClientNameFormat>${basename}-${hash}</slaveClientNameFormat>
+ <lineEndValue>local</lineEndValue>
+ <useViewMask>false</useViewMask>
+ <useViewMaskForPolling>false</useViewMaskForPolling>
+ <useViewMaskForSyncing>false</useViewMaskForSyncing>
+ <pollOnlyOnMaster>false</pollOnlyOnMaster>
+ </scm>
+ <canRoam>true</canRoam>
+ <disabled>false</disabled>
+ <blockBuildWhenDownstreamBuilding>false</blockBuildWhenDownstreamBuilding>
+ <blockBuildWhenUpstreamBuilding>false</blockBuildWhenUpstreamBuilding>
+ <triggers class="vector"/>
+ <concurrentBuild>false</concurrentBuild>
+ <builders/>
+ <publishers/>
+ <buildWrappers/>
+</project>
View
1  ...s/hudson/plugins/perforce/PerforceSCMTest/testP4ExeMigration/jobs/test_p4exe_migration_2/nextBuildNumber
@@ -0,0 +1 @@
+2
View
50 ...ources/hudson/plugins/perforce/PerforceSCMTest/testP4ExeMigration/jobs/test_p4exe_migration_3/config.xml
@@ -0,0 +1,50 @@
+<?xml version='1.0' encoding='UTF-8'?>
+<project>
+ <actions/>
+ <description></description>
+ <keepDependencies>false</keepDependencies>
+ <properties/>
+ <scm class="hudson.plugins.perforce.PerforceSCM">
+ <p4User>user</p4User>
+ <p4Passwd>password</p4Passwd>
+ <p4Port>port</p4Port>
+ <p4Client>client</p4Client>
+ <projectOptions>noallwrite clobber nocompress unlocked nomodtime rmdir</projectOptions>
+ <p4Stream>//stream_depot/stream</p4Stream>
+ <p4Exe>p4.exe</p4Exe>
+ <p4SysDrive>C:</p4SysDrive>
+ <p4SysRoot>C:\windows</p4SysRoot>
+ <useClientSpec>false</useClientSpec>
+ <useStreamDepot>true</useStreamDepot>
+ <forceSync>false</forceSync>
+ <alwaysForceSync>false</alwaysForceSync>
+ <dontUpdateServer>false</dontUpdateServer>
+ <disableAutoSync>false</disableAutoSync>
+ <disableSyncOnly>false</disableSyncOnly>
+ <useOldClientName>false</useOldClientName>
+ <createWorkspace>true</createWorkspace>
+ <updateView>true</updateView>
+ <dontRenameClient>false</dontRenameClient>
+ <updateCounterValue>false</updateCounterValue>
+ <dontUpdateClient>false</dontUpdateClient>
+ <exposeP4Passwd>false</exposeP4Passwd>
+ <wipeBeforeBuild>false</wipeBeforeBuild>
+ <wipeRepoBeforeBuild>false</wipeRepoBeforeBuild>
+ <firstChange>0</firstChange>
+ <slaveClientNameFormat>${basename}-${hash}</slaveClientNameFormat>
+ <lineEndValue>local</lineEndValue>
+ <useViewMask>false</useViewMask>
+ <useViewMaskForPolling>false</useViewMaskForPolling>
+ <useViewMaskForSyncing>false</useViewMaskForSyncing>
+ <pollOnlyOnMaster>false</pollOnlyOnMaster>
+ </scm>
+ <canRoam>true</canRoam>
+ <disabled>false</disabled>
+ <blockBuildWhenDownstreamBuilding>false</blockBuildWhenDownstreamBuilding>
+ <blockBuildWhenUpstreamBuilding>false</blockBuildWhenUpstreamBuilding>
+ <triggers class="vector"/>
+ <concurrentBuild>false</concurrentBuild>
+ <builders/>
+ <publishers/>
+ <buildWrappers/>
+</project>
View
1  ...s/hudson/plugins/perforce/PerforceSCMTest/testP4ExeMigration/jobs/test_p4exe_migration_3/nextBuildNumber
@@ -0,0 +1 @@
+2

No commit comments for this range

Something went wrong with that request. Please try again.