Diff
Modified: trunk/hudson/plugins/subversion/pom.xml (40556 => 40557)
--- trunk/hudson/plugins/subversion/pom.xml 2012-05-07 17:42:18 UTC (rev 40556)
+++ trunk/hudson/plugins/subversion/pom.xml 2012-05-07 20:29:34 UTC (rev 40557)
@@ -101,7 +101,7 @@
<dependency>
<groupId>org.jenkins-ci.svnkit</groupId>
<artifactId>svnkit</artifactId>
- <version>1.3.6.1-jenkins-2</version>
+ <version>1.7.4-jenkins-1</version>
</dependency>
<dependency>
@@ -123,6 +123,12 @@
</exclusion>
</exclusions>
</dependency>
+ <dependency>
+ <groupId>junit</groupId>
+ <artifactId>junit</artifactId>
+ <version>4.9</version>
+ <scope>test</scope>
+ </dependency>
</dependencies>
<pluginRepositories>
Modified: trunk/hudson/plugins/subversion/src/main/java/hudson/scm/SubversionChangeLogBuilder.java (40556 => 40557)
--- trunk/hudson/plugins/subversion/src/main/java/hudson/scm/SubversionChangeLogBuilder.java 2012-05-07 17:42:18 UTC (rev 40556)
+++ trunk/hudson/plugins/subversion/src/main/java/hudson/scm/SubversionChangeLogBuilder.java 2012-05-07 20:29:34 UTC (rev 40557)
@@ -216,7 +216,7 @@
}
public String invoke(File p, VirtualChannel channel) throws IOException {
- final SVNClientManager manager = SubversionSCM.createSvnClientManager(authProvider);
+ final SvnClientManager manager = SubversionSCM.createClientManager(authProvider);
try {
final SVNWCClient svnwc = manager.getWCClient();
Modified: trunk/hudson/plugins/subversion/src/main/java/hudson/scm/SubversionSCM.java (40556 => 40557)
--- trunk/hudson/plugins/subversion/src/main/java/hudson/scm/SubversionSCM.java 2012-05-07 17:42:18 UTC (rev 40556)
+++ trunk/hudson/plugins/subversion/src/main/java/hudson/scm/SubversionSCM.java 2012-05-07 20:29:34 UTC (rev 40557)
@@ -763,7 +763,8 @@
}
public List<External> invoke(File ws, VirtualChannel channel) throws IOException {
- manager = createSvnClientManager(authProvider);
+ clientManager = createClientManager(authProvider);
+ manager = clientManager.getCore();
this.ws = ws;
try {
List<External> externals = perform();
@@ -775,7 +776,7 @@
} catch (InterruptedException e) {
throw (InterruptedIOException)new InterruptedIOException().initCause(e);
} finally {
- manager.dispose();
+ clientManager.dispose();
}
}
@@ -790,7 +791,7 @@
private void checkClockOutOfSync() {
try {
- SVNDirEntry dir = manager.createRepository(location.getSVNURL(), true).info("/", -1);
+ SVNDirEntry dir = clientManager.createRepository(location.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.
{
@@ -809,6 +810,15 @@
}
/**
+ *
+ * @deprecated as of 1.40
+ * Use {@link #createClientManager(ISVNAuthenticationProvider)}
+ */
+ public static SVNClientManager createSvnClientManager(ISVNAuthenticationProvider authProvider) {
+ return createClientManager(authProvider).getCore();
+ }
+
+ /**
* Creates {@link SVNClientManager}.
*
* <p>
@@ -819,10 +829,10 @@
* If the operation runs on slaves,
* (and properly remoted, if the svn operations run on slaves.)
*/
- public static SVNClientManager createSvnClientManager(ISVNAuthenticationProvider authProvider) {
+ public static SvnClientManager createClientManager(ISVNAuthenticationProvider authProvider) {
SubversionWorkspaceSelector.syncWorkspaceFormatFromMaster();
ISVNAuthenticationManager sam = createSvnAuthenticationManager(authProvider);
- return SVNClientManager.newInstance(createDefaultSVNOptions(), sam);
+ return new SvnClientManager(SVNClientManager.newInstance(createDefaultSVNOptions(), sam));
}
/**
@@ -853,14 +863,23 @@
}
/**
+ * @deprecated as of 2.0
+ * Use {@link #createClientManager(AbstractProject)}
+ *
+ */
+ public static SVNClientManager createSvnClientManager(AbstractProject context) {
+ return createClientManager(context).getCore();
+ }
+
+ /**
* Creates {@link SVNClientManager} for code running on the master.
* <p>
* CAUTION: this code only works when invoked on master. On slaves, use
* {@link #createSvnClientManager(ISVNAuthenticationProvider)} and get {@link ISVNAuthenticationProvider}
- * from the master via remoting.
+ * from the master via remoting.
*/
- public static SVNClientManager createSvnClientManager(AbstractProject context) {
- return createSvnClientManager(Hudson.getInstance().getDescriptorByType(DescriptorImpl.class).createAuthenticationProvider(context));
+ public static SvnClientManager createClientManager(AbstractProject context) {
+ return new SvnClientManager(createSvnClientManager(Hudson.getInstance().getDescriptorByType(DescriptorImpl.class).createAuthenticationProvider(context)));
}
public static final class SvnInfo implements Serializable, Comparable<SvnInfo> {
@@ -990,7 +1009,7 @@
* The target to run "svn info".
*/
private static SVNInfo parseSvnInfo(SVNURL remoteUrl, ISVNAuthenticationProvider authProvider) throws SVNException {
- final SVNClientManager manager = createSvnClientManager(authProvider);
+ final SvnClientManager manager = createClientManager(authProvider);
try {
final SVNWCClient svnWc = manager.getWCClient();
return svnWc.doInfo(remoteUrl, SVNRevision.HEAD, SVNRevision.HEAD);
@@ -1022,7 +1041,7 @@
public List<SvnInfoP> invoke(File ws, VirtualChannel channel) throws IOException {
List<SvnInfoP> revisions = new ArrayList<SvnInfoP>();
- final SVNClientManager manager = createSvnClientManager(authProvider);
+ final SvnClientManager manager = createClientManager(authProvider);
try {
final SVNWCClient svnWc = manager.getWCClient();
// invoke the "svn info"
@@ -1223,7 +1242,7 @@
// if no exclusion rules are defined, don't waste time going through "svn log".
if (!hasExclusionRule()) return true;
- final SVNClientManager manager = createSvnClientManager(authProvider);
+ final SvnClientManager manager = createClientManager(authProvider);
try {
manager.getLogClient().doLog(url, null, SVNRevision.UNDEFINED,
SVNRevision.create(from), // get log entries from the local revision + 1
Modified: trunk/hudson/plugins/subversion/src/main/java/hudson/scm/SubversionTagAction.java (40556 => 40557)
--- trunk/hudson/plugins/subversion/src/main/java/hudson/scm/SubversionTagAction.java 2012-05-07 17:42:18 UTC (rev 40556)
+++ trunk/hudson/plugins/subversion/src/main/java/hudson/scm/SubversionTagAction.java 2012-05-07 20:29:34 UTC (rev 40557)
@@ -243,9 +243,9 @@
@Override
protected void perform(TaskListener listener) {
try {
- final SVNClientManager cm = upc!=null
- ? SVNClientManager.newInstance(SubversionSCM.createDefaultSVNOptions(),upc.new AuthenticationManagerImpl(listener))
- : SubversionSCM.createSvnClientManager(getBuild().getProject());
+ final SvnClientManager cm = upc!=null
+ ? new SvnClientManager(SVNClientManager.newInstance(SubversionSCM.createDefaultSVNOptions(),upc.new AuthenticationManagerImpl(listener)))
+ : SubversionSCM.createClientManager(getBuild().getProject());
try {
for (Entry<SvnInfo, String> e : tagSet.entrySet()) {
PrintStream logger = listener.getLogger();
Modified: trunk/hudson/plugins/subversion/src/main/java/hudson/scm/SubversionWorkspaceSelector.java (40556 => 40557)
--- trunk/hudson/plugins/subversion/src/main/java/hudson/scm/SubversionWorkspaceSelector.java 2012-05-07 17:42:18 UTC (rev 40556)
+++ trunk/hudson/plugins/subversion/src/main/java/hudson/scm/SubversionWorkspaceSelector.java 2012-05-07 20:29:34 UTC (rev 40557)
@@ -30,6 +30,7 @@
import org.tmatesoft.svn.core.internal.wc.admin.ISVNAdminAreaFactorySelector;
import org.tmatesoft.svn.core.internal.wc.admin.SVNAdminArea14;
import org.tmatesoft.svn.core.internal.wc.admin.SVNAdminAreaFactory;
+import org.tmatesoft.svn.core.internal.wc2.SvnWcGeneration;
import java.io.File;
import java.io.IOException;
@@ -52,7 +53,14 @@
* The primary scenario of this is the use of command-line SVN client, either from shell
* script, Ant, or Maven.
*
+ * <p>
+ * Working copy changes from Subversion 1.6 to 1.7 was so big that they introduced a separate
+ * {@link SvnWcGeneration} constant to represent that. So this class alone is no longer sufficient
+ * to make SVNKit sticks to the version we want it to use. See {@link SvnClientManager} that
+ * controls the other half of this.
+ *
* @author Kohsuke Kawaguchi
+ * @see SvnClientManager
*/
public class SubversionWorkspaceSelector implements ISVNAdminAreaFactorySelector {
public SubversionWorkspaceSelector() {
@@ -78,6 +86,11 @@
* {@link #getEnabledFactories(File, Collection, boolean)} method is called quite a few times
* during a Subversion operation, so consulting this value back with master each time is not practical
* performance wise. Therefore, we have {@link SubversionSCM} set this value, even though it's error prone.
+ *
+ * <p>
+ * Internally in SVNKit, these constants go up only to 1.6. We use {@link #WC_FORMAT_17} to indicate
+ * 1.7 (but when that value is chosen, it is really {@link SvnClientManager} that does the work, not
+ * {@link ISVNAdminAreaFactorySelector}).
*/
public static volatile int workspaceFormat = SVNAdminArea14.WC_FORMAT;
@@ -104,5 +117,10 @@
}
}
+ /**
+ * Constant for {@link #workspaceFormat} that indicates we opt for 1.7 working copy.
+ */
+ public static final int WC_FORMAT_17 = 100;
+
private static final Logger LOGGER = Logger.getLogger(SubversionWorkspaceSelector.class.getName());
}
Added: trunk/hudson/plugins/subversion/src/main/java/hudson/scm/SvnClientManager.java (0 => 40557)
--- trunk/hudson/plugins/subversion/src/main/java/hudson/scm/SvnClientManager.java (rev 0)
+++ trunk/hudson/plugins/subversion/src/main/java/hudson/scm/SvnClientManager.java 2012-05-07 20:29:34 UTC (rev 40557)
@@ -0,0 +1,72 @@
+package hudson.scm;
+
+import org.tmatesoft.svn.core.SVNException;
+import org.tmatesoft.svn.core.SVNURL;
+import org.tmatesoft.svn.core.internal.wc2.SvnWcGeneration;
+import org.tmatesoft.svn.core.io.SVNRepository;
+import org.tmatesoft.svn.core.wc.SVNBasicClient;
+import org.tmatesoft.svn.core.wc.SVNClientManager;
+import org.tmatesoft.svn.core.wc.SVNCommitClient;
+import org.tmatesoft.svn.core.wc.SVNCopyClient;
+import org.tmatesoft.svn.core.wc.SVNLogClient;
+import org.tmatesoft.svn.core.wc.SVNStatusClient;
+import org.tmatesoft.svn.core.wc.SVNUpdateClient;
+import org.tmatesoft.svn.core.wc.SVNWCClient;
+
+/**
+ * {@link SVNClientManager} makes it rather error prone to specify the proper expected version
+ * of the working copy we need to use, so inside Jenkins we wrap it to this class to ensure
+ * we won't forget to set {@link SvnWcGeneration} when using {@link SVNBasicClient}.
+ *
+ * @author Kohsuke Kawaguchi
+ */
+public class SvnClientManager {
+ private final SVNClientManager core;
+ private final SvnWcGeneration wcgen;
+
+ public SvnClientManager(SVNClientManager core) {
+ this.core = core;
+ wcgen = SubversionWorkspaceSelector.workspaceFormat>=SubversionWorkspaceSelector.WC_FORMAT_17 ? SvnWcGeneration.V17 : SvnWcGeneration.V16;
+ }
+
+ public SVNClientManager getCore() {
+ return core;
+ }
+
+ public SVNWCClient getWCClient() {
+ return wrapUp(core.getWCClient());
+ }
+
+ public SVNLogClient getLogClient() {
+ return wrapUp(core.getLogClient());
+ }
+
+ private <T extends SVNBasicClient> T wrapUp(T client) {
+ client.getOperationsFactory().setPrimaryWcGeneration(wcgen);
+ return client;
+ }
+
+ public void dispose() {
+ core.dispose();
+ }
+
+ public SVNCommitClient getCommitClient() {
+ return wrapUp(core.getCommitClient());
+ }
+
+ public SVNStatusClient getStatusClient() {
+ return wrapUp(core.getStatusClient());
+ }
+
+ public SVNCopyClient getCopyClient() {
+ return wrapUp(core.getCopyClient());
+ }
+
+ public SVNUpdateClient getUpdateClient() {
+ return wrapUp(core.getUpdateClient());
+ }
+
+ public SVNRepository createRepository(SVNURL url, boolean mayReuse) throws SVNException {
+ return core.createRepository(url,mayReuse);
+ }
+}
Modified: trunk/hudson/plugins/subversion/src/main/java/hudson/scm/subversion/CheckoutUpdater.java (40556 => 40557)
--- trunk/hudson/plugins/subversion/src/main/java/hudson/scm/subversion/CheckoutUpdater.java 2012-05-07 17:42:18 UTC (rev 40556)
+++ trunk/hudson/plugins/subversion/src/main/java/hudson/scm/subversion/CheckoutUpdater.java 2012-05-07 20:29:34 UTC (rev 40557)
@@ -35,6 +35,7 @@
import org.tmatesoft.svn.core.SVNCancelException;
import org.tmatesoft.svn.core.SVNDepth;
import org.tmatesoft.svn.core.SVNException;
+import org.tmatesoft.svn.core.internal.wc2.SvnWcGeneration;
import org.tmatesoft.svn.core.wc.SVNRevision;
import org.tmatesoft.svn.core.wc.SVNUpdateClient;
@@ -64,7 +65,8 @@
@Override
public List<External> perform() throws IOException, InterruptedException {
- final SVNUpdateClient svnuc = manager.getUpdateClient();
+ final SVNUpdateClient svnuc = clientManager.getUpdateClient();
+ svnuc.getOperationsFactory().setPrimaryWcGeneration(SvnWcGeneration.V16);
final List<External> externals = new ArrayList<External>(); // store discovered externals to here
listener.getLogger().println("Cleaning local Directory " + location.getLocalDir());
Modified: trunk/hudson/plugins/subversion/src/main/java/hudson/scm/subversion/UpdateUpdater.java (40556 => 40557)
--- trunk/hudson/plugins/subversion/src/main/java/hudson/scm/subversion/UpdateUpdater.java 2012-05-07 17:42:18 UTC (rev 40556)
+++ trunk/hudson/plugins/subversion/src/main/java/hudson/scm/subversion/UpdateUpdater.java 2012-05-07 20:29:34 UTC (rev 40557)
@@ -111,7 +111,7 @@
* The target to run "svn info".
*/
private SVNInfo parseSvnInfo(File workspace) throws SVNException {
- final SVNWCClient svnWc = manager.getWCClient();
+ final SVNWCClient svnWc = clientManager.getWCClient();
return svnWc.doInfo(workspace,SVNRevision.WORKING);
}
@@ -122,7 +122,7 @@
}
- final SVNUpdateClient svnuc = manager.getUpdateClient();
+ final SVNUpdateClient svnuc = clientManager.getUpdateClient();
final List<External> externals = new ArrayList<External>(); // store discovered externals to here
try {
Modified: trunk/hudson/plugins/subversion/src/main/java/hudson/scm/subversion/UpdateWithCleanUpdater.java (40556 => 40557)
--- trunk/hudson/plugins/subversion/src/main/java/hudson/scm/subversion/UpdateWithCleanUpdater.java 2012-05-07 17:42:18 UTC (rev 40556)
+++ trunk/hudson/plugins/subversion/src/main/java/hudson/scm/subversion/UpdateWithCleanUpdater.java 2012-05-07 20:29:34 UTC (rev 40557)
@@ -63,7 +63,7 @@
protected void preUpdate(ModuleLocation module, File local) throws SVNException, IOException {
listener.getLogger().println("Cleaning up " + local);
- manager.getStatusClient().doStatus(local, null, SVNDepth.INFINITY, false, false, true, false, new ISVNStatusHandler() {
+ clientManager.getStatusClient().doStatus(local, null, SVNDepth.INFINITY, false, false, true, false, new ISVNStatusHandler() {
public void handleStatus(SVNStatus status) throws SVNException {
SVNStatusType s = status.getContentsStatus();
if (s == SVNStatusType.STATUS_UNVERSIONED || s == SVNStatusType.STATUS_IGNORED || s == SVNStatusType.STATUS_MODIFIED) {
Modified: trunk/hudson/plugins/subversion/src/main/java/hudson/scm/subversion/UpdateWithRevertUpdater.java (40556 => 40557)
--- trunk/hudson/plugins/subversion/src/main/java/hudson/scm/subversion/UpdateWithRevertUpdater.java 2012-05-07 17:42:18 UTC (rev 40556)
+++ trunk/hudson/plugins/subversion/src/main/java/hudson/scm/subversion/UpdateWithRevertUpdater.java 2012-05-07 20:29:34 UTC (rev 40557)
@@ -58,7 +58,7 @@
@Override
protected void preUpdate(ModuleLocation module, File local) throws SVNException, IOException {
listener.getLogger().println("Reverting " + local);
- manager.getWCClient().doRevert(new File[]{local.getCanonicalFile()}, SVNDepth.INFINITY, null);
+ clientManager.getWCClient().doRevert(new File[]{local.getCanonicalFile()}, SVNDepth.INFINITY, null);
}
}
Modified: trunk/hudson/plugins/subversion/src/main/java/hudson/scm/subversion/WorkspaceUpdater.java (40556 => 40557)
--- trunk/hudson/plugins/subversion/src/main/java/hudson/scm/subversion/WorkspaceUpdater.java 2012-05-07 17:42:18 UTC (rev 40556)
+++ trunk/hudson/plugins/subversion/src/main/java/hudson/scm/subversion/WorkspaceUpdater.java 2012-05-07 20:29:34 UTC (rev 40557)
@@ -31,6 +31,7 @@
import hudson.scm.SubversionSCM;
import hudson.scm.SubversionSCM.External;
import hudson.scm.SubversionSCM.ModuleLocation;
+import hudson.scm.SvnClientManager;
import org.kohsuke.stapler.export.ExportedBean;
import org.tmatesoft.svn.core.auth.ISVNAuthenticationProvider;
import org.tmatesoft.svn.core.wc.SVNClientManager;
@@ -78,11 +79,17 @@
// fields that are set by the caller as context for the perform method
/**
- * Factory for various subversion commands.
+ * @deprecated as of 1.40
+ * Use {@link #clientManager}
*/
public SVNClientManager manager;
/**
+ * Factory for various subversion commands.
+ */
+ public SvnClientManager clientManager;
+
+ /**
* Encapusulates the authentication. Connected back to Hudson master. Never null.
*/
public ISVNAuthenticationProvider authProvider;
@@ -126,6 +133,7 @@
protected List<External> delegateTo(UpdateTask t) throws IOException, InterruptedException {
t.manager = this.manager;
+ t.clientManager = this.clientManager;
t.authProvider = this.authProvider;
t.timestamp = this.timestamp;
t.listener = this.listener;
Modified: trunk/hudson/plugins/subversion/src/main/resources/hudson/scm/SubversionSCM/global.jelly (40556 => 40557)
--- trunk/hudson/plugins/subversion/src/main/resources/hudson/scm/SubversionSCM/global.jelly 2012-05-07 17:42:18 UTC (rev 40556)
+++ trunk/hudson/plugins/subversion/src/main/resources/hudson/scm/SubversionSCM/global.jelly 2012-05-07 20:29:34 UTC (rev 40557)
@@ -27,9 +27,10 @@
<f:section title="${%Subversion}">
<f:entry title="${%Subversion Workspace Version}" help="/descriptor/hudson.scm.SubversionSCM/help/workspaceFormat">
<select name="svn.workspaceFormat">
- <f:option value="8" selected="${descriptor.workspaceFormat==8}" >1.4</f:option>
- <f:option value="9" selected="${descriptor.workspaceFormat==9}" >1.5</f:option>
- <f:option value="10" selected="${descriptor.workspaceFormat==10}">1.6 (svn:externals to file)</f:option>
+ <f:option value="8" selected="${descriptor.workspaceFormat==8}" >1.4</f:option>
+ <f:option value="9" selected="${descriptor.workspaceFormat==9}" >1.5</f:option>
+ <f:option value="10" selected="${descriptor.workspaceFormat==10}" >1.6 (svn:externals to file)</f:option>
+ <f:option value="100" selected="${descriptor.workspaceFormat==100}">1.7</f:option>
</select>
</f:entry>
<f:entry title="${%Exclusion revprop name}" help="/descriptor/hudson.scm.SubversionSCM/help/excludedRevprop">
Modified: trunk/hudson/plugins/subversion/src/test/java/hudson/scm/SubversionSCMTest.java (40556 => 40557)
--- trunk/hudson/plugins/subversion/src/test/java/hudson/scm/SubversionSCMTest.java 2012-05-07 17:42:18 UTC (rev 40556)
+++ trunk/hudson/plugins/subversion/src/test/java/hudson/scm/SubversionSCMTest.java 2012-05-07 20:29:34 UTC (rev 40557)
@@ -649,7 +649,7 @@
p.setScm(loadSvnRepo());
FreeStyleBuild b = p.scheduleBuild2(0).get();
- SVNClientManager wc = SubversionSCM.createSvnClientManager((AbstractProject)null);
+ SvnClientManager wc = SubversionSCM.createClientManager((AbstractProject)null);
SVNStatus st = wc.getStatusClient().doStatus(new File(b.getWorkspace().getRemote()+"/a"), false);
int wcf = st.getWorkingCopyFormat();
System.out.println(wcf);
@@ -797,7 +797,7 @@
forCommit.setScm(scm);
forCommit.setAssignedLabel(hudson.getSelfLabel());
FreeStyleBuild b = assertBuildStatusSuccess(forCommit.scheduleBuild2(0).get());
- SVNClientManager svnm = SubversionSCM.createSvnClientManager((AbstractProject)null);
+ SvnClientManager svnm = SubversionSCM.createClientManager((AbstractProject)null);
List<File> added = new ArrayList<File>();
for (String path : paths) {
@@ -833,7 +833,7 @@
FreeStyleBuild b = assertBuildStatusSuccess(forCommit.scheduleBuild2(0).get());
FilePath newFile = b.getWorkspace().child("foo");
newFile.touch(System.currentTimeMillis());
- SVNClientManager svnm = SubversionSCM.createSvnClientManager(p);
+ SvnClientManager svnm = SubversionSCM.createClientManager(p);
svnm.getWCClient().doAdd(new File(newFile.getRemote()),false,false,false, SVNDepth.INFINITY, false,false);
SVNCommitClient cc = svnm.getCommitClient();
cc.doCommit(new File[]{new File(newFile.getRemote())},false,"added",null,null,false,false,SVNDepth.INFINITY);