Plugin Information
This plugin allows you to set up a job in Hudson for building specific revisions of a project. Here is a screenshot of this project configured to use the plugin. Today it uses a copy of SubversionSCM named SubversionReleaseSCM, but would only require a small change to SubversionSCM.CheckOutTask to work with the core code.
Here is the change that is needed. Just look for the java comments that start with EDIT.
SubversionSCM.java CheckOutTask
/**
* Either run "svn co" or "svn up" equivalent.
*/
private static class CheckOutTask implements FileCallable<List<External>> {
private final ISVNAuthenticationProvider authProvider;
private final Date timestamp;
// true to "svn update", false to "svn checkout".
private boolean update;
private final TaskListener listener;
private final ModuleLocation[] locations;
//EDIT (1) next line added by piascikj for building specific revision
private String revision;
public CheckOutTask(AbstractBuild<?, ?> build, SubversionSCM parent, Date timestamp, boolean update, TaskListener listener) {
this.authProvider = parent.getDescriptor().createAuthenticationProvider();
this.timestamp = timestamp;
this.update = update;
this.listener = listener;
this.locations = parent.getLocations(build);
//EDIT (2) next line added by piascikj for building specific revision
this.revision = build.getEnvVars().get("REVISION");
}
public List<External> invoke(File ws, VirtualChannel channel) throws IOException {
final SVNClientManager manager = createSvnClientManager(authProvider);
try {
final SVNUpdateClient svnuc = manager.getUpdateClient();
final List<External> externals = new ArrayList<External>(); // store discovered externals to here
//EDIT next line removed by piascikj for building specific revision
//final SVNRevision revision = SVNRevision.create(timestamp);
//EDIT (3) next 6 lines added by piascikj for building specific revision
SVNRevision revision = SVNRevision.create(timestamp);
try {
if (this.revision != null) revision = SVNRevision.create(Long.parseLong(this.revision));
} catch (NumberFormatException e) {
listener.getLogger().println("Unable to parse revision number from value: " + this.revision + ", checking out HEAD revision.");
}
if(update) {
for (final ModuleLocation l : locations) {
try {
listener.getLogger().println("Updating "+ l.remote);
File local = new File(ws, l.local);
svnuc.setEventHandler(new SubversionUpdateEventHandler(listener.getLogger(), externals,local,l.local));
svnuc.doUpdate(local.getCanonicalFile(), l.getRevision(revision), true);
} catch (final SVNException e) {
if(e.getErrorMessage().getErrorCode()== SVNErrorCode.WC_LOCKED) {
// work space locked. try fresh check out
listener.getLogger().println("Workspace appear to be locked, so getting a fresh workspace");
update = false;
return invoke(ws,channel);
}
if(e.getErrorMessage().getErrorCode()== SVNErrorCode.WC_OBSTRUCTED_UPDATE) {
// HUDSON-1882. If existence of local files cause an update to fail,
// revert to fresh check out
listener.getLogger().println(e.getMessage()); // show why this happened. Sometimes this is caused by having a build artifact in the repository.
listener.getLogger().println("Updated failed due to local files. Getting a fresh workspace");
update = false;
return invoke(ws,channel);
}
e.printStackTrace(listener.error("Failed to update "+l.remote));
// trouble-shooting probe for #591
if(e.getErrorMessage().getErrorCode()== SVNErrorCode.WC_NOT_LOCKED) {
listener.getLogger().println("Polled jobs are "+ Hudson.getInstance().getDescriptorByType(SCMTrigger.DescriptorImpl.class).getItemsBeingPolled());
}
return null;
}
}
} else {
Util.deleteContentsRecursive(ws);
// buffer the output by a separate thread so that the update operation
// won't be blocked by the remoting of the data
PipedOutputStream pos = new PipedOutputStream();
StreamCopyThread sct = new StreamCopyThread("svn log copier", new PipedInputStream(pos), listener.getLogger());
sct.start();
for (final ModuleLocation l : locations) {
try {
listener.getLogger().println("Checking out "+l.remote);
File local = new File(ws, l.local);
svnuc.setEventHandler(new SubversionUpdateEventHandler(new PrintStream(pos), externals, local, l.local));
svnuc.doCheckout(l.getSVNURL(), local.getCanonicalFile(), SVNRevision.HEAD, l.getRevision(revision), true);
} catch (SVNException e) {
e.printStackTrace(listener.error("Failed to check out "+l.remote));
return null;
}
}
pos.close();
try {
sct.join(); // wait for all data to be piped.
} catch (InterruptedException e) {
throw new IOException2("interrupted",e);
}
}
try {
for (final ModuleLocation l : locations) {
SVNDirEntry dir = manager.createRepository(l.getSVNURL(),true).info("/",-1);
if(dir!=null) {// I don't think this can ever be null, but be defensive
if(dir.getDate()!=null && dir.getDate().after(new Date())) // see http://www.nabble.com/NullPointerException-in-SVN-Checkout-Update-td21609781.html that reported this being null.
listener.getLogger().println(Messages.SubversionSCM_ClockOutOfSync());
}
}
} catch (SVNException e) {
LOGGER.log(Level.INFO,"Failed to estimate the remote time stamp",e);
}
return externals;
} finally {
manager.dispose();
}
}
private static final long serialVersionUID = 1L;
}
Change LogVersion 1.1 (2010-03-01)
Version 0.2 (2009-12-29)
Version 0.1 (2009-03-27)
|

Comments (5)
Jan 22, 2010
Jay Blanton says:
Can you explain if this revision is the Subversion revision or is this related t...Can you explain if this revision is the Subversion revision or is this related to a tag/branch in subversion?
I installed this plugin and don't see the releases link.
Is that because I need to make code changes suggested above?
Thanks...jay
Apr 23
John Carter says:
Note that the example screenshot has a typo - "Prodution" should be "Production"Note that the example screenshot has a typo - "Prodution" should be "Production"
Jun 19
Krishnan says:
Hi I am supposed to build a svn revision using subversion release manager. I ha...Hi
I am supposed to build a svn revision using subversion release manager. I have configured a build parameter for the revision number. I would like to set a default value so that SVN head is built when the revision number is not specified/changed. 'HEAD' does not seem to be working. I see the following error:
Location 'http://<mySVNLocation>/trunk@HEAD' does not exist.
any workarounds? Thanks.
Jun 28
Salman Awan says:
Hey Jesse, Great plug-in, worked a charm, thanks a lot as it resolved a pressing...Hey Jesse, Great plug-in, worked a charm, thanks a lot as it resolved a pressing issue on my part.
Just a question, when selecting 'Subversion Release' instead of 'Subversion' as SCM, two additional options that are available with 'Subversion' SCM are not available any more i.e. 'Use update' and 'Revert'.
Is that by design, or you might consider adding them in future?
Thanks again, Regards, Salman Awan
yesterday at 06:36 AM
Robert Redd says:
In addition to the issue mentioned by Salman above, I can also no longer browse ...In addition to the issue mentioned by Salman above, I can also no longer browse or see the diff in files modified when looking at the project's change history using the Repository Browser option. I use ViewSVN with the repository URL specified. It worked when the SCM was the original Subversion type, though.