Index: src/main/resources/hudson/plugins/accurev/AccurevSCM/global.jelly
===================================================================
--- src/main/resources/hudson/plugins/accurev/AccurevSCM/global.jelly (revision 20179)
+++ src/main/resources/hudson/plugins/accurev/AccurevSCM/global.jelly Mon Jul 27 17:54:18 CEST 2009
@@ -26,6 +26,10 @@
+
+
+
Index: src/main/webapp/help/validTransactionTypes.html
===================================================================
--- src/main/webapp/help/validTransactionTypes.html Mon Jul 27 17:54:50 CEST 2009
+++ src/main/webapp/help/validTransactionTypes.html Mon Jul 27 17:54:50 CEST 2009
@@ -0,0 +1,27 @@
+
+
WARNING: By changing the valid types of transactions you can miss vital changes made to your source code.
+
+ By default, the AccuRev-plugin will allow any type of transaction to trigger a build.
+ This behaviour is not always wanted, resulting in issue-triggered builds.
+
+ To solve this you specify the types of transactions that you want to use.
+ You enter the transaction types separated by semicolons like this
+ add;chstream;co;defcomp;defunct;keep;mkstream;move;promote;purge
+ The types you are able to choose are the AccuRev transaction types,
+
+ add -
+ chstream -
+ co -
+ defcomp -
+ defunct -
+ dispatch -
+ keep -
+ mkstream -
+ move -
+ promote -
+ purge -
+
+
+
+
+
\ No newline at end of file
Index: src/main/java/hudson/plugins/accurev/AccurevSCM.java
===================================================================
--- src/main/java/hudson/plugins/accurev/AccurevSCM.java (revision 20179)
+++ src/main/java/hudson/plugins/accurev/AccurevSCM.java Wed Jul 29 17:57:25 CEST 2009
@@ -1,41 +1,9 @@
package hudson.plugins.accurev;
-import java.io.BufferedOutputStream;
-import java.io.BufferedReader;
-import java.io.File;
-import java.io.FileOutputStream;
-import java.io.FileReader;
-import java.io.IOException;
-import java.io.InputStream;
-import java.io.OutputStream;
-import java.io.Serializable;
-import java.io.StringReader;
-import java.io.ObjectStreamException;
-import java.net.InetAddress;
-import java.net.UnknownHostException;
-import java.text.SimpleDateFormat;
-import java.util.ArrayList;
-import java.util.Calendar;
-import java.util.Date;
-import java.util.HashMap;
-import java.util.List;
-import java.util.Map;
-import java.util.Arrays;
-import java.util.concurrent.locks.Lock;
-import java.util.concurrent.locks.ReentrantLock;
-import java.util.logging.Logger;
-
import hudson.FilePath;
import hudson.Launcher;
import hudson.Util;
-import hudson.model.AbstractBuild;
-import hudson.model.AbstractProject;
-import hudson.model.BuildListener;
-import hudson.model.ModelObject;
-import hudson.model.Result;
-import hudson.model.Run;
-import hudson.model.TaskListener;
-import hudson.model.Descriptor;
+import hudson.model.*;
import hudson.plugins.jetty.security.Password;
import hudson.remoting.Callable;
import hudson.remoting.VirtualChannel;
@@ -45,6 +13,7 @@
import hudson.scm.SCMDescriptor;
import hudson.util.ArgumentListBuilder;
import hudson.util.IOException2;
+import net.sf.json.JSONObject;
import org.codehaus.plexus.util.StringOutputStream;
import org.kohsuke.stapler.DataBoundConstructor;
import org.kohsuke.stapler.StaplerRequest;
@@ -52,8 +21,16 @@
import org.xmlpull.v1.XmlPullParser;
import org.xmlpull.v1.XmlPullParserException;
import org.xmlpull.v1.XmlPullParserFactory;
-import net.sf.json.JSONObject;
+import java.io.*;
+import java.net.InetAddress;
+import java.net.UnknownHostException;
+import java.text.SimpleDateFormat;
+import java.util.*;
+import java.util.concurrent.locks.Lock;
+import java.util.concurrent.locks.ReentrantLock;
+import java.util.logging.Logger;
+
/**
* Created by IntelliJ IDEA.
*
@@ -77,7 +54,7 @@
private final boolean synctime;
private final String workspace;
private final String workspaceSubPath;
-
+ private static String notificationTransactionTypes;
// --------------------------- CONSTRUCTORS ---------------------------
/**
@@ -177,6 +154,22 @@
return useWorkspace;
}
+ /**
+ *
+ * @return what types of transactions should render a notification to the author if the build fails
+ */
+ public static String getNotificationTransactionTypes() {
+ return notificationTransactionTypes;
+ }
+
+ /**
+ *
+ * @param notifTransactionTypes what types of transactions should render a notification to the author if the build fails
+ */
+ public static void setNotificationTransactionTypes(String notifTransactionTypes) {
+ notificationTransactionTypes = notifTransactionTypes;
+ }
+
// ------------------------ INTERFACE METHODS ------------------------
// --------------------- Interface Describable ---------------------
@@ -532,7 +525,8 @@
* {@inheritDoc}
*/
public ChangeLogParser createChangeLogParser() {
- return new AccurevChangeLogParser();
+ //include notifyTransactionTypes so that notification-filtering works
+ return new AccurevChangeLogParser(getNotificationTransactionTypes());
}
/**
@@ -734,6 +728,20 @@
}
}
+ /**
+ *
+ * @param server
+ * @param accurevEnv
+ * @param workspace
+ * @param listener
+ * @param accurevPath
+ * @param launcher
+ * @param stream
+ * @param buildDate
+ * @return if there are any new transactions in the stream since the last build was done
+ * @throws IOException
+ * @throws InterruptedException
+ */
private boolean checkStreamForChanges(AccurevServer server,
Map accurevEnv,
FilePath workspace,
@@ -743,80 +751,105 @@
String stream,
Date buildDate)
throws IOException, InterruptedException {
+ AccurevTransaction latestCodeChangeTransaction = new AccurevTransaction();
+ latestCodeChangeTransaction.setDate(new Date(0));
+
+ //query AccuRev for the latest transactions of each kind defined in transactionTypes using getTimeOfLatestTransaction
+ for (String transactionType : server.getValidTransactionTypes().split(";")) {
+ AccurevTransaction tempTransaction;
+
+ try {
+ tempTransaction = getLatestTransaction(server, accurevEnv, workspace, listener, accurevPath, launcher, stream, transactionType);
+ if (latestCodeChangeTransaction.getDate().before(tempTransaction.getDate())) {
+ latestCodeChangeTransaction = tempTransaction;
+ }
+ }
+ catch(NullPointerException e){
+ listener.getLogger().println("There is no transactions of the type " + transactionType + " in the stream " + stream);
+ }
+ catch(Exception e) {
+ listener.getLogger().println("getTimeOfLatestTransaction failed when checking the stream " + stream + " for changes with transaction type " + transactionType);
+ e.printStackTrace(listener.getLogger());
+ logger.warning(e.getMessage());
+ }
+ }
+
+ //log transaction-information
+ listener.getLogger().println("Last change on " + latestCodeChangeTransaction.getDate());
+ listener.getLogger().println("#" + latestCodeChangeTransaction.getId() + " " + latestCodeChangeTransaction.getAuthor() + " " + latestCodeChangeTransaction.getAction());
+ if(latestCodeChangeTransaction.getMsg() != null ) {
+ listener.getLogger().println(latestCodeChangeTransaction.getMsg());
+ }
+
+ return buildDate == null || buildDate.before(latestCodeChangeTransaction.getDate());
+ }
+
+ /**
+ *
+ *
+ * @param server
+ * @param accurevEnv
+ * @param workspace
+ * @param listener
+ * @param accurevPath
+ * @param launcher
+ * @param stream
+ * @param transactionType Specify what type of transaction to search for
+ * @return the latest transaction of the specified type from the selected stream
+ * @throws Exception
+ */
+ private AccurevTransaction getLatestTransaction(AccurevServer server,
+ Map accurevEnv,
+ FilePath workspace,
+ TaskListener listener,
+ String accurevPath,
+ Launcher launcher,
+ String stream,
+ String transactionType)
+ throws Exception {
+ //initialize code that extracts the latest transaction of a certain type using -k flag
- ArgumentListBuilder cmd = new ArgumentListBuilder();
- cmd.add(accurevPath);
- cmd.add("hist");
- addServer(cmd, server);
- cmd.add("-fx");
- cmd.add("-p");
- cmd.add(depot);
- cmd.add("-s");
- cmd.add(stream);
- cmd.add("-t");
- cmd.add("now.1");
+ ArgumentListBuilder cmd = new ArgumentListBuilder();
+ cmd.add(accurevPath);
+ cmd.add("hist");
+ addServer(cmd, server);
+ cmd.add("-fx");
+ cmd.add("-p");
+ cmd.add(depot);
+ cmd.add("-s");
+ cmd.add(stream);
+ cmd.add("-t");
+ cmd.add("now.1");
+ cmd.add("-k");
+ cmd.add(transactionType);
- StringOutputStream sos = new StringOutputStream();
+ StringOutputStream sos = new StringOutputStream();
- int rv;
- if (0 != (rv = launchAccurev(launcher, cmd, accurevEnv, null, sos, workspace))) {
- listener.fatalError("History command failed with exit code " + rv);
- return false;
+
+ //execute code that extracts the latest transaction
+ int rv = launchAccurev(launcher, cmd, accurevEnv, null, sos, workspace);
+ if (0 != rv) {
+ throw new Exception("History command failed with exit code " + rv + " when trying to get the latest transaction of type " + transactionType);
- }
+ }
- try {
+ //parse the result from the transaction-query
XmlPullParser parser = newPullParser();
parser.setInput(new StringReader(sos.toString()));
- while (true) {
- int event = parser.next();
- if (event == XmlPullParser.END_DOCUMENT) {
- // we've got to the end with no transaction tags,
- // therefore no changes in this stream
- return false;
- }
- if (event != XmlPullParser.START_TAG) {
- continue;
- }
- if (!"transaction".equalsIgnoreCase(parser.getName())) {
- continue;
- }
- break;
- }
- String transactionId = parser.getAttributeValue("", "id");
- String transactionType = parser.getAttributeValue("", "type");
- String transactionTime = parser.getAttributeValue("", "time");
- String transactionUser = parser.getAttributeValue("", "user");
- Date transactionDate = convertAccurevTimestamp(transactionTime);
- listener.getLogger().println("Last change on " + transactionDate);
- listener.getLogger().println("#" + transactionId + " " + transactionUser + " " + transactionType);
- String transactionComment = null;
- boolean inComment = false;
- while (transactionComment == null) {
- switch (parser.next()) {
- case XmlPullParser.START_TAG:
- inComment = "comment".equalsIgnoreCase(parser.getName());
- break;
- case XmlPullParser.END_TAG:
- inComment = false;
- break;
- case XmlPullParser.TEXT:
- if (inComment) {
- transactionComment = parser.getText();
+ AccurevTransaction resultTransaction = new AccurevTransaction();
+ while (parser.next() != XmlPullParser.END_DOCUMENT) {
+ if (parser.getEventType() == XmlPullParser.START_TAG) {
+ if(parser.getName().equalsIgnoreCase("transaction")) {
+ //parse transaction-values
+ resultTransaction.setId( ( Integer.parseInt( parser.getAttributeValue("", "id"))));
+ resultTransaction.setAction( parser.getAttributeValue("","type"));
+ resultTransaction.setDate( convertAccurevTimestamp(parser.getAttributeValue("", "time")));
+ resultTransaction.setUser( parser.getAttributeValue("", "user"));
+ } else if (parser.getName().equalsIgnoreCase("comment")) {
+ //parse comments
+ resultTransaction.setMsg(parser.nextText());
- }
+ }
- break;
- case XmlPullParser.END_DOCUMENT:
- transactionComment = "";
- default:
}
}
- listener.getLogger().println(transactionComment);
-
- return buildDate == null || buildDate.compareTo(transactionDate) < 0;
- } catch (XmlPullParserException e) {
- e.printStackTrace(listener.getLogger());
- logger.warning(e.getMessage());
- return false;
+ return resultTransaction;
- }
+ }
- }
-
/**
* Helper method to retrieve include/exclude rules for a given stream.
*
@@ -1071,7 +1104,7 @@
private String password;
private transient List winCmdLocations;
private transient List nixCmdLocations;
-
+ private String validTransactionTypes;
/**
* The default search paths for Windows clients.
*/
@@ -1097,7 +1130,7 @@
}
@DataBoundConstructor
- public AccurevServer(String name, String host, int port, String username, String password) {
+ public AccurevServer(String name, String host, int port, String username, String password, String validTransactionTypes) {
this.name = name;
this.host = host;
this.port = port;
@@ -1105,6 +1138,8 @@
this.password = Password.obfuscate(password);
winCmdLocations = new ArrayList(DEFAULT_WIN_CMD_LOCATIONS);
nixCmdLocations = new ArrayList(DEFAULT_NIX_CMD_LOCATIONS);
+ this.validTransactionTypes = validTransactionTypes;
+ setNotificationTransactionTypes(validTransactionTypes);
}
/**
@@ -1186,8 +1221,23 @@
return winCmdLocations.toArray(new String[winCmdLocations.size()]);
}
+ /**
+ *
+ * @return returns the currently set transaction types that are seen as valid for triggering builds and whos authors get notified when a build fails
+ */
+ public String getValidTransactionTypes() {
+ return validTransactionTypes;
- }
+ }
+ /**
+ *
+ * @param validTransactionTypes the currently set transaction types that are seen as valid for triggering builds and whos authors get notified when a build fails
+ */
+ public void setValidTransactionTypes(String validTransactionTypes) {
+ this.validTransactionTypes = validTransactionTypes;
+ }
+ }
+
private static final class PurgeWorkspaceContents implements FilePath.FileCallable {
private final TaskListener listener;
@@ -1243,6 +1293,14 @@
private static final class AccurevChangeLogParser extends ChangeLogParser {
+ private String notificationTransactionTypes;
+
+ public AccurevChangeLogParser(){}
+
+ public AccurevChangeLogParser(String notifTransactionTypes){
+ notificationTransactionTypes = notifTransactionTypes;
+ }
+
/**
* {@inheritDoc}
*/
@@ -1292,9 +1350,14 @@
currentTransaction = new AccurevTransaction();
transactions.add(currentTransaction);
currentTransaction.setRevision(parser.getAttributeValue("", "id"));
- currentTransaction.setUser(parser.getAttributeValue("", "user"));
currentTransaction.setDate(convertAccurevTimestamp(parser.getAttributeValue("", "time")));
currentTransaction.setAction(parser.getAttributeValue("", "type"));
+ currentTransaction.setUser(" ");
+ for (String transactionType : notificationTransactionTypes.split(";")) {
+ if (currentTransaction.getAction().equalsIgnoreCase(transactionType)) {
+ currentTransaction.setUser(parser.getAttributeValue("", "user"));
+ }
+ }
} else if ("version".equalsIgnoreCase(tagName) && currentTransaction != null) {
String path = parser.getAttributeValue("", "path");
if (path != null) {
Index: src/main/java/hudson/plugins/accurev/AccurevTransaction.java
===================================================================
--- src/main/java/hudson/plugins/accurev/AccurevTransaction.java (revision 20179)
+++ src/main/java/hudson/plugins/accurev/AccurevTransaction.java Mon Jul 27 13:56:04 CEST 2009
@@ -19,6 +19,7 @@
private String msg;
private String action;
private List affectedPaths = new ArrayList();
+ private int id;
public String getRevision() {
return revision;
@@ -96,4 +97,29 @@
public void addAffectedPath(String path) {
affectedPaths.add(path);
}
+ /**
+ * Getter for action
+ * Enables accurate filtering by AccuRev transaction type since the metod getEditType censors the actual type.
+ * @return transaction type of the AccuRev transaction
+ */
+ public String getAction() {
+ return action;
-}
+ }
+
+ /**
+ * Getter for id
+ * Enables logging with AccuRev transaction id
+ * @return transaction id of the AccuRev transaction
+ */
+ public int getId() {
+ return id;
+ }
+
+ /**
+ * Setter for id
+ * @param id transaction id of the AccuRev transaction
+ */
+ public void setId(int id) {
+ this.id = id;
+ }
+}