package org.jenkinsci.plugins.p4.client; import com.perforce.p4java.core.IDepot; import com.perforce.p4java.core.file.FileSpecBuilder; import com.perforce.p4java.core.file.FileSpecOpStatus; import com.perforce.p4java.core.file.IFileSpec; import com.perforce.p4java.exception.P4JavaException; import com.perforce.p4java.option.server.GetDepotFilesOptions; import com.perforce.p4java.option.server.GetDirectoriesOptions; import com.perforce.p4java.server.IOptionsServer; import hudson.model.AutoCompletionCandidates; import java.io.Closeable; import java.io.IOException; import java.util.ArrayList; import java.util.List; public class NavigateHelper implements Closeable { private final int max; private final IOptionsServer p4; private final String root; private List<Node> nodes; public NavigateHelper(IOptionsServer p4) { this.max = 0; this.p4 = p4; String client = p4.getCurrentClient().getName(); this.root = "//" + client + "/"; } public NavigateHelper(int max) { this.max = max; p4 = ConnectionFactory.getConnection(); root = ""; } /** * Matches for a partial depot path * * @param depotPath a Perforce Depot path e.g. //depot/pro * @return matches for the depot path e.g. //depot/projA */ public AutoCompletionCandidates getCandidates(String depotPath) { nodes = new ArrayList<>(); buildPaths(depotPath); return getCandidates(); } /** * Get a list of path nodes. * * @param localPath a relative local path e.g. "" for root or "projA/comX" * @return list of nodes */ public List<Node> getNodes(String localPath) { nodes = new ArrayList<>(); String path = root + localPath; if (!path.isEmpty() && !path.endsWith("/")) { path = path + "/"; } buildPaths(path); return nodes; } private void buildPaths(String value) { try { if (!value.startsWith("//")) { value = "//" + value; } // remove leading '//' markers for depot matching String depot = value.substring(2); if (!depot.contains("/")) { if (!listDepots(depot)) { return; } } listDirs(value); listFiles(value); } catch (P4JavaException e) { } } /** * @param value path to match * @return true if value is a depot, false if partial match. e.g. false is returned * for 'dep' as it is only partial match to 'depot', even thought there may be only one match. * @throws P4JavaException */ private boolean listDepots(String value) throws P4JavaException { if (p4 != null) { List<IDepot> list = p4.getDepots(); for (IDepot l : list) { if (l.getName().equals(value)) { // complete match, return early nodes = new ArrayList<>(); return true; } if (l.getName().startsWith(value)) { nodes.add(new Node("//" + l.getName(), true)); } } } return false; } private void listDirs(String value) throws P4JavaException { if (p4 != null && value.length() > 4) { List<IFileSpec> dirs = specBuilder(value); GetDirectoriesOptions opts = new GetDirectoriesOptions(); List<IFileSpec> list = p4.getDirectories(dirs, opts); if (list == null) { return; } if (max > 0 && list.size() > max) { list = list.subList(0, max); } for (IFileSpec l : list) { String dir = l.getOriginalPathString(); if (dir != null) { nodes.add(new Node(dir, true)); } } } } private void listFiles(String value) throws P4JavaException { if (p4 != null && value.length() > 4) { List<IFileSpec> files = specBuilder(value); GetDepotFilesOptions opts = new GetDepotFilesOptions(); if (max > 0) { opts.setMaxResults(max); } List<IFileSpec> list = p4.getDepotFiles(files, opts); for (IFileSpec l : list) { if (l.getOpStatus().equals(FileSpecOpStatus.VALID)) { nodes.add(new Node(l.getDepotPathString(), false)); } } } } private List<IFileSpec> specBuilder(String value) { List<IFileSpec> files = FileSpecBuilder.makeFileSpecList(value + "*"); return files; } private AutoCompletionCandidates getCandidates() { AutoCompletionCandidates c = new AutoCompletionCandidates(); for (Node node : nodes) { c.add(node.getDepotPath()); } return c; } @Override public void close() throws IOException { try { p4.disconnect(); } catch (P4JavaException e) { throw new IOException(e); } } public static final class Node { private String name; private String depotPath; private boolean isDir; protected Node(String depotPath, boolean isDir) { this.isDir = isDir; this.depotPath = depotPath; this.name = depotPath.substring(depotPath.lastIndexOf("/") + 1); if (isDir && !depotPath.endsWith("/")) { this.depotPath = depotPath + "/"; } } public String getName() { return name; } public String getDepotPath() { return depotPath; } public boolean isDir() { return isDir; } } }
# | Change | User | Description | Committed | |
---|---|---|---|---|---|
#2 | 23685 | Paul Allen | Copy main -> dev | ||
#1 | 20641 | Paul Allen | Copy main -> dev (jenkinsci/p4-plugin) | ||
//guest/perforce_software/p4jenkins/main/src/main/java/org/jenkinsci/plugins/p4/client/NavigateHelper.java | |||||
#1 | 9690 | Paul Allen |
[Branching using p4-jenkins] Release 1.0.1 |
||
//guest/paul_allen/dev/p4-jenkins/p4-client/src/main/java/org/jenkinsci/plugins/p4/client/NavigateHelper.java | |||||
#1 | 9672 | Paul Allen | Refactor name from 'p4_client' to 'p4'. | ||
//guest/paul_allen/dev/p4-jenkins/p4-client/src/main/java/org/jenkinsci/plugins/p4_client/client/NavigateHelper.java | |||||
#1 | 9133 | Paul Allen |
Added Workspace mode for versioned Client Specs. Client Spec can be specified by depot path and used to configure workspace for build. - Includes fix for removing header when using p4 print. |