Skip to content
Permalink
Browse files

[JENKINS-7618] improvements to where parsing

* correctly handle cases where the file isn't in the client workspace
* getAffectedPaths will only provide files that are in the client workspace
* added retry in the event of data corruption
  • Loading branch information...
Rob Petti
Rob Petti committed Jul 12, 2011
1 parent fd481a6 commit ba734198ade6038ff0dcbc0671009ecff6763809
@@ -39,6 +39,7 @@
import com.tek42.perforce.model.Changelist;
import com.tek42.perforce.model.Workspace;
import hudson.plugins.perforce.PerforceSCMHelper;
import java.io.IOException;

/**
* Base API object for interacting with changelists.
@@ -74,9 +75,27 @@ public Changelist getChangelist(int number) throws PerforceException {
*/
private void calculateWorkspacePaths(Changelist change) throws PerforceException{
for(Changelist.FileEntry file :change.getFiles()){
byte[] bytes = getRawPerforceResponseBytes(new String[]{getP4Exe(),"-G","where",file.getFilename()});
PerforceSCMHelper.WhereMapping map = PerforceSCMHelper.parseWhereMapping(bytes);
file.setWorkspacePath(map.getWorkspacePath().replaceAll("^//\\S+?/",""));
String workspacePath;
try {
workspacePath = getWorkspacePathForFile(file.getFilename());
} catch (PerforceException e) {
//Try again
workspacePath = getWorkspacePathForFile(file.getFilename());
}
file.setWorkspacePath(workspacePath);
}
}

private String getWorkspacePathForFile(String file) throws PerforceException {
byte[] bytes = getRawPerforceResponseBytes(new String[]{getP4Exe(),"-G","where",file});
PerforceSCMHelper.WhereMapping map = PerforceSCMHelper.parseWhereMapping(bytes);
String workspacePath = map.getWorkspacePath();
if(workspacePath!=null){
//trim the head off of it, so it's a workspace-relative path.
return map.getWorkspacePath().replaceAll("^//\\S+?/", "");
} else {
//We didn't get a workspace path, likely because it's not in the workspace
return "";
}
}

@@ -61,7 +61,10 @@ public String getUser() {
public Collection<String> getAffectedPaths() {
List<String> paths = new ArrayList<String>(change.getFiles().size());
for (Changelist.FileEntry entry : change.getFiles()) {
paths.add(entry.getWorkspacePath()==null?entry.getFilename():entry.getWorkspacePath());
//only report those files that are actually in the workspace
if(entry.getWorkspacePath()!=null && !entry.getWorkspacePath().equals("")){
paths.add(entry.getWorkspacePath());
}
}
return paths;
}
@@ -1,16 +1,22 @@
package hudson.plugins.perforce;

import com.tek42.perforce.PerforceException;
import java.io.IOException;
import java.util.Collection;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.StringTokenizer;
import java.util.logging.Level;
import java.util.logging.Logger;


/**
* @author Brian Westrich
*/
public final class PerforceSCMHelper {

private static final Logger LOGGER = Logger.getLogger(PerforceSCMHelper.class.getName());
private static final String DEPOT_ROOT = "//";
private static final String EXCLUSION_VIEW_PREFIX = "-";

@@ -107,8 +113,12 @@ static public int readInt(byte[] bytes, int offset){
counter++;
value = readPythonString(dict,counter);
counter += value.length() + 4;
} else if(dict[counter] == 'i'){
counter++;
value = Integer.toString(readInt(dict, counter));
counter += 4;
} else {
//don't know how to handle non-string objects yet
// Don't know how to handle anything but ints and strings, so bail out
return null;
}
map.put(key, value);
@@ -125,11 +135,25 @@ static private String readPythonString(byte[] bytes, int offset){
return result;
}

static public WhereMapping parseWhereMapping(byte[] whereOutput){
static public WhereMapping parseWhereMapping(byte[] whereOutput) throws PerforceException {
String depot;
String workspace;
String filesystem;
Map<String,String> map = readPythonDictionary(whereOutput);
if(map == null){
throw new PerforceException("Could not parse Where map.");
}
if(map.get("code").equals("error")){
//error handling
LOGGER.log(Level.FINE, "P4 Where Parsing Error: "+map.get("data"));
if(map.get("data")!=null){
if(map.get("data").contains("not in client view")){
//this is non-fatal, but not sure what to do with it
} else {
throw new PerforceException("P4 Where Parsing Error: "+map.get("data"));
}
}
}
depot = map.get("depotFile");
workspace = map.get("clientFile");
filesystem = map.get("path");
@@ -1,10 +1,16 @@
package hudson.plugins.perforce;

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

import java.io.IOException;
import junit.framework.TestCase;
import java.io.BufferedReader;
import java.io.InputStreamReader;
import java.io.File;
import java.io.FileInputStream;
import java.io.InputStream;

public class PerforceSCMHelperTest extends TestCase {

@@ -40,7 +46,7 @@ public void testProjectPathIsValid() {
.projectPathIsValidForMultiviews("//...@mylabel"));
}

public void testWhereParser() {
public void testWhereParser() throws PerforceException {
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,
@@ -84,4 +90,74 @@ public void testReadIntNegativeByte() {
assertEquals(150,result);
}

public void disabledtestWhereData() throws java.io.FileNotFoundException, java.io.IOException, PerforceException{
File whereFile = new File("/home/rpetti/Downloads/whereData.dat");
InputStream input = new FileInputStream(whereFile);
int read=0;
byte data[] = new byte[1024];
ArrayList<Byte> bytes = new ArrayList<Byte>(1024);
while((read = input.read(data, 0, 1024))!=-1){
for(int i=0; i<read; i++){
bytes.add(new Byte((byte)(data[i]&0xff)));
}
}
input.close();
byte[] byteArray = new byte[bytes.size()];
for(int i=0; i<bytes.size(); i++){
byteArray[i] = bytes.get(i).byteValue();
}
PerforceSCMHelper.WhereMapping map;
map = PerforceSCMHelper.parseWhereMapping(byteArray);
System.out.println(map.getDepotPath() + " " + map.getFilesystemPath() + " " + map.getWorkspacePath());
}

public void disabledtestMappingExtensively() throws IOException, PerforceException {
ArrayList<String> opts = new ArrayList<String>();
opts.add("-c");
opts.add("rpetti");
opts.add("-p");
opts.add("ratchet:1668");
ArrayList<String> command = new ArrayList<String>();
command.add("p4");
command.addAll(opts);
command.add("files");
command.add("//DSConsole/...");
Process p = Runtime.getRuntime().exec(command.toArray(new String[0]));
p.getOutputStream().close();
p.getErrorStream().close();
BufferedReader br = new BufferedReader(new InputStreamReader(p.getInputStream()));
String line=null;
while((line = br.readLine()) != null){
int hashLoc = line.indexOf("#");
String filename = line.substring(0, hashLoc);
System.out.println("Testing where on " + filename);
ArrayList<String> whereCommand = new ArrayList<String>();
whereCommand.add("p4");
whereCommand.addAll(opts);
whereCommand.add("-G");
whereCommand.add("where");
whereCommand.add(filename);
Process whereProc = Runtime.getRuntime().exec(whereCommand.toArray(new String[0]));
whereProc.getErrorStream().close();
whereProc.getOutputStream().close();
int read=0;
byte data[] = new byte[1024];
ArrayList<Byte> bytes = new ArrayList<Byte>(1024);
while((read = whereProc.getInputStream().read(data, 0, 1024))!=-1){
for(int i=0; i<read; i++){
bytes.add(new Byte((byte)(data[i]&0xff)));
}
}
whereProc.getInputStream().close();
byte[] byteArray = new byte[bytes.size()];
for(int i=0; i<bytes.size(); i++){
byteArray[i] = bytes.get(i).byteValue();
}
PerforceSCMHelper.WhereMapping map;
map = PerforceSCMHelper.parseWhereMapping(byteArray);
System.out.println(map.getDepotPath() + " " + map.getFilesystemPath() + " " + map.getWorkspacePath());
}
br.close();
}

}

0 comments on commit ba73419

Please sign in to comment.
You can’t perform that action at this time.