Skip to content

Commit 4c8e35c

Browse files
committed
Merge pull request #33 from jenkinsci/multiple-scm-instatination-fix
[IN_PROGRESS][JENKINS-18583] - Fixed PerforceSCM instatination forn Multiple SCMs
2 parents 02d2fcf + 92e8c1d commit 4c8e35c

File tree

7 files changed

+343
-69
lines changed

7 files changed

+343
-69
lines changed

src/main/java/hudson/plugins/perforce/PerforceSCM.java

Lines changed: 59 additions & 43 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
package hudson.plugins.perforce;
22

3+
import hudson.plugins.perforce.config.DepotType;
34
import com.tek42.perforce.Depot;
45
import com.tek42.perforce.PerforceException;
56
import com.tek42.perforce.model.Changelist;
@@ -22,6 +23,9 @@
2223
import hudson.matrix.MatrixRun;
2324
import hudson.model.*;
2425
import hudson.model.listeners.ItemListener;
26+
import hudson.plugins.perforce.config.CleanTypeConfig;
27+
import hudson.plugins.perforce.config.MaskViewConfig;
28+
import hudson.plugins.perforce.config.WorkspaceCleanupConfig;
2529
import hudson.plugins.perforce.utils.MacroStringHelper;
2630
import hudson.plugins.perforce.utils.ParameterSubstitutionException;
2731
import hudson.remoting.VirtualChannel;
@@ -54,6 +58,7 @@
5458
import java.io.StringWriter;
5559
import java.net.InetAddress;
5660
import java.util.*;
61+
import java.util.concurrent.atomic.AtomicLong;
5762
import java.util.logging.Level;
5863
import java.util.logging.Logger;
5964
import java.util.regex.Matcher;
@@ -278,7 +283,13 @@ public class PerforceSCM extends SCM {
278283
private String p4Charset = null;
279284
private String p4CommandCharset = null;
280285

281-
// Plugin constructor, (only?) used when a job configuration is saved
286+
/**
287+
* SCM constructor, (only?) used when a job configuration is saved.
288+
* This constructor uses data classes from {@link hudson.plugins.perforce.config}
289+
* to allow proper handling of hierarchical data in Stapler. In the current
290+
* state, these classes are not being used outside this constructor.
291+
*/
292+
// TODO: move data to configuration classes during the refactoring
282293
@DataBoundConstructor
283294
public PerforceSCM(
284295
String p4User,
@@ -314,7 +325,11 @@ public PerforceSCM(
314325
PerforceRepositoryBrowser browser,
315326
String excludedUsers,
316327
String excludedFiles,
317-
boolean excludedFilesCaseSensitivity) {
328+
boolean excludedFilesCaseSensitivity,
329+
DepotType depotType,
330+
WorkspaceCleanupConfig cleanWorkspace,
331+
MaskViewConfig useViewMask
332+
) {
318333

319334
this.configVersion = 1L;
320335

@@ -341,8 +356,39 @@ public PerforceSCM(
341356

342357
this.p4UpstreamProject = Util.fixEmptyAndTrim(p4UpstreamProject);
343358

344-
this.projectPath = Util.fixEmptyAndTrim(projectPath);
345-
359+
//TODO: move optional entries to external classes
360+
// Get data from the depot type
361+
if (depotType != null) {
362+
this.p4Stream = depotType.getP4Stream();
363+
this.clientSpec = depotType.getClientSpec();
364+
this.projectPath = Util.fixEmptyAndTrim(depotType.getProjectPath());
365+
this.useStreamDepot = depotType.useP4Stream();
366+
this.useClientSpec = depotType.useClientSpec();
367+
this.useViewMask = depotType.useProjectPath();
368+
}
369+
370+
// Get data from workspace cleanup settings
371+
if (cleanWorkspace != null) {
372+
setWipeRepoBeforeBuild(cleanWorkspace.isWipeRepoBeforeBuild());
373+
374+
CleanTypeConfig cleanType = cleanWorkspace.getCleanType();
375+
if (cleanType != null) {
376+
setWipeBeforeBuild(cleanType.isWipe());
377+
setQuickCleanBeforeBuild(cleanType.isQuick());
378+
setRestoreChangedDeletedFiles(cleanType.isRestoreChangedDeletedFiles());
379+
}
380+
}
381+
382+
// Setup view mask
383+
if (useViewMask != null) {
384+
setUseViewMask(true);
385+
setViewMask(hudson.Util.fixEmptyAndTrim(useViewMask.getViewMask()));
386+
setUseViewMaskForPolling(useViewMask.isUseViewMaskForPolling());
387+
setUseViewMaskForSyncing(useViewMask.isUseViewMaskForSyncing());
388+
setUseViewMaskForChangeLog(useViewMask.isUseViewMaskForChangeLog());
389+
390+
}
391+
346392
this.clientOwner = Util.fixEmptyAndTrim(clientOwner);
347393

348394
if (p4SysRoot != null) {
@@ -464,6 +510,7 @@ protected Depot getDepot(Launcher launcher, FilePath workspace, AbstractProject
464510
return depot;
465511
}
466512

513+
467514
/**
468515
* Override of SCM.buildEnvVars() in order to setup the last change we have
469516
* sync'd to as a Hudson
@@ -1809,45 +1856,14 @@ public String getDisplayName() {
18091856

18101857
@Override
18111858
public SCM newInstance(StaplerRequest req, JSONObject formData) throws FormException {
1812-
PerforceSCM newInstance = (PerforceSCM)super.newInstance(req, formData);
1813-
String depotType = req.getParameter("p4.depotType");
1814-
boolean useStreamDepot = depotType.equals("stream");
1815-
boolean useClientSpec = depotType.equals("file");
1816-
newInstance.setUseStreamDepot(useStreamDepot);
1817-
if (useStreamDepot) {
1818-
newInstance.setP4Stream(req.getParameter("p4Stream"));
1819-
}
1820-
else {
1821-
newInstance.setUseClientSpec(useClientSpec);
1822-
if (useClientSpec) {
1823-
newInstance.setClientSpec(req.getParameter("clientSpec"));
1824-
}
1825-
else {
1826-
newInstance.setProjectPath(req.getParameter("projectPath"));
1827-
}
1828-
}
1829-
newInstance.setUseViewMask(req.getParameter("p4.useViewMask") != null);
1830-
newInstance.setViewMask(Util.fixEmptyAndTrim(req.getParameter("p4.viewMask")));
1831-
newInstance.setUseViewMaskForPolling(req.getParameter("p4.useViewMaskForPolling") != null);
1832-
newInstance.setUseViewMaskForSyncing(req.getParameter("p4.useViewMaskForSyncing") != null);
1833-
newInstance.setUseViewMaskForChangeLog(req.getParameter("p4.useViewMaskForChangeLog") != null);
1834-
1835-
String cleanType = req.getParameter("p4.cleanType");
1836-
boolean useWipe = false;
1837-
boolean useQuickClean = false;
1838-
if(cleanType != null && req.getParameter("p4.cleanWorkspace") != null){
1839-
useWipe = cleanType.equals("wipe");
1840-
useQuickClean = cleanType.equals("quick");
1841-
}
1842-
newInstance.setWipeBeforeBuild(useWipe);
1843-
newInstance.setQuickCleanBeforeBuild(useQuickClean);
1844-
1845-
String wipeRepo = req.getParameter("p4.wipeRepoBeforeBuild");
1846-
newInstance.setWipeRepoBeforeBuild(wipeRepo != null);
1847-
1848-
newInstance.setRestoreChangedDeletedFiles(req.getParameter("p4.restoreChangedDeletedFiles") != null);
1849-
1850-
return newInstance;
1859+
return (PerforceSCM)super.newInstance(req, formData);
1860+
}
1861+
1862+
/**Generates a random key for p4.config.instanceID*/
1863+
private static final AtomicLong P4_INSTANCE_COUNTER = new AtomicLong();
1864+
public String generateP4InstanceID() {
1865+
// There's no problem even if the counter reaches overflow
1866+
return Long.toString(P4_INSTANCE_COUNTER.incrementAndGet());
18511867
}
18521868

18531869
/**
Lines changed: 55 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,55 @@
1+
/*
2+
* The MIT License
3+
*
4+
* Copyright 2013 Oleg Nenashev <nenashev@synopsys.com>, Synopsys Inc.
5+
*
6+
* Permission is hereby granted, free of charge, to any person obtaining a copy
7+
* of this software and associated documentation files (the "Software"), to deal
8+
* in the Software without restriction, including without limitation the rights
9+
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
10+
* copies of the Software, and to permit persons to whom the Software is
11+
* furnished to do so, subject to the following conditions:
12+
*
13+
* The above copyright notice and this permission notice shall be included in
14+
* all copies or substantial portions of the Software.
15+
*
16+
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17+
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18+
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
19+
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
20+
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
21+
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
22+
* THE SOFTWARE.
23+
*/
24+
package hudson.plugins.perforce.config;
25+
26+
import hudson.plugins.perforce.PerforceSCM;
27+
import org.kohsuke.stapler.DataBoundConstructor;
28+
29+
/**
30+
* Contains workspace cleanup options for {@link PerforceSCM}.
31+
* @author Oleg Nenashev <nenashev@synopsys.com>, Synopsys Inc.
32+
* @since TODO: define a version
33+
*/
34+
public class CleanTypeConfig {
35+
String value;
36+
boolean restoreChangedDeletedFiles;
37+
38+
@DataBoundConstructor
39+
public CleanTypeConfig(String value, Boolean restoreChangedDeletedFiles) {
40+
this.value = value;
41+
this.restoreChangedDeletedFiles = restoreChangedDeletedFiles != null ? restoreChangedDeletedFiles.booleanValue() : false;
42+
}
43+
44+
public boolean isQuick() {
45+
return value.equals("quick");
46+
}
47+
48+
public boolean isWipe() {
49+
return value.equals("wipe");
50+
}
51+
52+
public boolean isRestoreChangedDeletedFiles() {
53+
return restoreChangedDeletedFiles;
54+
}
55+
}
Lines changed: 76 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,76 @@
1+
/*
2+
* The MIT License
3+
*
4+
* Copyright 2013 Oleg Nenashev <nenashev@synopsys.com>, Synopsys Inc.
5+
*
6+
* Permission is hereby granted, free of charge, to any person obtaining a copy
7+
* of this software and associated documentation files (the "Software"), to deal
8+
* in the Software without restriction, including without limitation the rights
9+
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
10+
* copies of the Software, and to permit persons to whom the Software is
11+
* furnished to do so, subject to the following conditions:
12+
*
13+
* The above copyright notice and this permission notice shall be included in
14+
* all copies or substantial portions of the Software.
15+
*
16+
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17+
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18+
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
19+
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
20+
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
21+
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
22+
* THE SOFTWARE.
23+
*/
24+
package hudson.plugins.perforce.config;
25+
26+
import org.kohsuke.stapler.DataBoundConstructor;
27+
28+
/**
29+
* Provides databound-transfer of depot type parameters for ${@link PerforceSCM}.
30+
* Class is developed in order to resolve <a href="https://issues.jenkins-ci.org/browse/JENKINS-18583">JENKINS-18583 issue</a>
31+
* @see PerforceSCMceSCM
32+
* @author Oleg Nenashev <nenashev@synopsys.com>, Synopsys Inc.
33+
* @since TODO: define a version
34+
*/
35+
public class DepotType {
36+
public static final String USE_P4STREAM_MARKER="stream";
37+
public static final String USE_CLIENTSPEC_MARKER="file";
38+
public static final String USE_PROJECTPATH_MARKER="map";
39+
40+
String value;
41+
String p4Stream;
42+
String clientSpec;
43+
String projectPath;
44+
45+
@DataBoundConstructor
46+
public DepotType(String value, String p4Stream, String clientSpec, String projectPath) {
47+
this.value = (value != null) ? value : "";
48+
this.p4Stream = p4Stream;
49+
this.clientSpec = clientSpec;
50+
this.projectPath = projectPath;
51+
}
52+
53+
public String getProjectPath() {
54+
return projectPath;
55+
}
56+
57+
public boolean useProjectPath() {
58+
return value.equals(USE_PROJECTPATH_MARKER);
59+
}
60+
61+
public String getClientSpec() {
62+
return clientSpec;
63+
}
64+
65+
public boolean useClientSpec() {
66+
return value.equals(USE_CLIENTSPEC_MARKER);
67+
}
68+
69+
public String getP4Stream() {
70+
return p4Stream;
71+
}
72+
73+
public boolean useP4Stream() {
74+
return value.equals(USE_P4STREAM_MARKER);
75+
}
76+
}
Lines changed: 63 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,63 @@
1+
/*
2+
* The MIT License
3+
*
4+
* Copyright 2013 Oleg Nenashev <nenashev@synopsys.com>, Synopsys Inc.
5+
*
6+
* Permission is hereby granted, free of charge, to any person obtaining a copy
7+
* of this software and associated documentation files (the "Software"), to deal
8+
* in the Software without restriction, including without limitation the rights
9+
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
10+
* copies of the Software, and to permit persons to whom the Software is
11+
* furnished to do so, subject to the following conditions:
12+
*
13+
* The above copyright notice and this permission notice shall be included in
14+
* all copies or substantial portions of the Software.
15+
*
16+
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17+
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18+
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
19+
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
20+
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
21+
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
22+
* THE SOFTWARE.
23+
*/
24+
package hudson.plugins.perforce.config;
25+
26+
import org.kohsuke.stapler.DataBoundConstructor;
27+
28+
/**
29+
* Defines masking options for {@link PerforceSCM}.
30+
* @author Oleg Nenashev <nenashev@synopsys.com>, Synopsys Inc.
31+
* @since TODO: define a version
32+
*/
33+
public class MaskViewConfig {
34+
String viewMask;
35+
boolean useViewMaskForPolling;
36+
boolean useViewMaskForSyncing;
37+
boolean useViewMaskForChangeLog;
38+
39+
@DataBoundConstructor
40+
public MaskViewConfig(String viewMask, boolean useViewMaskForPolling,
41+
boolean useViewMaskForSyncing, boolean useViewMaskForChangeLog) {
42+
this.viewMask = viewMask;
43+
this.useViewMaskForPolling = useViewMaskForPolling;
44+
this.useViewMaskForSyncing = useViewMaskForSyncing;
45+
this.useViewMaskForChangeLog = useViewMaskForChangeLog;
46+
}
47+
48+
public String getViewMask() {
49+
return viewMask;
50+
}
51+
52+
public boolean isUseViewMaskForPolling() {
53+
return useViewMaskForPolling;
54+
}
55+
56+
public boolean isUseViewMaskForSyncing() {
57+
return useViewMaskForSyncing;
58+
}
59+
60+
public boolean isUseViewMaskForChangeLog() {
61+
return useViewMaskForChangeLog;
62+
}
63+
}

0 commit comments

Comments
 (0)