Skip to content

Commit

Permalink
Merge pull request #25 from vtintillier/upstream-revision-rc1
Browse files Browse the repository at this point in the history
Add ability to use same change set as an upstream job
  • Loading branch information
rpetti committed Jun 18, 2012
2 parents 1869641 + 64a94ff commit c014778
Show file tree
Hide file tree
Showing 4 changed files with 161 additions and 11 deletions.
101 changes: 96 additions & 5 deletions src/main/java/hudson/plugins/perforce/PerforceSCM.java
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@
import hudson.matrix.MatrixBuild;
import hudson.matrix.MatrixRun;
import hudson.model.*;
import hudson.model.listeners.ItemListener;
import hudson.remoting.VirtualChannel;
import hudson.scm.ChangeLogParser;
import hudson.scm.PollingResult;
Expand All @@ -29,6 +30,8 @@
import hudson.scm.SCMRevisionState;
import hudson.slaves.EnvironmentVariablesNodeProperty;
import hudson.slaves.NodeProperty;
import hudson.tasks.BuildTrigger;
import hudson.tasks.Messages;
import hudson.util.FormValidation;
import hudson.util.LogTaskListener;

Expand Down Expand Up @@ -75,6 +78,7 @@ public class PerforceSCM extends SCM {
String projectOptions;
String p4Label;
String p4Counter;
String p4UpstreamProject;
String p4Stream;
String clientOwner;

Expand Down Expand Up @@ -276,6 +280,7 @@ public PerforceSCM(
String p4SysDrive,
String p4Label,
String p4Counter,
String p4UpstreamProject,
String lineEndValue,
String p4Charset,
String p4CommandCharset,
Expand Down Expand Up @@ -323,6 +328,8 @@ public PerforceSCM(
this.p4Counter = Util.fixEmptyAndTrim(p4Counter);
this.updateCounterValue = updateCounterValue;

this.p4UpstreamProject = Util.fixEmptyAndTrim(p4UpstreamProject);

this.projectPath = Util.fixEmptyAndTrim(projectPath);

this.clientOwner = Util.fixEmptyAndTrim(clientOwner);
Expand Down Expand Up @@ -844,6 +851,24 @@ public boolean checkout(AbstractBuild build, Launcher launcher,
if (p4Label != null && !p4Label.trim().isEmpty()) {
newestChange = depot.getChanges().getHighestLabelChangeNumber(p4workspace, p4Label.trim(), p4WorkspacePath);
} else {
if (p4UpstreamProject != null && p4UpstreamProject.length() > 0) {
log.println("Using last successful or unstable build of upstream project " + p4UpstreamProject);
Job job = Hudson.getInstance().getItemByFullName(p4UpstreamProject, Job.class);
if (job == null) {
throw new AbortException(
"Configured upstream job does not exist anymore: " + p4UpstreamProject + ". Please update your job configuration.");
}
Run upStreamRun = job.getLastSuccessfulBuild();
int lastUpStreamChange = getLastChangeNoFirstChange(upStreamRun);
if (lastUpStreamChange > 0) {
log.println("Using P4 revision " + lastUpStreamChange + " from upstream project " + p4UpstreamProject);
newestChange = lastUpStreamChange;
} else {
log.println("No P4 revision found in upstream project " + p4UpstreamProject);
throw new AbortException(
"Configured upstream job has not been run yet: " + p4UpstreamProject + ". Please run it once befor launching a new build.");
}
} else
if (p4Counter != null && !updateCounterValue) {
//use a counter
String counterName;
Expand Down Expand Up @@ -1346,9 +1371,14 @@ private boolean wouldSyncChangeWorkspace(AbstractProject project, Depot depot,
}

public int getLastChange(Run build) {
// If we are starting a new hudson project on existing work and want to skip the prior history...
if (firstChange > 0)
return firstChange;
// If we are starting a new hudson project on existing work and want to skip the prior history...
if (firstChange > 0)
return firstChange;

return getLastChangeNoFirstChange(build);
}

private static int getLastChangeNoFirstChange(Run build) {

// If we can't find a PerforceTagAction, we will default to 0.

Expand All @@ -1360,7 +1390,7 @@ public int getLastChange(Run build) {
return action.getChangeNumber();
}

private PerforceTagAction getMostRecentTagAction(Run build) {
private static PerforceTagAction getMostRecentTagAction(Run build) {
if (build == null)
return null;

Expand Down Expand Up @@ -1820,7 +1850,7 @@ public FormValidation doValidateP4Label(StaplerRequest req, @QueryParameter Stri
/**
* Performs syntactical and permissions check on the P4Counter
*/
public FormValidation doValidateP4Counter(StaplerRequest req, @QueryParameter String counter) throws IOException, ServletException {
public FormValidation doValidateP4Counter(StaplerRequest req, @QueryParameter String counter) {
counter= Util.fixEmptyAndTrim(counter);
if (counter == null)
return FormValidation.ok();
Expand All @@ -1839,6 +1869,30 @@ public FormValidation doValidateP4Counter(StaplerRequest req, @QueryParameter St
}
return FormValidation.ok();
}

/**
* Checks to see if the specified project exists and has p4 info.
*/
public FormValidation doValidateP4UpstreamProject(StaplerRequest req, @QueryParameter String project) throws IOException, ServletException {
project = Util.fixEmptyAndTrim(project);
if (project == null) {
// well, it is not really OK, but it means it will not be used, so no error
return FormValidation.ok();
}

Job job = Hudson.getInstance().getItemByFullName(project, Job.class);
if (job == null) {
return FormValidation.error(Messages.BuildTrigger_NoSuchProject(project, AbstractProject.findNearest(project).getName()));
}

Run upStreamRun = job.getLastSuccessfulBuild();
int lastUpStreamChange = getLastChangeNoFirstChange(upStreamRun);
if (lastUpStreamChange < 1) {
FormValidation.warning("No Perforce change found in this project");
}

return FormValidation.ok();
}

/**
* Checks to see if the specified ClientSpec is valid.
Expand Down Expand Up @@ -2069,6 +2123,29 @@ public String getAppName() {
return Hudson.getInstance().getDisplayName();
}

@Extension
public static class ItemListenerImpl extends ItemListener {
@Override
public void onRenamed(Item item, String oldName, String newName) {
for( Project<?,?> p : Hudson.getInstance().getProjects() ) {
SCM scm = p.getScm();
if (scm instanceof PerforceSCM) {
PerforceSCM p4scm = (PerforceSCM) scm;
if (oldName.equals(p4scm.p4UpstreamProject)) {
p4scm.p4UpstreamProject = newName;
try {
p.save();
} catch (IOException e) {
LOGGER.log(Level.WARNING,
"Failed to persist project setting during rename from "
+ oldName + " to " + newName, e);
}
}
}
}
}
}

}

/* Regular expressions for parsing view mappings.
Expand Down Expand Up @@ -2470,6 +2547,20 @@ public String getP4Counter() {
public void setP4Counter(String counter) {
p4Counter = counter;
}

/**
* @return the p4UpstreamProject
*/
public String getP4UpstreamProject() {
return p4UpstreamProject;
}

/**
* @param label the p4Label to set
*/
public void setP4UpstreamProject(String project) {
p4UpstreamProject = project;
}

/**
* @return True if the plugin should update the counter to the last change
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -161,6 +161,13 @@
<f:entry title="Update counter to most recent changeset" help="/plugin/perforce/help/updateCounterValue.html">
<f:checkbox field="updateCounterValue" default="false" />
</f:entry>

<j:invokeStatic var="hudsonInstance" className="hudson.model.Hudson" method="getInstance"/>
<j:invoke var="allProjects" on="${hudsonInstance}" method="getJobNames"/>
<f:entry title="Use Upstream Project revision" help="/plugin/perforce/help/p4UpstreamProject.html">
<f:editableComboBox id="p4UpstreamProject" field="p4UpstreamProject" items="${allProjects}"
checkUrl="'${rootURL}/scm/PerforceSCM/validateP4UpstreamProject?project='+escape(document.forms[1].p4UpstreamProject.value)"/>
</f:entry>

<f:entry title="Don't update client workspace" help="/plugin/perforce/help/dontUpdateClient.html">
<f:checkbox field="dontUpdateClient" default="false" />
Expand Down
13 changes: 13 additions & 0 deletions src/main/webapp/help/p4UpstreamProject.html
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
<div>
<p>
Sync to the changeset of another project.
</p>
<p>
If a project name is entered here, the plugin will sync to the changeset
of this other project last succesful build instead of the most recent
changeset.
This feature can be used for downstream jobs to sync to the same revision
as the upstream job, for example when using copy artifact plugin to copy
this project last succesful artifacts.
</p>
</div>
51 changes: 45 additions & 6 deletions src/test/java/hudson/plugins/perforce/PerforceSCMTest.java
Original file line number Diff line number Diff line change
Expand Up @@ -4,8 +4,10 @@
import hudson.model.Hudson;
import hudson.plugins.perforce.PerforceToolInstallation.DescriptorImpl;
import hudson.plugins.perforce.browsers.P4Web;
import hudson.scm.SCM;
import hudson.tools.ToolProperty;

import java.io.IOException;
import java.net.URL;
import java.util.Arrays;
import java.util.Collections;
Expand All @@ -26,7 +28,7 @@ public void testConfigRoundtrip() throws Exception {
P4Web browser = new P4Web(new URL("http://localhost/"));
PerforceSCM scm = new PerforceSCM(
"user", "pass", "client", "port", "", "exe", "sysRoot",
"sysDrive", "label", "counter", "shared", "charset", "charset2", "user", false, true, true, true, true, true, false,
"sysDrive", "label", "counter", "upstreamProject", "shared", "charset", "charset2", "user", false, true, true, true, true, true, false,
false, true, false, false, false, "${basename}", 0, -1, browser, "exclude_user", "exclude_file", true);
scm.setProjectPath("path");
project.setScm(scm);
Expand All @@ -47,7 +49,7 @@ public void testConfigRoundtripWithStream() throws Exception {
P4Web browser = new P4Web(new URL("http://localhost/"));
PerforceSCM scm = new PerforceSCM(
"user", "pass", "client", "port", "", "exe", "sysRoot",
"sysDrive", "label", "counter", "shared", "charset", "charset2", "user", false, true, true, true, true, true, false,
"sysDrive", "label", "counter", "upstreamProject", "shared", "charset", "charset2", "user", false, true, true, true, true, true, false,
false, true, false, false, false, "${basename}", 0, -1, browser, "exclude_user", "exclude_file", true);
scm.setP4Stream("stream");
scm.setUseStreamDepot(true);
Expand All @@ -74,7 +76,7 @@ public void testConfigPasswordEnctyptionAndDecription() throws Exception {
String password = "pass";
PerforceSCM scm = new PerforceSCM(
"user", password, "client", "port", "", "test_installation", "sysRoot",
"sysDrive", "label", "counter", "shared", "charset", "charset2", "user", false, true, true, true, true, true, false,
"sysDrive", "label", "counter", "upstreamProject", "shared", "charset", "charset2", "user", false, true, true, true, true, true, false,
false, true, false, false, false, "${basename}", 0, -1, browser, "exclude_user", "exclude_file", true);
scm.setProjectPath("path");
project.setScm(scm);
Expand Down Expand Up @@ -103,7 +105,7 @@ public void testDepotContainsUnencryptedPassword() throws Exception {
String password = "pass";
PerforceSCM scm = new PerforceSCM(
"user", password, "client", "port", "", "test_installation", "sysRoot",
"sysDrive", "label", "counter", "shared", "charset", "charset2", "user", false, true, true, true, true, true, false,
"sysDrive", "label", "counter", "upstreamProject", "shared", "charset", "charset2", "user", false, true, true, true, true, true, false,
false, true, false, false, false, "${basename}", 0, -1, browser, "exclude_user", "exclude_file", true);
scm.setProjectPath("path");
project.setScm(scm);
Expand All @@ -121,7 +123,7 @@ public void testConfigSaveReloadAndSaveDoesNotDoubleEncryptThePassword() throws
String password = "pass";
PerforceSCM scm = new PerforceSCM(
"user", password, "client", "port", "", "test_installation", "sysRoot",
"sysDrive", "label", "counter", "shared", "charset", "charset2", "user", false, true, true, true, true, true, false,
"sysDrive", "label", "counter", "upstreamProject", "shared", "charset", "charset2", "user", false, true, true, true, true, true, false,
false, true, false, false, false, "${basename}", 0, -1, browser, "exclude_user", "exclude_file", true);
scm.setProjectPath("path");
project.setScm(scm);
Expand Down Expand Up @@ -284,7 +286,7 @@ public void testDepotContainsUnencryptedPasswordWithgetProperty() throws Excepti
String password = "pass";
PerforceSCM scm = new PerforceSCM(
"user", password, "client", "port", "", "test_installation", "sysRoot",
"sysDrive", "label", "counter", "shared", "charset", "charset2", "user", false, true, true, true, true, true, false,
"sysDrive", "label", "counter", "upstreamProject", "shared", "charset", "charset2", "user", false, true, true, true, true, true, false,
false, false, true, false, false, "${basename}", 0, -1, browser, "exclude_user", "exclude_file", true);
scm.setP4Stream("stream");
project.setScm(scm);
Expand Down Expand Up @@ -312,4 +314,41 @@ static void assertEquals(PerforceToolInstallation[] expected, PerforceToolInstal
}
}

public void testP4UpstreamProjectRenaming() throws Exception {
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();

FreeStyleProject upstreamProject = createFreeStyleProject();
PerforceSCM upstreamScm = new PerforceSCM(
"user", "pass", "client", "port", "", "test_installation", "sysRoot",
"sysDrive", null, null, null, "shared", "charset", "charset2", "user", false, true, true, true, true, true, false,
false, true, false, false, false, "${basename}", 0, -1, browser, "exclude_user", "exclude_file", true);
upstreamScm.setProjectPath("path");
upstreamProject.setScm(upstreamScm);

FreeStyleProject downstreamProject = createFreeStyleProject();
String oldName = upstreamProject.getName();
PerforceSCM downstreamScm = new PerforceSCM(
"user", "pass", "client", "port", "", "test_installation", "sysRoot",
"sysDrive", null, null, oldName, "shared", "charset", "charset2", "user", false, true, true, true, true, true, false,
false, true, false, false, false, "${basename}", 0, -1, browser, "exclude_user", "exclude_file", true);
downstreamScm.setProjectPath("path");
downstreamProject.setScm(downstreamScm);

// config roundtrip
submit(new WebClient().getPage(upstreamProject,"configure").getFormByName("config"));
submit(new WebClient().getPage(downstreamProject,"configure").getFormByName("config"));

PerforceSCM scm = (PerforceSCM) downstreamProject.getScm();
assertEquals(scm.p4UpstreamProject, oldName);

String newName = "newName" + oldName;
upstreamProject.renameTo(newName);

scm = (PerforceSCM) downstreamProject.getScm();
assertEquals(scm.p4UpstreamProject, newName);
}
}

0 comments on commit c014778

Please sign in to comment.