Skip to content
Browse files
[JENKINS-7618] potential fix for workspace path problem.
Using p4 -G where <depotFilePath> we can determine what the workspace path should be.
  • Loading branch information
Rob Petti committed Jun 22, 2011
1 parent 2d3fb9b commit 4f82c3a48009061c99bf905a39af59178b924094
@@ -104,6 +104,7 @@ public String toString() {
Action action;
String filename;
String revision;
String workspacePath;
Changelist changelist;

private static Map<Action, EditType> registry = new HashMap<Action, EditType>();
@@ -171,6 +172,14 @@ public void setRevision(String revision) {
this.revision = revision;

public String getWorkspacePath() {
return workspacePath;

public void setWorkspacePath(String workspacePath) {
this.workspacePath = workspacePath;

public void setChangelist(Changelist changelist) {
this.changelist = changelist;
@@ -38,6 +38,7 @@
import com.tek42.perforce.PerforceException;
import com.tek42.perforce.model.Changelist;
import com.tek42.perforce.model.Workspace;
import hudson.plugins.perforce.PerforceSCMHelper;

* Base API object for interacting with changelists.
@@ -63,9 +64,22 @@ public Changelist getChangelist(int number) throws PerforceException {
Changelist change =, Integer.toString(number))));
if(change == null)
throw new PerforceException("Failed to retrieve changelist " + number);
return change;

* Calculates the workspace paths for every file in the changelist.
* @param change
private void calculateWorkspacePaths(Changelist change) throws PerforceException{
for(Changelist.FileEntry file :change.getFiles()){
StringBuilder response = getPerforceResponse(new String[]{getP4Exe(),"-G","where",file.getFilename()});
PerforceSCMHelper.WhereMapping map = PerforceSCMHelper.parseWhereMapping(response.toString().getBytes());

* Returns a list of changelists that match the parameters
@@ -61,7 +61,7 @@ public String getUser() {
public Collection<String> getAffectedPaths() {
List<String> paths = new ArrayList<String>(change.getFiles().size());
for (Changelist.FileEntry entry : change.getFiles()) {
return paths;
@@ -1,7 +1,9 @@
package hudson.plugins.perforce;

import java.util.Collection;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.StringTokenizer;

@@ -51,4 +53,87 @@ static boolean projectPathIsValidForMultiviews(String projectPath) {
|| projectPath.indexOf('@') > -1; // labels ok {

static public class WhereMapping {
private String depot;
private String workspace;
private String filesystem;

public WhereMapping(String depot,String workspace,String filesystem){
this.depot = depot;
this.workspace = workspace;
this.filesystem = filesystem;

public String getDepotPath() {
return depot;

public String getFilesystemPath() {
return filesystem;

public String getWorkspacePath() {
return workspace;


static private int readInt(byte[] bytes, int offset){
int result=0;
for (int i=offset; i<offset+4; i++) {
result += (int) bytes[i] << (8*(i-offset));
return result;

static private Map<String,String> readPythonDictionary(byte[] dict){
int counter = 0;
Map<String,String> map = new HashMap<String,String>();
if(dict[0] == '{' && dict[1] == 's'){
//good to go
counter = 1;
while(counter < dict.length && dict[counter] != 0x30){
//read in pairs
String key,value;
if(dict[counter] == 's'){
key = readPythonString(dict,counter);
counter += key.length() + 4;
} else {
//keys 'should' always be strings
return null;
if(dict[counter] == 's'){
value = readPythonString(dict,counter);
counter += value.length() + 4;
} else {
//don't know how to handle non-string objects yet
return null;
map.put(key, value);
} else {
return null;
return map;

static private String readPythonString(byte[] bytes, int offset){
int length = readInt(bytes, offset);
String result = new String(bytes, offset+4, length);
return result;

static public WhereMapping parseWhereMapping(byte[] whereOutput){
String depot;
String workspace;
String filesystem;
Map<String,String> map = readPythonDictionary(whereOutput);
depot = map.get("depotFile");
workspace = map.get("clientFile");
filesystem = map.get("path");
return new WhereMapping(depot,workspace,filesystem);

@@ -1,5 +1,6 @@
package hudson.plugins.perforce;

import hudson.plugins.perforce.PerforceSCMHelper.WhereMapping;
import java.util.ArrayList;
import java.util.List;

@@ -39,4 +40,42 @@ public void testProjectPathIsValid() {

public void testWhereParser() {
byte testOutput[] = {
(byte)0x7b, (byte)0x73, (byte)0x04, (byte)0x00, (byte)0x00, (byte)0x00, (byte)0x63, (byte)0x6f, (byte)0x64, (byte)0x65, (byte)0x73, (byte)0x04, (byte)0x00, (byte)0x00, (byte)0x00, (byte)0x73,
(byte)0x74, (byte)0x61, (byte)0x74, (byte)0x73, (byte)0x09, (byte)0x00, (byte)0x00, (byte)0x00, (byte)0x64, (byte)0x65, (byte)0x70, (byte)0x6f, (byte)0x74, (byte)0x46, (byte)0x69, (byte)0x6c,
(byte)0x65, (byte)0x73, (byte)0x2b, (byte)0x00, (byte)0x00, (byte)0x00, (byte)0x2f, (byte)0x2f, (byte)0x49, (byte)0x6e, (byte)0x73, (byte)0x74, (byte)0x61, (byte)0x6c, (byte)0x6c, (byte)0x2f,
(byte)0x74, (byte)0x72, (byte)0x75, (byte)0x6e, (byte)0x6b, (byte)0x2f, (byte)0x49, (byte)0x6e, (byte)0x73, (byte)0x74, (byte)0x61, (byte)0x6c, (byte)0x6c, (byte)0x65, (byte)0x72, (byte)0x73,
(byte)0x2f, (byte)0x62, (byte)0x75, (byte)0x69, (byte)0x6c, (byte)0x64, (byte)0x2e, (byte)0x70, (byte)0x72, (byte)0x6f, (byte)0x70, (byte)0x65, (byte)0x72, (byte)0x74, (byte)0x69, (byte)0x65,
(byte)0x73, (byte)0x73, (byte)0x0a, (byte)0x00, (byte)0x00, (byte)0x00, (byte)0x63, (byte)0x6c, (byte)0x69, (byte)0x65, (byte)0x6e, (byte)0x74, (byte)0x46, (byte)0x69, (byte)0x6c, (byte)0x65,
(byte)0x73, (byte)0x32, (byte)0x00, (byte)0x00, (byte)0x00, (byte)0x2f, (byte)0x2f, (byte)0x72, (byte)0x70, (byte)0x65, (byte)0x74, (byte)0x74, (byte)0x69, (byte)0x2f, (byte)0x49, (byte)0x6e,
(byte)0x73, (byte)0x74, (byte)0x61, (byte)0x6c, (byte)0x6c, (byte)0x2f, (byte)0x74, (byte)0x72, (byte)0x75, (byte)0x6e, (byte)0x6b, (byte)0x2f, (byte)0x49, (byte)0x6e, (byte)0x73, (byte)0x74,
(byte)0x61, (byte)0x6c, (byte)0x6c, (byte)0x65, (byte)0x72, (byte)0x73, (byte)0x2f, (byte)0x62, (byte)0x75, (byte)0x69, (byte)0x6c, (byte)0x64, (byte)0x2e, (byte)0x70, (byte)0x72, (byte)0x6f,
(byte)0x70, (byte)0x65, (byte)0x72, (byte)0x74, (byte)0x69, (byte)0x65, (byte)0x73, (byte)0x73, (byte)0x04, (byte)0x00, (byte)0x00, (byte)0x00, (byte)0x70, (byte)0x61, (byte)0x74, (byte)0x68,
(byte)0x73, (byte)0x40, (byte)0x00, (byte)0x00, (byte)0x00, (byte)0x2f, (byte)0x68, (byte)0x6f, (byte)0x6d, (byte)0x65, (byte)0x2f, (byte)0x72, (byte)0x70, (byte)0x65, (byte)0x74, (byte)0x74,
(byte)0x69, (byte)0x2f, (byte)0x77, (byte)0x6f, (byte)0x72, (byte)0x6b, (byte)0x73, (byte)0x70, (byte)0x61, (byte)0x63, (byte)0x65, (byte)0x2f, (byte)0x49, (byte)0x6e, (byte)0x73, (byte)0x74,
(byte)0x61, (byte)0x6c, (byte)0x6c, (byte)0x2f, (byte)0x74, (byte)0x72, (byte)0x75, (byte)0x6e, (byte)0x6b, (byte)0x2f, (byte)0x49, (byte)0x6e, (byte)0x73, (byte)0x74, (byte)0x61, (byte)0x6c,
(byte)0x6c, (byte)0x65, (byte)0x72, (byte)0x73, (byte)0x2f, (byte)0x62, (byte)0x75, (byte)0x69, (byte)0x6c, (byte)0x64, (byte)0x2e, (byte)0x70, (byte)0x72, (byte)0x6f, (byte)0x70, (byte)0x65,
(byte)0x72, (byte)0x74, (byte)0x69, (byte)0x65, (byte)0x73, (byte)0x30, (byte)0x7b, (byte)0x73, (byte)0x04, (byte)0x00, (byte)0x00, (byte)0x00, (byte)0x63, (byte)0x6f, (byte)0x64, (byte)0x65,
(byte)0x73, (byte)0x04, (byte)0x00, (byte)0x00, (byte)0x00, (byte)0x73, (byte)0x74, (byte)0x61, (byte)0x74, (byte)0x73, (byte)0x09, (byte)0x00, (byte)0x00, (byte)0x00, (byte)0x64, (byte)0x65,
(byte)0x70, (byte)0x6f, (byte)0x74, (byte)0x46, (byte)0x69, (byte)0x6c, (byte)0x65, (byte)0x73, (byte)0x24, (byte)0x00, (byte)0x00, (byte)0x00, (byte)0x2f, (byte)0x2f, (byte)0x49, (byte)0x6e,
(byte)0x73, (byte)0x74, (byte)0x61, (byte)0x6c, (byte)0x6c, (byte)0x2f, (byte)0x74, (byte)0x72, (byte)0x75, (byte)0x6e, (byte)0x6b, (byte)0x2f, (byte)0x49, (byte)0x6e, (byte)0x73, (byte)0x74,
(byte)0x61, (byte)0x6c, (byte)0x6c, (byte)0x65, (byte)0x72, (byte)0x73, (byte)0x2f, (byte)0x62, (byte)0x75, (byte)0x69, (byte)0x6c, (byte)0x64, (byte)0x2e, (byte)0x78, (byte)0x6d, (byte)0x6c,
(byte)0x73, (byte)0x0a, (byte)0x00, (byte)0x00, (byte)0x00, (byte)0x63, (byte)0x6c, (byte)0x69, (byte)0x65, (byte)0x6e, (byte)0x74, (byte)0x46, (byte)0x69, (byte)0x6c, (byte)0x65, (byte)0x73,
(byte)0x2b, (byte)0x00, (byte)0x00, (byte)0x00, (byte)0x2f, (byte)0x2f, (byte)0x72, (byte)0x70, (byte)0x65, (byte)0x74, (byte)0x74, (byte)0x69, (byte)0x2f, (byte)0x49, (byte)0x6e, (byte)0x73,
(byte)0x74, (byte)0x61, (byte)0x6c, (byte)0x6c, (byte)0x2f, (byte)0x74, (byte)0x72, (byte)0x75, (byte)0x6e, (byte)0x6b, (byte)0x2f, (byte)0x49, (byte)0x6e, (byte)0x73, (byte)0x74, (byte)0x61,
(byte)0x6c, (byte)0x6c, (byte)0x65, (byte)0x72, (byte)0x73, (byte)0x2f, (byte)0x62, (byte)0x75, (byte)0x69, (byte)0x6c, (byte)0x64, (byte)0x2e, (byte)0x78, (byte)0x6d, (byte)0x6c, (byte)0x73,
(byte)0x04, (byte)0x00, (byte)0x00, (byte)0x00, (byte)0x70, (byte)0x61, (byte)0x74, (byte)0x68, (byte)0x73, (byte)0x39, (byte)0x00, (byte)0x00, (byte)0x00, (byte)0x2f, (byte)0x68, (byte)0x6f,
(byte)0x6d, (byte)0x65, (byte)0x2f, (byte)0x72, (byte)0x70, (byte)0x65, (byte)0x74, (byte)0x74, (byte)0x69, (byte)0x2f, (byte)0x77, (byte)0x6f, (byte)0x72, (byte)0x6b, (byte)0x73, (byte)0x70,
(byte)0x61, (byte)0x63, (byte)0x65, (byte)0x2f, (byte)0x49, (byte)0x6e, (byte)0x73, (byte)0x74, (byte)0x61, (byte)0x6c, (byte)0x6c, (byte)0x2f, (byte)0x74, (byte)0x72, (byte)0x75, (byte)0x6e,
(byte)0x6b, (byte)0x2f, (byte)0x49, (byte)0x6e, (byte)0x73, (byte)0x74, (byte)0x61, (byte)0x6c, (byte)0x6c, (byte)0x65, (byte)0x72, (byte)0x73, (byte)0x2f, (byte)0x62, (byte)0x75, (byte)0x69,
(byte)0x6c, (byte)0x64, (byte)0x2e, (byte)0x78, (byte)0x6d, (byte)0x6c, (byte)0x30
PerforceSCMHelper.WhereMapping map;
map = PerforceSCMHelper.parseWhereMapping(testOutput);
assertEquals("//Install/trunk/Installers/", map.getDepotPath());
assertEquals("//rpetti/Install/trunk/Installers/", map.getWorkspacePath());
assertEquals("/home/rpetti/workspace/Install/trunk/Installers/", map.getFilesystemPath());


0 comments on commit 4f82c3a

Please sign in to comment.