package org.jenkinsci.plugins.p4_client; import hudson.DescriptorExtensionList; import hudson.Extension; import hudson.FilePath; import hudson.Launcher; import hudson.model.BuildListener; import hudson.model.TaskListener; import hudson.model.AbstractBuild; import hudson.model.AbstractProject; import hudson.model.Descriptor; import hudson.scm.ChangeLogParser; import hudson.scm.PollingResult; import hudson.scm.SCMDescriptor; import hudson.scm.SCMRevisionState; import hudson.scm.SCM; import hudson.util.FormValidation; import hudson.util.XStream2; import hudson.util.ListBoxModel; import java.io.File; import java.io.IOException; import javax.servlet.ServletException; import jenkins.model.Jenkins; import net.sf.json.JSONObject; import org.jenkinsci.plugins.p4_client.connection.ConnectionData; import org.jenkinsci.plugins.p4_client.connection.ConnectionPool; import org.jenkinsci.plugins.p4_client.connection.ConnectionProvider; import org.kohsuke.stapler.DataBoundConstructor; import org.kohsuke.stapler.QueryParameter; import org.kohsuke.stapler.StaplerRequest; import org.kohsuke.stapler.StaplerResponse; import org.slf4j.Logger; import org.slf4j.LoggerFactory; public class PerforceScm extends SCM { private ConnectionProvider cp; private Logger logger = LoggerFactory.getLogger(PerforceScm.class); /** * Create a constructor that takes non-transient fields, and add the * annotation @DataBoundConstructor to it. Using the annotation helps the * Stapler class to find which constructor that should be used when * automatically copying values from a web form to a class. * * @param server * @param project * @param cleanCopy * @param username * @param password * @param domain * @param workspaceName */ @DataBoundConstructor public PerforceScm(ConnectionProvider cp) { this.cp = cp; } /** * Calculate the state of the workspace of the given build. The returned * object is then fed into compareRemoteRevisionWith as the baseline * SCMRevisionState to determine if the build is necessary, and is added to * the build as an Action for later retrieval. */ @Override public SCMRevisionState calcRevisionsFromBuild(AbstractBuild<?, ?> build, Launcher launcher, TaskListener listener) throws IOException, InterruptedException { // TODO Auto-generated method stub return null; } /** * This method does the actual polling and returns a PollingResult. The * change attribute of the PollingResult the significance of the changes * detected by this poll. */ @Override protected PollingResult compareRemoteRevisionWith( AbstractProject<?, ?> project, Launcher launcher, FilePath workspace, TaskListener listener, SCMRevisionState baseline) throws IOException, InterruptedException { // TODO Auto-generated method stub return null; } /** * The checkout method is expected to check out modified files into the * project workspace. In Perforce terms a 'p4 sync' on the project's * workspace. Authorisation */ @Override public boolean checkout(AbstractBuild<?, ?> build, Launcher launcher, FilePath workspace, BuildListener listener, File changelogFile) throws IOException, InterruptedException { // TODO Auto-generated method stub return false; } /** * The checkout method should, besides checking out the modified files, * write a changelog.xml file that contains the changes for a certain build. * The changelog.xml file is specific for each SCM implementation, and the * createChangeLogParser returns a parser that can parse the file and return * a ChangeLogSet. */ @Override public ChangeLogParser createChangeLogParser() { // TODO Auto-generated method stub return null; } /** * Returns the ScmDescriptor<?> for the SCM object. The ScmDescriptor is * used to create new instances of the SCM. */ @Override public SCMDescriptor<PerforceScm> getDescriptor() { return (DescriptorImpl) super.getDescriptor(); } public static final DescriptorImpl DESCRIPTOR = new DescriptorImpl(); /** * The relationship of Descriptor and SCM (the describable) is akin to class * and object. What this means is that the descriptor is used to create * instances of the describable. Usually the Descriptor is an internal class * in the SCM class named DescriptorImpl. The Descriptor should also contain * the global configuration options as fields, just like the SCM class * contains the configurations options for a job. * * @author pallen * */ @Extension public static class DescriptorImpl extends SCMDescriptor<PerforceScm> { private static Logger logger = LoggerFactory .getLogger(DescriptorImpl.class); private String connection; private ConnectionPool connectionPool = new ConnectionPool(); private ConnectionProvider connProvider; /** * public no-argument constructor */ public DescriptorImpl() { super(PerforceScm.class, null); logger.info("Creating dummy connections..."); ConnectionData a = new ConnectionData("myMac"); a.setPort("localhost:1666"); a.setUser("pallen"); connectionPool.add(a); ConnectionData b = new ConnectionData("p4prod"); b.setPort("p4prod.perforce.com"); b.setUser("pallen"); connectionPool.add(b); ConnectionData c = new ConnectionData("foo"); c.setPort("foo:1666"); c.setUser("foobar"); connectionPool.add(c); load(); } @Override public SCM newInstance(StaplerRequest req, JSONObject formData) throws FormException { PerforceScm scm = (PerforceScm) super.newInstance(req, formData); return scm; } /** * Returns the name of the SCM, this is the name that will show up next * to CVS and Subversion when configuring a job. */ @Override public String getDisplayName() { return "Perforce Software"; } /** * The configure method is invoked when the global configuration page is * submitted. In the method the data in the web form should be copied to * the Descriptor's fields. To persist the fields to the global * configuration XML file, the save() method must be called. Data is * defined in the global.jelly page. * */ @Override public boolean configure(StaplerRequest req, JSONObject json) throws FormException { logger.info("DescriptorImpl save()..."); connection = json.getString("connection"); // Read global configs of P4GlobalCredentials try { JSONObject formData = req.getSubmittedForm(); if (formData.has("addPasswordConnection")) { ConnectionData c = new ConnectionData("new"); c.setPort(formData.getString("port")); c.setUser(formData.getString("user")); connectionPool.add(c); } } catch (ServletException ex) { throw new FormException("Cannot get the form data", ex, "globalCredentials"); } // for (ConnectionDescriptor d : ConnectionProvider.all()) { // String name = d.getJsonSafeClassName(); // logger.info("... calling descriptor: " + name); // JSONObject js = formData.has(name) ? formData // .getJSONObject(name) : new JSONObject(); // d.configure(req, js); // } save(); return true; } /** * Global Jelly method. * * @return A list of connection pool items to populate the jelly Select * list. */ public ListBoxModel doFillConnectionItems() { ListBoxModel list = new ListBoxModel(); // Add hint when no connection is defined if (connection == null) list.add("Select Perforce connection...", ""); for (String name : connectionPool.getNames()) { if (connection != null && name.equals(connection)) { list.add(new ListBoxModel.Option(name, name, true)); } else { list.add(name); } } return list; } /** * Global Jelly method. * * @return A list of connection types for creating new connections. */ public DescriptorExtensionList<ConnectionProvider, Descriptor<ConnectionProvider>> getConnDescriptors() { return Jenkins .getInstance() .<ConnectionProvider, Descriptor<ConnectionProvider>> getDescriptorList( ConnectionProvider.class); } public void doAddPasswordConnection(StaplerRequest req, StaplerResponse rsp) throws IOException, ServletException { logger.info("SCM doDoApprove"); ConnectionProvider c = req.bindJSON(ConnectionProvider.class, req .getSubmittedForm().getJSONObject("connProvider")); rsp.setContentType("text/plain"); new XStream2().toXML(c, rsp.getWriter()); } public FormValidation doTestConnection( @QueryParameter("connProvider") final ConnectionProvider c) throws IOException, ServletException { logger.info("SCM doTestConnection"); return FormValidation.ok("Success"); } } /** * This methods determines if the SCM plugin can be used for polling */ @Override public boolean supportsPolling() { return true; } /** * This method should return true if the SCM requires a workspace for * polling. Perforce however can report submitted, pending and shelved * changes without needing a workspace */ @Override public boolean requiresWorkspaceForPolling() { return true; } }
# | Change | User | Description | Committed | |
---|---|---|---|---|---|
#33 | 9672 | Paul Allen | Refactor name from 'p4_client' to 'p4'. | ||
#32 | 9495 | Paul Allen |
Fix Polling issue; using the wrong client. Removed static classes and internal referenced to PerforceScm attributes, to avoid threading issues. |
||
#31 | 9472 | Paul Allen |
Added support to pin build at a label in the populate configuration. - includes help and updates to tests. |
||
#30 | 9430 | Paul Allen |
Polling SCM: skip filter check if no filters - added more logging for Polling errors. |
||
#29 | 9429 | Paul Allen |
Fix SCM Polling bug. Client workspace was not set (unless by an earlier build). - Move listChanges method to ClientHelper. |
||
#28 | 9115 | Paul Allen |
Initial implementation of workspace Cleanup and Sync options. - Includes 3 modes: Automatic Clean/Sync, Force Clean/Sync, Sync Only Automatic Clean/Sync Uses reconcile to clean up workspace and sync changes. Force Clean/Sync Force sync of all files (does not remove files yet...) Sync Only Normal sync with no cleanup TODO: - remove of files in Force Clean/Sync mode - Inline help - Update docs - Add unit/functional tests |
||
#27 | 9091 | Paul Allen |
Added Changelist build filtering for SCM polling: - Configuration uses 'repeatableHeteroProperty' - Filter on Perforce username - Filter on Perforce Depot path (no wildcard support) |
||
#26 | 9069 | Paul Allen |
Adding initial support for tagging Jenkins builds as Perforce Automatic Labels. Only implements TagAction (manual labels); TagNotifier and test cases TODO. |
||
#25 | 9055 | Paul Allen |
Label support. Build at a label using the pram 'label'. This includes adding the label to the ChangeEntry, building the change reports and Browser links to Swarm. (TPI-102) |
||
#24 | 9038 | Paul Allen |
Improved error messages for Form Validate field checks. Uses Perforce Server messages (TPI-80) |
||
#23 | 8969 | Paul Allen |
Adds all contributing change-lists for the build to the change log (using p4 cstat). - Includes exception logging for server connection to the Jenkins console. |
||
#22 | 8940 | Paul Allen |
Major refactor for the ConnectionHelper class to simplify serialisation. Fixed remote Jenkins JNLP slave connection issue. ClientHelper now extends ConnectionHelper and takes on all methods that require a client workspace. P4StandardCredentials is sent to the remote node instead of Credentials ID due to an issue accessing the Credentials store over a remote connection. For simplicity Client ID (workspace name) is serialised instead of the Workspace object. |
||
#21 | 8929 | Paul Allen |
Clean up doCheck Warnings on configuration page (TPI-80). - Added check exceptions to log as warnings. |
||
#20 | 8915 | Paul Allen |
Support for ChangeLog and RepoBrowser. - Added RepoBrowser for Swarm (porting the others should be easy) - ChangeLog XML file now only stores the changelist number all other information is fetched from Perforce |
||
#19 | 8771 | Paul Allen |
Perforce Server 12.1 min check for: Build configuration and password/ticket credentials. Includes: - Added logging for Perforce connections (fine) and set connection pool to 2. - Add 'none' to empty charset list (connection bug?) - Supress P4Java errors for syncing ubinary, xtext, unicode |
||
#18 | 8770 | Paul Allen |
Implemented SCM hook for when Jenkins deletes a workspace. The PerforceScm plugin deletes the workspace, but leaves Jenkins to clean up the local files and directories. (includes dummy 'p4 cstat' code for change reporting) |
||
#17 | 8762 | Paul Allen |
Console Ouptut logging for SCM build steps. - Removed SLF4J and used old style logger (matching Jenkins) - Set Client Host filed to null, Jenkins sometimes gives an IP address. - Test p4java setps in SCM tasks for success(true/false) |
||
#16 | 8744 | Paul Allen |
Support basic SCM Polling. When Jenkins has "Poll SCM" checked the Perforce SCM provider just runs a 'p4 sync -n' on the Workspace. Simple and Fast. |
||
#15 | 8738 | Paul Allen |
Workspace Name Formatter. For Template and Stream workspaces it allows the substitution of the following tags: ${node} The name given to the slave Jenkins node. ${hostname} The hostname for the slave Jenkins node. ${project} The name of the Jenkins build Job. ${hash} Unique hash code of the Jenkins node. |
||
#14 | 8737 | Paul Allen |
Added basic Help for SCM Configuration page. Tidy up descriptions and fix (null:null) in Credential summary. |
||
#13 | 8694 | Paul Allen | Added support for unshelve and revert -w behaviour for builds. | ||
#12 | 8688 | Paul Allen | (Work in progress) Able to call build from review Action and pass URL params. | ||
#11 | 8664 | Paul Allen | Simplified connection to Perforce to get around the SCM initilisation (or lack of). | ||
#10 | 8663 | Paul Allen | Rollout of charset for all Workspace modes. | ||
#9 | 8661 | Paul Allen | Workspace auto fill | ||
#8 | 8641 | Paul Allen | Added workspace helper (setClient) and template/stream types. | ||
#7 | 8640 | Paul Allen |
Added Workspace and Singleton descriptor. Removed old connection code. |
||
#6 | 8639 | Paul Allen |
Added hint URL to Credentials page when no Credentials are defined. Minor refactor and UX changes. |
||
#5 | 8629 | Paul Allen |
Added p4java with connection/authorisation helper classes. Included SSL support and detection of Unicode servers. |
||
#4 | 8613 | Paul Allen | Tidy up unused Credentials data and for debug added getId() to SelectList title. | ||
#3 | 8612 | Paul Allen | Job can now select and save/load Credential choice (some cleanup TODO) | ||
#2 | 8611 | Paul Allen | Basic implementation of Credentials Store | ||
#1 | 8598 | Paul Allen | Experimentation with data binding for Jelly files and ExtensionPoint/Descriptor |