提交 19f2300c 编写于 作者: K kohsuke

[FIXED HUDSON-262] Subversion checkout/update now supports fixed revisions. In Hudson 1.269.

git-svn-id: https://hudson.dev.java.net/svn/hudson/trunk/hudson/main@14076 71c3de6d-444a-0410-be80-ed276b4c234a
上级 73d1db26
...@@ -71,7 +71,7 @@ public final class SubversionChangeLogBuilder { ...@@ -71,7 +71,7 @@ public final class SubversionChangeLogBuilder {
logHandler.startDocument(); logHandler.startDocument();
for (ModuleLocation l : scm.getLocations(build)) { for (ModuleLocation l : scm.getLocations(build)) {
changelogFileCreated |= buildModule(l.remote, svnlc, logHandler); changelogFileCreated |= buildModule(l.getURL(), svnlc, logHandler);
} }
for(SubversionSCM.External ext : externals) { for(SubversionSCM.External ext : externals) {
changelogFileCreated |= buildModule( changelogFileCreated |= buildModule(
......
...@@ -87,7 +87,6 @@ import java.util.Collections; ...@@ -87,7 +87,6 @@ import java.util.Collections;
import java.util.Date; import java.util.Date;
import java.util.HashMap; import java.util.HashMap;
import java.util.Hashtable; import java.util.Hashtable;
import java.util.Iterator;
import java.util.List; import java.util.List;
import java.util.Map; import java.util.Map;
import java.util.Map.Entry; import java.util.Map.Entry;
...@@ -429,7 +428,7 @@ public class SubversionSCM extends SCM implements Serializable { ...@@ -429,7 +428,7 @@ public class SubversionSCM extends SCM implements Serializable {
File local = new File(ws, l.local); File local = new File(ws, l.local);
svnuc.setEventHandler(new SubversionUpdateEventHandler(listener.getLogger(), externals,local,l.local)); svnuc.setEventHandler(new SubversionUpdateEventHandler(listener.getLogger(), externals,local,l.local));
svnuc.doUpdate(local.getCanonicalFile(), revision, true); svnuc.doUpdate(local.getCanonicalFile(), l.getRevision(revision), true);
} catch (final SVNException e) { } catch (final SVNException e) {
if(e.getErrorMessage().getErrorCode()== SVNErrorCode.WC_LOCKED) { if(e.getErrorMessage().getErrorCode()== SVNErrorCode.WC_LOCKED) {
...@@ -465,12 +464,11 @@ public class SubversionSCM extends SCM implements Serializable { ...@@ -465,12 +464,11 @@ public class SubversionSCM extends SCM implements Serializable {
for (final ModuleLocation l : locations) { for (final ModuleLocation l : locations) {
try { try {
final SVNURL url = SVNURL.parseURIEncoded(l.remote); listener.getLogger().println("Checking out "+l.remote);
listener.getLogger().println("Checking out "+url);
File local = new File(ws, l.local); File local = new File(ws, l.local);
svnuc.setEventHandler(new SubversionUpdateEventHandler(new PrintStream(pos), externals, local, l.local)); svnuc.setEventHandler(new SubversionUpdateEventHandler(new PrintStream(pos), externals, local, l.local));
svnuc.doCheckout(url, local.getCanonicalFile(), SVNRevision.HEAD, revision, true); svnuc.doCheckout(l.getSVNURL(), local.getCanonicalFile(), SVNRevision.HEAD, l.getRevision(revision), true);
} catch (SVNException e) { } catch (SVNException e) {
e.printStackTrace(listener.error("Failed to check out "+l.remote)); e.printStackTrace(listener.error("Failed to check out "+l.remote));
return null; return null;
...@@ -487,8 +485,7 @@ public class SubversionSCM extends SCM implements Serializable { ...@@ -487,8 +485,7 @@ public class SubversionSCM extends SCM implements Serializable {
try { try {
for (final ModuleLocation l : locations) { for (final ModuleLocation l : locations) {
final SVNURL url = SVNURL.parseURIEncoded(l.remote); SVNDirEntry dir = manager.createRepository(l.getSVNURL(),true).info("/",-1);
SVNDirEntry dir = manager.createRepository(url,true).info("/",-1);
if(dir!=null) {// I don't think this can ever be null, but be defensive if(dir!=null) {// I don't think this can ever be null, but be defensive
if(dir.getDate().after(new Date())) if(dir.getDate().after(new Date()))
listener.getLogger().println(Messages.SubversionSCM_ClockOutOfSync()); listener.getLogger().println(Messages.SubversionSCM_ClockOutOfSync());
...@@ -740,7 +737,6 @@ public class SubversionSCM extends SCM implements Serializable { ...@@ -740,7 +737,6 @@ public class SubversionSCM extends SCM implements Serializable {
public Boolean invoke(File ws, VirtualChannel channel) throws IOException { public Boolean invoke(File ws, VirtualChannel channel) throws IOException {
for (ModuleLocation l : locations) { for (ModuleLocation l : locations) {
String url = l.remote;
String moduleName = l.local; String moduleName = l.local;
File module = new File(ws,moduleName).getCanonicalFile(); // canonicalize to remove ".." and ".". See #474 File module = new File(ws,moduleName).getCanonicalFile(); // canonicalize to remove ".." and ".". See #474
...@@ -753,6 +749,7 @@ public class SubversionSCM extends SCM implements Serializable { ...@@ -753,6 +749,7 @@ public class SubversionSCM extends SCM implements Serializable {
SVNInfo svnkitInfo = parseSvnInfo(module, authProvider); SVNInfo svnkitInfo = parseSvnInfo(module, authProvider);
SvnInfo svnInfo = new SvnInfo(svnkitInfo); SvnInfo svnInfo = new SvnInfo(svnkitInfo);
String url = l.getURL();
if(!svnInfo.url.equals(url)) { if(!svnInfo.url.equals(url)) {
listener.getLogger().println("Checking out a fresh workspace because the workspace is not "+url); listener.getLogger().println("Checking out a fresh workspace because the workspace is not "+url);
return false; return false;
...@@ -1407,8 +1404,7 @@ public class SubversionSCM extends SCM implements Serializable { ...@@ -1407,8 +1404,7 @@ public class SubversionSCM extends SCM implements Serializable {
PrintStream out = listener.getLogger(); PrintStream out = listener.getLogger();
for (ModuleLocation l : getLocations(build)) for (ModuleLocation l : getLocations(build))
if (getDescriptor().checkRepositoryPath( if (getDescriptor().checkRepositoryPath(l.getSVNURL()) == SVNNodeKind.NONE) {
SVNURL.parseURIDecoded(l.remote)) == SVNNodeKind.NONE) {
out.println("Location '" + l.remote + "' does not exist"); out.println("Location '" + l.remote + "' does not exist");
ParametersAction params = build ParametersAction params = build
...@@ -1465,7 +1461,16 @@ public class SubversionSCM extends SCM implements Serializable { ...@@ -1465,7 +1461,16 @@ public class SubversionSCM extends SCM implements Serializable {
* to make failure messages when doing a checkout possible * to make failure messages when doing a checkout possible
*/ */
public static final class ModuleLocation implements Serializable { public static final class ModuleLocation implements Serializable {
/**
* Subversion URL to check out.
*
* This may include "@NNN" at the end to indicate a fixed revision.
*/
public final String remote; public final String remote;
/**
* Local directory to place the file to.
* Relative to the workspace root.
*/
public final String local; public final String local;
public ModuleLocation(String remote, String local) { public ModuleLocation(String remote, String local) {
...@@ -1476,18 +1481,58 @@ public class SubversionSCM extends SCM implements Serializable { ...@@ -1476,18 +1481,58 @@ public class SubversionSCM extends SCM implements Serializable {
this.local = local.trim(); this.local = local.trim();
} }
public String toString() { /**
* Returns the pure URL portion of {@link #remote} by removing
* possible "@NNN" suffix.
*/
public String getURL() {
int idx = remote.lastIndexOf('@');
if(idx>0) {
try {
String n = remote.substring(idx+1);
Long.parseLong(n);
return remote.substring(0,idx);
} catch (NumberFormatException e) {
// not a revision number
}
}
return remote; return remote;
} }
private static final long serialVersionUID = 1L; /**
* Gets {@link #remote} as {@link SVNURL}.
*/
public SVNURL getSVNURL() throws SVNException {
return SVNURL.parseURIEncoded(getURL());
}
/**
* Figures out which revision to check out.
*
* If {@link #remote} is {@code url@rev}, then this method
* returns that specific revision.
*
* @param defaultValue
* If "@NNN" portion is not in the URL, this value will be returned.
* Normally, this is the SVN revision timestamped at the build date.
*/
public SVNRevision getRevision(SVNRevision defaultValue) {
int idx = remote.lastIndexOf('@');
if(idx>0) {
try {
String n = remote.substring(idx+1);
return SVNRevision.create(Long.parseLong(n));
} catch (NumberFormatException e) {
// not a revision number
}
}
return defaultValue;
}
private String getExpandedRemote(AbstractBuild<?, ?> build) { private String getExpandedRemote(AbstractBuild<?,?> build) {
String outRemote = remote; String outRemote = remote;
ParametersAction parameters = build ParametersAction parameters = build.getAction(ParametersAction.class);
.getAction(ParametersAction.class);
if (parameters != null) if (parameters != null)
outRemote = parameters.substitute(build, remote); outRemote = parameters.substitute(build, remote);
...@@ -1496,16 +1541,22 @@ public class SubversionSCM extends SCM implements Serializable { ...@@ -1496,16 +1541,22 @@ public class SubversionSCM extends SCM implements Serializable {
/** /**
* Expand location value based on Build parametric execution. * Expand location value based on Build parametric execution.
* *
* @param build * @param build
* Build instance for expanding parameters into their values * Build instance for expanding parameters into their values
* *
* @return Output ModuleLocation expanded according to Build parameters * @return Output ModuleLocation expanded according to Build parameters
* values. * values.
*/ */
public ModuleLocation getExpandedLocation(AbstractBuild<?, ?> build) { public ModuleLocation getExpandedLocation(AbstractBuild<?, ?> build) {
return new ModuleLocation(getExpandedRemote(build), local); return new ModuleLocation(getExpandedRemote(build), local);
} }
public String toString() {
return remote;
}
private static final long serialVersionUID = 1L;
} }
private static final Logger LOGGER = Logger.getLogger(SubversionSCM.class.getName()); private static final Logger LOGGER = Logger.getLogger(SubversionSCM.class.getName());
......
...@@ -2,6 +2,7 @@ ...@@ -2,6 +2,7 @@
<l:ajax> <l:ajax>
<div> <div>
${%description.1} ${%description.1}
${%description.explicitRevision}
<br/> <br/>
${%description.2(rootURL)} ${%description.2(rootURL)}
<br /> <br />
......
description.1=\ description.1=\
Specify the subversion repository URL to check out, such as "http://svn.apache.org/repos/asf/ant/". Specify the subversion repository URL to check out, such as "http://svn.apache.org/repos/asf/ant/".
description.explicitRevision=\
You can also add "@NNN" at the end of the URL to check out a specific revision number, if that's desirable.
description.2=\ description.2=\
When you enter URL, Hudson automatically checks if Hudson can connect to it. If access requires\ When you enter URL, Hudson automatically checks if Hudson can connect to it. If access requires \
authentication, it will ask you the necessary credential. If you already have a working\ authentication, it will ask you the necessary credential. If you already have a working \
credential but would like to change it for other reasons, \ credential but would like to change it for other reasons, \
click <a href="{0}//scm/SubversionSCM/enterCredential">this link</a> and specify different credential. click <a href="{0}//scm/SubversionSCM/enterCredential">this link</a> and specify different credential.
description.3=\ description.3=\
During the build, revision number of the module that was checked out is available\ During the build, revision number of the module that was checked out is available \
through the environment variable <tt>SVN_REVISION</tt> through the environment variable <tt>SVN_REVISION</tt>, provided that you are only checking out \
one module. If you have multiple modules checked out, use \
<a href='http://www.manpagez.com/man/1/svnversion/'>the svnversion command</a>.
# OUTDATED
description.1=\ description.1=\
Spécifiez l''URL du repository Subversion à lire, par exemple "http://svn.apache.org/repos/asf/ant/". Sp?cifiez l''URL du repository Subversion ? lire, par exemple "http://svn.apache.org/repos/asf/ant/".
description.2=\ description.2=\
Quand vous entrez une URL, Hudson vérifie automatiquement s''il peut s''y connecter. Si l''accès cessite \ Quand vous entrez une URL, Hudson v?rifie automatiquement s''il peut s''y connecter. Si l''acc?s n?cessite \
une authentification, il vous demandera les informations nécessaires. Si vous avez déjà des informations d''identification \ une authentification, il vous demandera les informations n?cessaires. Si vous avez d?j? des informations d''identification \
qui marchent mais vous voulez tout de même changer, cliquez sur <a href="{0}//scm/SubversionSCM/enterCredential">ce lien</a> \ qui marchent mais vous voulez tout de m?me changer, cliquez sur <a href="{0}//scm/SubversionSCM/enterCredential">ce lien</a> \
et indiquez des informations différentes. et indiquez des informations diff?rentes.
description.3=\ description.3=\
Au cours du build, le numéro de révision du module qui a été récupéré est disponible à travers la variable \ Au cours du build, le num?ro de r?vision du module qui a ?t? r?cup?r? est disponible ? travers la variable \
d''environnement <tt>SVN_REVISION</tt> d''environnement <tt>SVN_REVISION</tt>
# OUTDATED
description.1=\ description.1=\
\u30C1\u30A7\u30C3\u30AF\u30A2\u30A6\u30C8\u3059\u308BSubversion\u306E\u30EA\u30DD\u30B8\u30C8\u30EAURL\u3092\u3001"http://svn.apache.org/repos/asf/ant/"\u306E\u3088\u3046\u306B\u6307\u5B9A\u3057\u3066\u304F\u3060\u3055\u3044\u3002. \u30C1\u30A7\u30C3\u30AF\u30A2\u30A6\u30C8\u3059\u308BSubversion\u306E\u30EA\u30DD\u30B8\u30C8\u30EAURL\u3092\u3001"http://svn.apache.org/repos/asf/ant/"\u306E\u3088\u3046\u306B\u6307\u5B9A\u3057\u3066\u304F\u3060\u3055\u3044\u3002.
description.2=\ description.2=\
......
...@@ -104,4 +104,23 @@ public class SubversionSCMTest extends HudsonTestCase { ...@@ -104,4 +104,23 @@ public class SubversionSCMTest extends HudsonTestCase {
assertBuildStatus(Result.SUCCESS,b); assertBuildStatus(Result.SUCCESS,b);
assertTrue(p.getWorkspace().child("jasf/maven.xml").exists()); assertTrue(p.getWorkspace().child("jasf/maven.xml").exists());
} }
/**
* Tests the "URL@REV" format in SVN URL.
*/
@Bug(262)
public void testRevisionedCheckout() throws Exception {
FreeStyleProject p = createFreeStyleProject();
p.setScm(new SubversionSCM(
new String[]{"https://svn.dev.java.net/svn/hudson/trunk/hudson/test-projects/trivial-ant@13000"},
new String[]{null},
true, null
));
FreeStyleBuild b = p.scheduleBuild2(0).get();
System.out.println(b.getLog());
assertTrue(b.getLog().contains("At revision 13000"));
assertBuildStatus(Result.SUCCESS,b);
assertTrue(p.getWorkspace().child("trivial-ant/build.xml").exists());
}
} }
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册