Skip to content

Commit 5529e90

Browse files
committed
Explicit Poll Workspace Implementation
1 parent 76953c5 commit 5529e90

File tree

10 files changed

+264
-0
lines changed

10 files changed

+264
-0
lines changed

src/main/java/org/jenkinsci/plugins/p4/PerforceScm.java

Lines changed: 37 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -47,8 +47,10 @@
4747
import org.jenkinsci.plugins.p4.changes.P4ChangeSet;
4848
import org.jenkinsci.plugins.p4.changes.P4GraphRef;
4949
import org.jenkinsci.plugins.p4.changes.P4LabelRef;
50+
import org.jenkinsci.plugins.p4.changes.P4PollRef;
5051
import org.jenkinsci.plugins.p4.changes.P4Ref;
5152
import org.jenkinsci.plugins.p4.client.ConnectionHelper;
53+
import org.jenkinsci.plugins.p4.client.TempClientHelper;
5254
import org.jenkinsci.plugins.p4.credentials.P4BaseCredentials;
5355
import org.jenkinsci.plugins.p4.credentials.P4CredentialsImpl;
5456
import org.jenkinsci.plugins.p4.credentials.P4InvalidCredentialException;
@@ -97,6 +99,7 @@
9799
import java.util.Optional;
98100
import java.util.logging.Level;
99101
import java.util.logging.Logger;
102+
import java.util.stream.Collectors;
100103

101104
public class PerforceScm extends SCM {
102105

@@ -530,10 +533,13 @@ private List<P4Ref> lookForChanges(FilePath buildWorkspace, Workspace ws, Run<?,
530533
return null;
531534
}
532535

536+
List<P4PollRef> lastPollPathRefs = TagAction.getLastPollChange(lastRun, listener, syncID);
537+
533538
// Create task
534539
PollTask task = new PollTask(credential, lastRun, listener, filter, lastRefs);
535540
task.setWorkspace(ws);
536541
task.setLimit(pin);
542+
task.setPollRefChanges(lastPollPathRefs);
537543

538544
// Execute remote task
539545
List<P4Ref> changes = buildWorkspace.act(task);
@@ -650,10 +656,41 @@ To help lookForChanges() find the correct change to build, sending it the previo
650656
task.setIncrementalChanges(changes);
651657
}
652658

659+
// Adding all the pollPath and their latest changes in a list
660+
List<P4Ref> finalPollPathList = new ArrayList<P4Ref>();
661+
if (ws instanceof ManualWorkspaceImpl) {
662+
String workspacePollpath = ((ManualWorkspaceImpl) ws).getSpec().getPollPath();
663+
List<String> pollPathList = new ArrayList<>();
664+
// Extract and clean comma-separated polling paths
665+
if (workspacePollpath != null && !workspacePollpath.isEmpty()) {
666+
pollPathList = Arrays.stream(workspacePollpath.split(","))
667+
.map(String::trim)
668+
.filter(s -> !s.isEmpty())
669+
.collect(Collectors.toList());
670+
}
671+
672+
if(!pollPathList.isEmpty()) {
673+
try (TempClientHelper p4 = new TempClientHelper(null, credential, listener, null)) {
674+
for (String pollPath : pollPathList) {
675+
// Fetching the latest change for each polling path
676+
List<P4Ref> changes = p4.listHaveChangesForPollPath(new P4PollRef(0, pollPath));
677+
if (!changes.isEmpty()) {
678+
P4Ref latestChange = changes.get(0);
679+
P4PollRef pollRef = new P4PollRef(latestChange.getChange(), pollPath);
680+
finalPollPathList.add(pollRef);
681+
}
682+
}
683+
} catch (Exception ex) {
684+
throw new RuntimeException("Error while processing polling paths: ", ex);
685+
}
686+
}
687+
}
688+
653689
// Add tagging action to build, enabling label support.
654690
TagAction tag = new TagAction(run, credential);
655691
tag.setWorkspace(ws);
656692
tag.setRefChanges(task.getSyncChange());
693+
tag.setPollPathChanges(finalPollPathList);
657694
// JENKINS-37442: Make the log file name available
658695
tag.setChangelog(changelogFile);
659696
// JENKINS-39107: Make Depot location of Jenkins file available
Lines changed: 79 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,79 @@
1+
package org.jenkinsci.plugins.p4.changes;
2+
3+
import com.perforce.p4java.core.IChangelistSummary;
4+
import com.perforce.p4java.core.file.IFileSpec;
5+
import org.jenkinsci.plugins.p4.client.ClientHelper;
6+
import org.jenkinsci.plugins.p4.client.ConnectionHelper;
7+
8+
import java.util.List;
9+
10+
public class P4PollRef implements P4Ref {
11+
12+
private final long change;
13+
private final String pollPath;
14+
15+
public P4PollRef(long change, String pollPath) {
16+
this.change = change;
17+
this.pollPath = pollPath;
18+
}
19+
20+
@Override
21+
public P4ChangeEntry getChangeEntry(ClientHelper p4) throws Exception {
22+
P4ChangeEntry cl = new P4ChangeEntry();
23+
IChangelistSummary summary = p4.getChangeSummary(change);
24+
cl.setChange(p4, summary);
25+
return cl;
26+
}
27+
28+
@Override
29+
public boolean isLabel() {
30+
return false;
31+
}
32+
33+
@Override
34+
public boolean isCommit() {
35+
return false;
36+
}
37+
38+
@Override
39+
public long getChange() {
40+
return change;
41+
}
42+
43+
public String getPollPath() {
44+
return pollPath;
45+
}
46+
47+
@Override
48+
public List<IFileSpec> getFiles(ConnectionHelper p4, int limit) throws Exception {
49+
return p4.getChangeFiles(change, limit);
50+
}
51+
52+
@Override
53+
public String toString() {
54+
return Long.toString(change);
55+
}
56+
57+
@Override
58+
public boolean equals(Object obj) {
59+
if (obj instanceof P4PollRef) {
60+
P4PollRef ref = (P4PollRef) obj;
61+
if (ref.getPollPath().equals(this.pollPath) && ref.getChange()==this.change) {
62+
return true;
63+
}
64+
}
65+
return false;
66+
}
67+
68+
@Override
69+
public int compareTo(Object obj) {
70+
if (equals(obj)) {
71+
return 0;
72+
}
73+
if (obj instanceof P4PollRef) {
74+
P4PollRef ref = (P4PollRef) obj;
75+
return (int) (change - ref.getChange());
76+
}
77+
throw new ClassCastException();
78+
}
79+
}

src/main/java/org/jenkinsci/plugins/p4/client/ClientHelper.java

Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -41,6 +41,7 @@
4141
import org.jenkinsci.plugins.p4.changes.P4ChangeRef;
4242
import org.jenkinsci.plugins.p4.changes.P4GraphRef;
4343
import org.jenkinsci.plugins.p4.changes.P4LabelRef;
44+
import org.jenkinsci.plugins.p4.changes.P4PollRef;
4445
import org.jenkinsci.plugins.p4.changes.P4Ref;
4546
import org.jenkinsci.plugins.p4.credentials.P4BaseCredentials;
4647
import org.jenkinsci.plugins.p4.populate.AutoCleanImpl;
@@ -1388,6 +1389,33 @@ public List<P4Ref> listHaveChanges(List<P4Ref> fromRefs) throws Exception {
13881389
return listHaveChanges(path);
13891390
}
13901391

1392+
/**
1393+
* Fetches a list of changes for a directory poll path (other than client view mapping)
1394+
*
1395+
* @param from List of from revisions
1396+
* @return changelist To Revision
1397+
* @throws Exception push up stack
1398+
*/
1399+
public List<P4Ref> listHaveChangesForPollPath(P4PollRef from) throws Exception {
1400+
List<P4Ref> finalChanges = new ArrayList<P4Ref>();
1401+
1402+
if (from.getChange() >= 0) {
1403+
String path = from.getPollPath() + "/...@" + from.getChange() + ",now";
1404+
log("P4: Polling with range: " + from + ",now for poll path: " + from.getPollPath());
1405+
1406+
List<P4Ref> changes = listChanges(path);
1407+
if (changes.size() > 0) {
1408+
P4PollRef firstChange = new P4PollRef(changes.get(0).getChange(), from.getPollPath());
1409+
if (!from.equals(firstChange)) {
1410+
finalChanges.add(firstChange);
1411+
return finalChanges;
1412+
}
1413+
}
1414+
}
1415+
1416+
return finalChanges;
1417+
}
1418+
13911419
/**
13921420
* Fetches a list of changes needed to update the workspace to the specified
13931421
* limit. The limit could be a Perforce change number, label or counter.

src/main/java/org/jenkinsci/plugins/p4/tagging/TagAction.java

Lines changed: 47 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@
1010
import org.jenkinsci.plugins.p4.PerforceScm;
1111
import org.jenkinsci.plugins.p4.changes.P4ChangeRef;
1212
import org.jenkinsci.plugins.p4.changes.P4LabelRef;
13+
import org.jenkinsci.plugins.p4.changes.P4PollRef;
1314
import org.jenkinsci.plugins.p4.changes.P4Ref;
1415
import org.jenkinsci.plugins.p4.changes.P4Revision;
1516
import org.jenkinsci.plugins.p4.client.ClientHelper;
@@ -41,6 +42,7 @@ public class TagAction extends AbstractScmTagAction {
4142
private List<String> tags = new ArrayList<String>();
4243

4344
private List<P4Ref> refChanges;
45+
private List<P4PollRef> pollRefChanges;
4446

4547
private P4Revision buildChange;
4648
private P4Review review;
@@ -298,6 +300,36 @@ public static List<P4Ref> getLastChange(Run<?, ?> run, TaskListener listener, St
298300
return changes;
299301
}
300302

303+
public static List<P4PollRef> getLastPollChange(Run<?, ?> run, TaskListener listener, String syncID) {
304+
List<P4PollRef> changes = new ArrayList<>();
305+
306+
List<TagAction> actions = lastActions(run);
307+
308+
if (actions == null || syncID == null || syncID.isEmpty()) {
309+
listener.getLogger().println("No previous build found...");
310+
return changes;
311+
}
312+
313+
logger.fine(" using syncID: " + syncID);
314+
315+
boolean found = false;
316+
for (TagAction action : actions) {
317+
if (syncID.equals(action.getSyncID())) {
318+
List<P4PollRef> pollChanges = action.getPollPathChanges();
319+
320+
if (pollChanges != null && !pollChanges.isEmpty()) {
321+
for (P4PollRef poll : pollChanges) {
322+
if (poll.getPollPath() != null && !changes.contains(poll)) {
323+
changes.add(poll);
324+
}
325+
}
326+
}
327+
}
328+
}
329+
330+
return changes;
331+
}
332+
301333
/**
302334
* Find the last action; use this for environment variable as the last action has the latest values.
303335
*
@@ -353,4 +385,19 @@ public void setJenkinsPath(String jenkinsPath) {
353385
public String getJenkinsPath() {
354386
return jenkinsPath;
355387
}
388+
389+
public void setPollPathChanges(List<P4Ref> finalPollPathList) {
390+
List<P4PollRef> changes = new ArrayList<P4PollRef>();
391+
392+
for(P4Ref ref : finalPollPathList) {
393+
P4PollRef poll = new P4PollRef(ref.getChange(), ((P4PollRef)ref).getPollPath());
394+
changes.add(poll);
395+
}
396+
this.pollRefChanges = changes;
397+
}
398+
399+
public List<P4PollRef> getPollPathChanges() {
400+
return this.pollRefChanges;
401+
}
402+
356403
}

src/main/java/org/jenkinsci/plugins/p4/tasks/CheckoutTask.java

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@
1414
import org.jenkinsci.plugins.p4.changes.P4ChangeEntry;
1515
import org.jenkinsci.plugins.p4.changes.P4ChangeRef;
1616
import org.jenkinsci.plugins.p4.changes.P4LabelRef;
17+
import org.jenkinsci.plugins.p4.changes.P4PollRef;
1718
import org.jenkinsci.plugins.p4.changes.P4Ref;
1819
import org.jenkinsci.plugins.p4.client.ClientHelper;
1920
import org.jenkinsci.plugins.p4.console.P4Logging;
@@ -315,6 +316,9 @@ public List<P4ChangeEntry> getChangesFull(List<P4Ref> lastRefs) {
315316
}
316317
} else {
317318
// add classic changes
319+
if(build instanceof P4PollRef) {
320+
continue;
321+
}
318322
List<P4Ref> changes = p4.listChanges(lastRefs, build);
319323
for (P4Ref change : changes) {
320324
P4ChangeEntry cl = change.getChangeEntry(p4);

src/main/java/org/jenkinsci/plugins/p4/tasks/PollTask.java

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@
1212
import jenkins.security.Roles;
1313
import org.jenkinsci.plugins.p4.changes.P4ChangeRef;
1414
import org.jenkinsci.plugins.p4.changes.P4LabelRef;
15+
import org.jenkinsci.plugins.p4.changes.P4PollRef;
1516
import org.jenkinsci.plugins.p4.changes.P4Ref;
1617
import org.jenkinsci.plugins.p4.client.ClientHelper;
1718
import org.jenkinsci.plugins.p4.filters.Filter;
@@ -37,13 +38,15 @@ public class PollTask extends AbstractTask implements FileCallable<List<P4Ref>>,
3738

3839
private final List<Filter> filter;
3940
private final List<P4Ref> lastRefs;
41+
private List<P4PollRef> lastPollRefs;
4042

4143
private String pin;
4244

4345
public PollTask(String credential, Run<?, ?> run, TaskListener listener, List<Filter> filter, List<P4Ref> lastRefs) {
4446
super(credential, run, listener);
4547
this.filter = filter;
4648
this.lastRefs = lastRefs;
49+
this.lastPollRefs = getPollRefChanges();
4750
}
4851

4952
@SuppressWarnings("unchecked")
@@ -94,13 +97,30 @@ public Object task(ClientHelper p4) throws Exception {
9497
}
9598
}
9699

100+
// Poll polling path changes
101+
if (changes.isEmpty() && !lastPollRefs.isEmpty()) {
102+
List<P4Ref> pollChanges = new ArrayList<P4Ref>();
103+
104+
for (P4PollRef ref : lastPollRefs) {
105+
pollChanges = p4.listHaveChangesForPollPath(ref);
106+
changes.addAll(pollChanges);
107+
}
108+
}
97109
return changes;
98110
}
99111

100112
public void setLimit(String expandedPin) {
101113
pin = expandedPin;
102114
}
103115

116+
public void setPollRefChanges(List<P4PollRef> pollRefs) {
117+
lastPollRefs = pollRefs;
118+
}
119+
120+
public List<P4PollRef> getPollRefChanges() {
121+
return lastPollRefs;
122+
}
123+
104124
/**
105125
* Returns true if change should be filtered
106126
*

src/main/java/org/jenkinsci/plugins/p4/workspace/WorkspaceSpec.java

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -36,6 +36,16 @@ public class WorkspaceSpec extends AbstractDescribableImpl<WorkspaceSpec> implem
3636

3737
private final String serverID;
3838
private final boolean backup;
39+
private String pollPath;
40+
41+
public String getPollPath() {
42+
return pollPath;
43+
}
44+
45+
@DataBoundSetter
46+
public void setPollPath(String pollPath) {
47+
this.pollPath = pollPath;
48+
}
3949

4050
public String getStreamName() {
4151
return streamName;
@@ -96,6 +106,7 @@ public WorkspaceSpec(boolean allwrite, boolean clobber, boolean compress,
96106
this.type = type;
97107
this.serverID = serverID;
98108
this.backup = backup;
109+
this.pollPath = getPollPath();
99110
}
100111

101112
// Default setup for Classic Workspace
@@ -114,6 +125,7 @@ public WorkspaceSpec(String view, String changeView) {
114125
this.type = null;
115126
this.serverID = null;
116127
this.backup = true;
128+
this.pollPath = getPollPath();
117129
}
118130

119131
@Deprecated

src/main/resources/org/jenkinsci/plugins/p4/workspace/ManualWorkspaceImpl/config.jelly

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -40,6 +40,7 @@
4040
document.getElementById("id.stream").value = json.stream;
4141
document.getElementById("id.line").value = json.line;
4242
document.getElementById("id.view").value = json.view;
43+
document.getElementById("id.pollPath").value = json.pollPath;
4344
});
4445
}
4546
</script>

0 commit comments

Comments
 (0)