提交 a20e6e43 编写于 作者: K kohsuke

Because of the tricky license in SVNKit that has a viral effect, I'm moving it...

Because of the tricky license in SVNKit that has a viral effect, I'm moving it out into a separate plugin so that
people can choose to remove it from their distributions.



git-svn-id: https://hudson.dev.java.net/svn/hudson/trunk/hudson/main@18923 71c3de6d-444a-0410-be80-ed276b4c234a
上级 d8bdd39e
......@@ -65,7 +65,6 @@ import hudson.scm.CVSSCM;
import hudson.scm.RepositoryBrowser;
import hudson.scm.SCM;
import hudson.scm.SCMDescriptor;
import hudson.scm.SubversionSCM;
import hudson.search.CollectionSearchIndex;
import hudson.search.SearchIndexBuilder;
import hudson.security.ACL;
......@@ -552,9 +551,6 @@ public final class Hudson extends Node implements ItemGroup<TopLevelItem>, Stapl
LOGGER.log(Level.SEVERE, "Failed to load proxy configuration", e);
}
// run the init code of SubversionSCM before we load plugins so that plugins can change SubversionWorkspaceSelector.
SubversionSCM.init();
// load plugins.
pluginManager = new PluginManager(context);
pluginManager.initialize();
......
/*
* The MIT License
*
* Copyright (c) 2004-2009, Sun Microsystems, Inc., Kohsuke Kawaguchi, Daniel Dyer, Jean-Baptiste Quenot, Luca Domenico Milanesio, Renaud Bruyeron
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE.
*/
package hudson.scm;
import hudson.model.AbstractBuild;
import hudson.model.BuildListener;
import hudson.model.Hudson;
import hudson.scm.SubversionSCM.ModuleLocation;
import hudson.FilePath;
import hudson.util.IOException2;
import hudson.remoting.VirtualChannel;
import hudson.FilePath.FileCallable;
import org.tmatesoft.svn.core.SVNException;
import org.tmatesoft.svn.core.SVNURL;
import org.tmatesoft.svn.core.ISVNLogEntryHandler;
import org.tmatesoft.svn.core.SVNLogEntry;
import org.tmatesoft.svn.core.auth.ISVNAuthenticationProvider;
import org.tmatesoft.svn.core.wc.SVNClientManager;
import org.tmatesoft.svn.core.wc.SVNLogClient;
import org.tmatesoft.svn.core.wc.SVNRevision;
import org.tmatesoft.svn.core.wc.SVNWCClient;
import org.tmatesoft.svn.core.wc.SVNInfo;
import org.tmatesoft.svn.core.wc.xml.SVNXMLLogHandler;
import org.xml.sax.helpers.LocatorImpl;
import javax.xml.transform.Result;
import javax.xml.transform.TransformerConfigurationException;
import javax.xml.transform.sax.SAXTransformerFactory;
import javax.xml.transform.sax.TransformerHandler;
import java.io.IOException;
import java.io.PrintStream;
import java.io.File;
import java.util.Map;
import java.util.Collection;
/**
* Builds <tt>changelog.xml</tt> for {@link SubversionSCM}.
*
* @author Kohsuke Kawaguchi
*/
public final class SubversionChangeLogBuilder {
/**
* Revisions of the workspace before the update/checkout.
*/
private final Map<String,Long> previousRevisions;
/**
* Revisions of the workspace after the update/checkout.
*/
private final Map<String,Long> thisRevisions;
private final BuildListener listener;
private final SubversionSCM scm;
private final AbstractBuild<?,?> build;
public SubversionChangeLogBuilder(AbstractBuild<?,?> build, BuildListener listener, SubversionSCM scm) throws IOException {
previousRevisions = SubversionSCM.parseRevisionFile(build.getPreviousBuild());
thisRevisions = SubversionSCM.parseRevisionFile(build);
this.listener = listener;
this.scm = scm;
this.build = build;
}
public boolean run(Collection<SubversionSCM.External> externals, Result changeLog) throws IOException, InterruptedException {
boolean changelogFileCreated = false;
final SVNClientManager manager = SubversionSCM.createSvnClientManager();
try {
SVNLogClient svnlc = manager.getLogClient();
TransformerHandler th = createTransformerHandler();
th.setResult(changeLog);
SVNXMLLogHandler logHandler = new SVNXMLLogHandler(th);
// work around for http://svnkit.com/tracker/view.php?id=175
th.setDocumentLocator(DUMMY_LOCATOR);
logHandler.startDocument();
for (ModuleLocation l : scm.getLocations(build)) {
changelogFileCreated |= buildModule(l.getURL(), svnlc, logHandler);
}
for(SubversionSCM.External ext : externals) {
changelogFileCreated |= buildModule(
getUrlForPath(build.getProject().getWorkspace().child(ext.path)), svnlc, logHandler);
}
if(changelogFileCreated) {
logHandler.endDocument();
}
return changelogFileCreated;
} finally {
manager.dispose();
}
}
private String getUrlForPath(FilePath path) throws IOException, InterruptedException {
return path.act(new GetUrlForPath(createAuthenticationProvider()));
}
private ISVNAuthenticationProvider createAuthenticationProvider() {
return Hudson.getInstance().getDescriptorByType(SubversionSCM.DescriptorImpl.class).createAuthenticationProvider();
}
private boolean buildModule(String url, SVNLogClient svnlc, SVNXMLLogHandler logHandler) throws IOException2 {
PrintStream logger = listener.getLogger();
Long prevRev = previousRevisions.get(url);
if(prevRev==null) {
logger.println("no revision recorded for "+url+" in the previous build");
return false;
}
Long thisRev = thisRevisions.get(url);
if (thisRev == null) {
listener.error("No revision found for URL: " + url + " in " + SubversionSCM.getRevisionFile(build) + ". Revision file contains: " + thisRevisions.keySet());
return true;
}
if(thisRev.equals(prevRev)) {
logger.println("no change for "+url+" since the previous build");
return false;
}
try {
if(debug)
listener.getLogger().printf("Computing changelog of %1s from %2s to %3s\n",
SVNURL.parseURIEncoded(url), prevRev+1, thisRev);
svnlc.doLog(SVNURL.parseURIEncoded(url),
null,
SVNRevision.UNDEFINED,
SVNRevision.create(prevRev+1),
SVNRevision.create(thisRev),
false, // Don't stop on copy.
true, // Report paths.
0, // Retrieve log entries for unlimited number of revisions.
debug ? new DebugSVNLogHandler(logHandler) : logHandler);
if(debug)
listener.getLogger().println("done");
} catch (SVNException e) {
throw new IOException2("revision check failed on "+url,e);
}
return true;
}
/**
* Filter {@link ISVNLogEntryHandler} that dumps information. Used only for debugging.
*/
private class DebugSVNLogHandler implements ISVNLogEntryHandler {
private final ISVNLogEntryHandler core;
private DebugSVNLogHandler(ISVNLogEntryHandler core) {
this.core = core;
}
public void handleLogEntry(SVNLogEntry logEntry) throws SVNException {
listener.getLogger().println("SVNLogEntry="+logEntry);
core.handleLogEntry(logEntry);
}
}
/**
* Creates an identity transformer.
*/
private static TransformerHandler createTransformerHandler() {
try {
return ((SAXTransformerFactory) SAXTransformerFactory.newInstance()).newTransformerHandler();
} catch (TransformerConfigurationException e) {
throw new Error(e); // impossible
}
}
private static final LocatorImpl DUMMY_LOCATOR = new LocatorImpl();
public static boolean debug = false;
static {
DUMMY_LOCATOR.setLineNumber(-1);
DUMMY_LOCATOR.setColumnNumber(-1);
}
private static class GetUrlForPath implements FileCallable<String> {
private final ISVNAuthenticationProvider authProvider;
public GetUrlForPath(ISVNAuthenticationProvider authProvider) {
this.authProvider = authProvider;
}
public String invoke(File p, VirtualChannel channel) throws IOException {
final SVNClientManager manager = SubversionSCM.createSvnClientManager(authProvider);
try {
final SVNWCClient svnwc = manager.getWCClient();
SVNInfo info;
try {
info = svnwc.doInfo(p, SVNRevision.WORKING);
return info.getURL().toDecodedString();
} catch (SVNException e) {
e.printStackTrace();
return null;
}
} finally {
manager.dispose();
}
}
private static final long serialVersionUID = 1L;
}
}
/*
* The MIT License
*
* Copyright (c) 2004-2009, Sun Microsystems, Inc., Kohsuke Kawaguchi
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE.
*/
package hudson.scm;
import hudson.model.AbstractBuild;
import hudson.scm.SubversionChangeLogSet.LogEntry;
import hudson.scm.SubversionChangeLogSet.Path;
import hudson.util.Digester2;
import hudson.util.IOException2;
import org.apache.commons.digester.Digester;
import org.xml.sax.SAXException;
import java.io.File;
import java.io.IOException;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Comparator;
/**
* {@link ChangeLogParser} for Subversion.
*
* @author Kohsuke Kawaguchi
*/
public class SubversionChangeLogParser extends ChangeLogParser {
public SubversionChangeLogSet parse(AbstractBuild build, File changelogFile) throws IOException, SAXException {
// http://svn.collab.net/repos/svn/trunk/subversion/svn/schema/
Digester digester = new Digester2();
ArrayList<LogEntry> r = new ArrayList<LogEntry>();
digester.push(r);
digester.addObjectCreate("*/logentry", LogEntry.class);
digester.addSetProperties("*/logentry");
digester.addBeanPropertySetter("*/logentry/author","user");
digester.addBeanPropertySetter("*/logentry/date");
digester.addBeanPropertySetter("*/logentry/msg");
digester.addSetNext("*/logentry","add");
digester.addObjectCreate("*/logentry/paths/path", Path.class);
digester.addSetProperties("*/logentry/paths/path");
digester.addBeanPropertySetter("*/logentry/paths/path","value");
digester.addSetNext("*/logentry/paths/path","addPath");
try {
digester.parse(changelogFile);
} catch (IOException e) {
throw new IOException2("Failed to parse "+changelogFile,e);
} catch (SAXException e) {
throw new IOException2("Failed to parse "+changelogFile,e);
}
return new SubversionChangeLogSet(build,r);
}
}
/*
* The MIT License
*
* Copyright (c) 2004-2009, Sun Microsystems, Inc., Kohsuke Kawaguchi, Erik Ramfelt
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE.
*/
package hudson.scm;
import hudson.model.AbstractBuild;
import hudson.model.User;
import hudson.scm.SubversionChangeLogSet.LogEntry;
import hudson.scm.SubversionSCM.ModuleLocation;
import org.kohsuke.stapler.export.Exported;
import org.kohsuke.stapler.export.ExportedBean;
import java.io.IOException;
import java.util.AbstractList;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Comparator;
/**
* {@link ChangeLogSet} for Subversion.
*
* @author Kohsuke Kawaguchi
*/
public final class SubversionChangeLogSet extends ChangeLogSet<LogEntry> {
private final List<LogEntry> logs;
/**
* @GuardedBy this
*/
private Map<String,Long> revisionMap;
/*package*/ SubversionChangeLogSet(AbstractBuild build, List<LogEntry> logs) {
super(build);
// we want recent changes first
Collections.sort(logs,new Comparator<LogEntry>() {
public int compare(LogEntry a, LogEntry b) {
return b.getRevision()-a.getRevision();
}
});
this.logs = Collections.unmodifiableList(logs);
for (LogEntry log : logs)
log.setParent(this);
}
public boolean isEmptySet() {
return logs.isEmpty();
}
public List<LogEntry> getLogs() {
return logs;
}
public Iterator<LogEntry> iterator() {
return logs.iterator();
}
@Override
public String getKind() {
return "svn";
}
public synchronized Map<String,Long> getRevisionMap() throws IOException {
if(revisionMap==null)
revisionMap = SubversionSCM.parseRevisionFile(build);
return revisionMap;
}
@Exported
public List<RevisionInfo> getRevisions() throws IOException {
List<RevisionInfo> r = new ArrayList<RevisionInfo>();
for (Map.Entry<String, Long> e : getRevisionMap().entrySet())
r.add(new RevisionInfo(e.getKey(),e.getValue()));
return r;
}
@ExportedBean(defaultVisibility=999)
public static final class RevisionInfo {
@Exported public final String module;
@Exported public final long revision;
public RevisionInfo(String module, long revision) {
this.module = module;
this.revision = revision;
}
}
/**
* One commit.
* <p>
* Setter methods are public only so that the objects can be constructed from Digester.
* So please consider this object read-only.
*/
public static class LogEntry extends ChangeLogSet.Entry {
private int revision;
private User author;
private String date;
private String msg;
private List<Path> paths = new ArrayList<Path>();
/**
* Gets the {@link SubversionChangeLogSet} to which this change set belongs.
*/
public SubversionChangeLogSet getParent() {
return (SubversionChangeLogSet)super.getParent();
}
/**
* Gets the revision of the commit.
*
* <p>
* If the commit made the repository revision 1532, this
* method returns 1532.
*/
@Exported
public int getRevision() {
return revision;
}
public void setRevision(int revision) {
this.revision = revision;
}
@Override
public User getAuthor() {
if(author==null)
return User.getUnknown();
return author;
}
@Override
public Collection<String> getAffectedPaths() {
return new AbstractList<String>() {
public String get(int index) {
return preparePath(paths.get(index).value);
}
public int size() {
return paths.size();
}
};
}
private String preparePath(String path) {
SubversionSCM scm = (SubversionSCM) getParent().build.getProject().getScm();
ModuleLocation[] locations = scm.getLocations();
for (int i = 0; i < locations.length; i++) {
String commonPart = findCommonPart(locations[i].remote, path);
if (commonPart != null) {
if (path.startsWith("/")) {
path = path.substring(1);
}
String newPath = path.substring(commonPart.length());
if (newPath.startsWith("/")) {
newPath = newPath.substring(1);
}
return newPath;
}
}
return path;
}
private String findCommonPart(String folder, String filePath) {
if (folder == null || filePath == null) {
return null;
}
if (filePath.startsWith("/")) {
filePath = filePath.substring(1);
}
for (int i = 0; i < folder.length(); i++) {
String part = folder.substring(i);
if (filePath.startsWith(part)) {
return part;
}
}
return null;
}
public void setUser(String author) {
this.author = User.get(author);
}
@Exported
public String getUser() {// digester wants read/write property, even though it never reads. Duh.
return author.getDisplayName();
}
@Exported
public String getDate() {
return date;
}
public void setDate(String date) {
this.date = date;
}
@Override @Exported
public String getMsg() {
return msg;
}
public void setMsg(String msg) {
this.msg = msg;
}
public void addPath( Path p ) {
p.entry = this;
paths.add(p);
}
/**
* Gets the files that are changed in this commit.
* @return
* can be empty but never null.
*/
@Exported
public List<Path> getPaths() {
return paths;
}
@Override
public Collection<Path> getAffectedFiles() {
return paths;
}
}
/**
* A file in a commit.
* <p>
* Setter methods are public only so that the objects can be constructed from Digester.
* So please consider this object read-only.
*/
@ExportedBean(defaultVisibility=999)
public static class Path implements AffectedFile {
private LogEntry entry;
private char action;
private String value;
/**
* Gets the {@link LogEntry} of which this path is a member.
*/
public LogEntry getLogEntry() {
return entry;
}
/**
* Sets the {@link LogEntry} of which this path is a member.
*/
public void setLogEntry(LogEntry entry) {
this.entry = entry;
}
public void setAction(String action) {
this.action = action.charAt(0);
}
/**
* Path in the repository. Such as <tt>/test/trunk/foo.c</tt>
*/
@Exported(name="file")
public String getValue() {
return value;
}
/**
* Inherited from AffectedFile
*/
public String getPath() {
return getValue();
}
public void setValue(String value) {
this.value = value;
}
@Exported
public EditType getEditType() {
if( action=='A' )
return EditType.ADD;
if( action=='D' )
return EditType.DELETE;
return EditType.EDIT;
}
}
}
/*
* The MIT License
*
* Copyright (c) 2004-2009, Sun Microsystems, Inc.
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE.
*/
package hudson.scm;
import hudson.ExtensionList;
import hudson.ExtensionPoint;
import hudson.Extension;
import hudson.model.Hudson;
import hudson.scm.SubversionSCM.DescriptorImpl.Credential;
import org.tmatesoft.svn.core.SVNURL;
/**
* Extension point for programmatically providing a credential (such as username/password) for
* Subversion access.
*
* <p>
* Put {@link Extension} on your implementation to have it registered.
*
* @author Kohsuke Kawaguchi
* @since 1.301
*/
public abstract class SubversionCredentialProvider implements ExtensionPoint {
/**
* Called whenever Hudson needs to connect to an authenticated subversion repository,
* to obtain a credential.
*
* @param realm
* This is a non-null string that represents the realm of authentication.
* @param url
* URL that is being accessed. Never null.
* @return
* null if the implementation doesn't understand the given realm. When null is returned,
* Hudson searches other sources of credentials to come up with one.
*/
public abstract Credential getCredential(SVNURL url, String realm);
/**
* All regsitered instances.
*/
public static ExtensionList<SubversionCredentialProvider> all() {
return Hudson.getInstance().getExtensionList(SubversionCredentialProvider.class);
}
}
/*
* ====================================================================
* Copyright (c) 2004-2007 TMate Software Ltd. All rights reserved.
*
* This software is licensed as described in the file COPYING, which
* you should have received as part of this distribution. The terms
* are also available at http://svnkit.com/license.html
* If newer versions of this license are posted there, you may use a
* newer version instead, at your option.
* ====================================================================
*/
package hudson.scm;
import org.tmatesoft.svn.core.SVNErrorCode;
import org.tmatesoft.svn.core.SVNErrorMessage;
import org.tmatesoft.svn.core.SVNException;
import org.tmatesoft.svn.core.internal.util.SVNPathUtil;
import org.tmatesoft.svn.core.internal.wc.SVNFileUtil;
import org.tmatesoft.svn.core.wc.SVNEvent;
import org.tmatesoft.svn.core.wc.SVNEventAction;
import org.tmatesoft.svn.core.wc.SVNEventAdapter;
import org.tmatesoft.svn.core.wc.SVNStatusType;
import org.tmatesoft.svn.core.wc.ISVNEventHandler;
import java.io.File;
import java.io.IOException;
import java.io.PrintStream;
/**
* {@link ISVNEventHandler} that emulates the SVN CLI behavior.
*
* @author Kohsuke Kawaguchi
*/
public class SubversionEventHandlerImpl extends SVNEventAdapter {
protected final PrintStream out;
protected final File baseDir;
public SubversionEventHandlerImpl(PrintStream out, File baseDir) {
this.out = out;
this.baseDir = baseDir;
}
public void handleEvent(SVNEvent event, double progress) throws SVNException {
File file = event.getFile();
String path = null;
if (file != null) {
try {
path = getRelativePath(file);
} catch (IOException e) {
throw new SVNException(SVNErrorMessage.create(SVNErrorCode.FS_GENERAL), e);
}
path = getLocalPath(path);
}
SVNEventAction action = event.getAction();
{// commit notifications
if (action == SVNEventAction.COMMIT_ADDED) {
out.println("Adding "+path);
return;
}
if (action == SVNEventAction.COMMIT_DELETED) {
out.println("Deleting "+path);
return;
}
if (action == SVNEventAction.COMMIT_MODIFIED) {
out.println("Sending "+path);
return;
}
if (action == SVNEventAction.COMMIT_REPLACED) {
out.println("Replacing "+path);
return;
}
if (action == SVNEventAction.COMMIT_DELTA_SENT) {
out.println("Transmitting file data....");
return;
}
}
String pathChangeType = " ";
if (action == SVNEventAction.UPDATE_ADD) {
pathChangeType = "A";
SVNStatusType contentsStatus = event.getContentsStatus();
if(contentsStatus== SVNStatusType.UNCHANGED) {
// happens a lot with merges
pathChangeType = " ";
}else if (contentsStatus == SVNStatusType.CONFLICTED) {
pathChangeType = "C";
} else if (contentsStatus == SVNStatusType.MERGED) {
pathChangeType = "G";
}
} else if (action == SVNEventAction.UPDATE_DELETE) {
pathChangeType = "D";
} else if (action == SVNEventAction.UPDATE_UPDATE) {
SVNStatusType contentsStatus = event.getContentsStatus();
if (contentsStatus == SVNStatusType.CHANGED) {
/*
* the item was modified in the repository (got the changes
* from the repository
*/
pathChangeType = "U";
}else if (contentsStatus == SVNStatusType.CONFLICTED) {
/*
* The file item is in a state of Conflict. That is, changes
* received from the repository during an update, overlap with
* local changes the user has in his working copy.
*/
pathChangeType = "C";
} else if (contentsStatus == SVNStatusType.MERGED) {
/*
* The file item was merGed (those changes that came from the
* repository did not overlap local changes and were merged
* into the file).
*/
pathChangeType = "G";
}
} else if (action == SVNEventAction.UPDATE_COMPLETED) {
// finished updating
out.println("At revision " + event.getRevision());
return;
} else if (action == SVNEventAction.ADD){
out.println("A " + path);
return;
} else if (action == SVNEventAction.DELETE){
out.println("D " + path);
return;
} else if (action == SVNEventAction.LOCKED){
out.println("L " + path);
return;
} else if (action == SVNEventAction.LOCK_FAILED){
out.println("failed to lock " + path);
return;
}
/*
* Now getting the status of properties of an item. SVNStatusType also
* contains information on the properties state.
*/
SVNStatusType propertiesStatus = event.getPropertiesStatus();
String propertiesChangeType = " ";
if (propertiesStatus == SVNStatusType.CHANGED) {
propertiesChangeType = "U";
} else if (propertiesStatus == SVNStatusType.CONFLICTED) {
propertiesChangeType = "C";
} else if (propertiesStatus == SVNStatusType.MERGED) {
propertiesChangeType = "G";
}
String lockLabel = " ";
SVNStatusType lockType = event.getLockStatus();
if (lockType == SVNStatusType.LOCK_UNLOCKED) {
// The lock is broken by someone.
lockLabel = "B";
}
if(pathChangeType.equals(" ") && propertiesChangeType.equals(" ") && lockLabel.equals(" "))
// nothing to display here.
return;
out.println(pathChangeType
+ propertiesChangeType
+ lockLabel
+ " "
+ path);
}
public String getRelativePath(File file) throws IOException {
String inPath = file.getCanonicalPath().replace(File.separatorChar, '/');
String basePath = baseDir.getCanonicalPath().replace(File.separatorChar, '/');
String commonRoot = getCommonAncestor(inPath, basePath);
String relativePath = inPath;
if (commonRoot != null) {
if (equals(inPath , commonRoot)) {
return "";
} else if (startsWith(inPath, commonRoot + "/")) {
relativePath = inPath.substring(commonRoot.length() + 1);
}
}
if (relativePath.endsWith("/")) {
relativePath = relativePath.substring(0, relativePath.length() - 1);
}
return relativePath;
}
private static String getCommonAncestor(String p1, String p2) {
if (SVNFileUtil.isWindows || SVNFileUtil.isOpenVMS) {
String ancestor = SVNPathUtil.getCommonPathAncestor(p1.toLowerCase(), p2.toLowerCase());
if (equals(ancestor, p1)) {
return p1;
} else if (equals(ancestor, p2)) {
return p2;
} else if (startsWith(p1, ancestor)) {
return p1.substring(0, ancestor.length());
}
return ancestor;
}
return SVNPathUtil.getCommonPathAncestor(p1, p2);
}
private static boolean startsWith(String p1, String p2) {
if (SVNFileUtil.isWindows || SVNFileUtil.isOpenVMS) {
return p1.toLowerCase().startsWith(p2.toLowerCase());
}
return p1.startsWith(p2);
}
private static boolean equals(String p1, String p2) {
if (SVNFileUtil.isWindows || SVNFileUtil.isOpenVMS) {
return p1.toLowerCase().equals(p2.toLowerCase());
}
return p1.equals(p2);
}
public static String getLocalPath(String path) {
path = path.replace('/', File.separatorChar);
if ("".equals(path)) {
path = ".";
}
return path;
}
}
/*
* The MIT License
*
* Copyright (c) 2004-2009, Sun Microsystems, Inc., Kohsuke Kawaguchi
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE.
*/
package hudson.scm;
import java.io.IOException;
import java.net.URL;
/**
* {@link RepositoryBrowser} for Subversion.
*
* @author Kohsuke Kawaguchi
*/
public abstract class SubversionRepositoryBrowser extends RepositoryBrowser<SubversionChangeLogSet.LogEntry> {
/**
* Determines the link to the diff between the version
* in the specified revision of {@link SubversionChangeLogSet.Path} to its previous version.
*
* @return
* null if the browser doesn't have any URL for diff.
*/
public abstract URL getDiffLink(SubversionChangeLogSet.Path path) throws IOException;
/**
* Determines the link to a single file under Subversion.
* This page should display all the past revisions of this file, etc.
*
* @return
* null if the browser doesn't have any suitable URL.
*/
public abstract URL getFileLink(SubversionChangeLogSet.Path path) throws IOException;
private static final long serialVersionUID = 1L;
}
package hudson.scm;
import hudson.model.AbstractModelObject;
import hudson.model.AbstractProject;
import hudson.model.Hudson;
import hudson.scm.SubversionSCM.ModuleLocation;
import hudson.triggers.SCMTrigger;
import org.kohsuke.stapler.StaplerRequest;
import org.kohsuke.stapler.StaplerResponse;
import org.tmatesoft.svn.core.SVNException;
import javax.servlet.ServletException;
import static javax.servlet.http.HttpServletResponse.SC_OK;
import java.io.BufferedReader;
import java.io.IOException;
import java.util.HashSet;
import java.util.Set;
import java.util.UUID;
import static java.util.logging.Level.FINE;
import static java.util.logging.Level.WARNING;
import java.util.logging.Logger;
/**
* Per repository status.
*
* @author Kohsuke Kawaguchi
* @see SubversionStatus
*/
public class SubversionRepositoryStatus extends AbstractModelObject {
public final UUID uuid;
public SubversionRepositoryStatus(UUID uuid) {
this.uuid = uuid;
}
public String getDisplayName() {
return uuid.toString();
}
public String getSearchUrl() {
return uuid.toString();
}
/**
* Notify the commit to this repository.
*
* <p>
* Because this URL is not guarded, we can't really trust the data that's sent to us. But we intentionally
* don't protect this URL to simplify <tt>post-commit</tt> script set up.
*/
public void doNotifyCommit(StaplerRequest req, StaplerResponse rsp) throws ServletException, IOException {
requirePOST();
// compute the affected paths
Set<String> affectedPath = new HashSet<String>();
String line;
while((line=new BufferedReader(req.getReader()).readLine())!=null)
affectedPath.add(line.substring(4));
if(LOGGER.isLoggable(FINE))
LOGGER.fine("Change reported to Subversion repository "+uuid+" on "+affectedPath);
OUTER:
for (AbstractProject<?,?> p : Hudson.getInstance().getItems(AbstractProject.class)) {
try {
SCM scm = p.getScm();
if (!(scm instanceof SubversionSCM)) continue;
SCMTrigger trigger = p.getTrigger(SCMTrigger.class);
if(trigger==null) continue;
SubversionSCM sscm = (SubversionSCM) scm;
for (ModuleLocation loc : sscm.getLocations()) {
if(!loc.getUUID().equals(uuid)) continue; // different repository
String m = loc.getSVNURL().getPath();
String n = loc.getRepositoryRoot().getPath();
if(!m.startsWith(n)) continue; // repository root should be a subpath of the module path, but be defensive
String remaining = m.substring(n.length());
if(remaining.startsWith("/")) remaining=remaining.substring(1);
String remainingSlash = remaining + '/';
for (String path : affectedPath) {
if(path.equals(remaining) /*for files*/ || path.startsWith(remainingSlash) /*for dirs*/) {
// this project is possibly changed. poll now.
// if any of the data we used was bogus, the trigger will not detect a chaange
LOGGER.fine("Scheduling the immediate polling of "+p);
trigger.run();
continue OUTER;
}
}
}
} catch (SVNException e) {
LOGGER.log(WARNING,"Failed to handle Subversion commit notification",e);
}
}
rsp.setStatus(SC_OK);
}
private static final Logger LOGGER = Logger.getLogger(SubversionRepositoryStatus.class.getName());
}
/*
* The MIT License
*
* Copyright (c) 2004-2009, Sun Microsystems, Inc.
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE.
*/
package hudson.scm;
import hudson.model.AbstractModelObject;
import hudson.model.Action;
import hudson.model.RootAction;
import hudson.Extension;
import java.util.regex.Pattern;
import java.util.UUID;
/**
* Information screen for the use of Subversion in Hudson.
*
* @author Kohsuke Kawaguchi
*/
@Extension
public class SubversionStatus extends AbstractModelObject implements RootAction {
public String getDisplayName() {
return "Subversion";
}
public String getSearchUrl() {
return getUrlName();
}
public String getIconFileName() {
// TODO
return null;
}
public String getUrlName() {
return "subversion";
}
public SubversionRepositoryStatus getDynamic(String uuid) {
if(UUID_PATTERN.matcher(uuid).matches())
return new SubversionRepositoryStatus(UUID.fromString(uuid));
return null;
}
private static final Pattern UUID_PATTERN = Pattern.compile("\\p{XDigit}{8}-\\p{XDigit}{4}-\\p{XDigit}{4}-\\p{XDigit}{4}-\\p{XDigit}{12}");
}
/*
* The MIT License
*
* Copyright (c) 2004-2009, Sun Microsystems, Inc., Kohsuke Kawaguchi, Jean-Baptiste Quenot, Seiji Sogabe, Vojtech Habarta
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE.
*/
package hudson.scm;
import hudson.model.AbstractBuild;
import hudson.model.Action;
import hudson.model.TaskListener;
import hudson.model.TaskThread;
import hudson.scm.SubversionSCM.SvnInfo;
import hudson.util.CopyOnWriteMap;
import hudson.security.Permission;
import org.kohsuke.stapler.StaplerRequest;
import org.kohsuke.stapler.StaplerResponse;
import org.tmatesoft.svn.core.SVNException;
import org.tmatesoft.svn.core.SVNURL;
import org.tmatesoft.svn.core.wc.SVNClientManager;
import org.tmatesoft.svn.core.wc.SVNCopyClient;
import org.tmatesoft.svn.core.wc.SVNRevision;
import org.tmatesoft.svn.core.wc.SVNCopySource;
import javax.servlet.ServletException;
import java.io.IOException;
import java.io.PrintStream;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Map.Entry;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
/**
* {@link Action} that lets people create tag for the given build.
*
* @author Kohsuke Kawaguchi
*/
public class SubversionTagAction extends AbstractScmTagAction {
/**
* Map is from the repository URL to the URLs of tags.
* If a module is not tagged, the value will be empty list.
* Never an empty map.
*/
private final Map<SvnInfo,List<String>> tags = new CopyOnWriteMap.Tree<SvnInfo, List<String>>();
/*package*/ SubversionTagAction(AbstractBuild build,Collection<SvnInfo> svnInfos) {
super(build);
Map<SvnInfo,List<String>> m = new HashMap<SvnInfo,List<String>>();
for (SvnInfo si : svnInfos)
m.put(si,new ArrayList<String>());
tags.putAll(m);
}
/**
* Was any tag created by the user already?
*/
public boolean hasTags() {
for (Entry<SvnInfo, List<String>> e : tags.entrySet())
if(!e.getValue().isEmpty())
return true;
return false;
}
public String getIconFileName() {
if(!hasTags() && !getACL().hasPermission(getPermission()))
return null;
return "save.gif";
}
public String getDisplayName() {
int nonNullTag = 0;
for (List<String> v : tags.values()) {
if(!v.isEmpty()) {
nonNullTag++;
if(nonNullTag>1)
break;
}
}
if(nonNullTag==0)
return Messages.SubversionTagAction_DisplayName_HasNoTag();
if(nonNullTag==1)
return Messages.SubversionTagAction_DisplayName_HasATag();
else
return Messages.SubversionTagAction_DisplayName_HasTags();
}
/**
* @see #tags
*/
public Map<SvnInfo,List<String>> getTags() {
return Collections.unmodifiableMap(tags);
}
/**
* Returns true if this build has already been tagged at least once.
*/
@Override
public boolean isTagged() {
for (List<String> t : tags.values()) {
if(!t.isEmpty()) return true;
}
return false;
}
@Override
public String getTooltip() {
if(isTagged()) return Messages.SubversionTagAction_Tooltip();
else return null;
}
private static final Pattern TRUNK_BRANCH_MARKER = Pattern.compile("/(trunk|branches)(/|$)");
/**
* Creates a URL, to be used as the default value of the module tag URL.
*
* @return
* null if failed to guess.
*/
public String makeTagURL(SvnInfo si) {
// assume the standard trunk/branches/tags repository layout
Matcher m = TRUNK_BRANCH_MARKER.matcher(si.url);
if(!m.find())
return null; // doesn't have 'trunk' nor 'branches'
return si.url.substring(0,m.start())+"/tags/"+build.getProject().getName()+"-"+build.getNumber();
}
/**
* Invoked to actually tag the workspace.
*/
public synchronized void doSubmit(StaplerRequest req, StaplerResponse rsp) throws IOException, ServletException {
getACL().checkPermission(getPermission());
Map<SvnInfo,String> newTags = new HashMap<SvnInfo,String>();
int i=-1;
for (SvnInfo e : tags.keySet()) {
i++;
if(tags.size()>1 && req.getParameter("tag"+i)==null)
continue; // when tags.size()==1, UI won't show the checkbox.
newTags.put(e,req.getParameter("name" + i));
}
new TagWorkerThread(newTags).start();
rsp.sendRedirect(".");
}
@Override
public Permission getPermission() {
return SubversionSCM.TAG;
}
/**
* The thread that performs tagging operation asynchronously.
*/
public final class TagWorkerThread extends TaskThread {
private final Map<SvnInfo,String> tagSet;
public TagWorkerThread(Map<SvnInfo,String> tagSet) {
super(SubversionTagAction.this,ListenerAndText.forMemory());
this.tagSet = tagSet;
}
@Override
protected void perform(TaskListener listener) {
try {
final SVNClientManager cm = SubversionSCM.createSvnClientManager();
try {
for (Entry<SvnInfo, String> e : tagSet.entrySet()) {
PrintStream logger = listener.getLogger();
logger.println("Tagging "+e.getKey()+" to "+e.getValue());
try {
SVNURL src = SVNURL.parseURIDecoded(e.getKey().url);
SVNURL dst = SVNURL.parseURIDecoded(e.getValue());
SVNCopyClient svncc = cm.getCopyClient();
SVNRevision sourceRevision = SVNRevision.create(e.getKey().revision);
SVNCopySource csrc = new SVNCopySource(sourceRevision, sourceRevision, src);
svncc.doCopy(
new SVNCopySource[]{csrc},
dst, false, true, false, "Tagged from "+build, null );
} catch (SVNException x) {
x.printStackTrace(listener.error("Failed to tag"));
return;
}
}
// completed successfully
for (Entry<SvnInfo,String> e : tagSet.entrySet())
SubversionTagAction.this.tags.get(e.getKey()).add(e.getValue());
build.save();
workerThread = null;
} finally {
cm.dispose();
}
} catch (Throwable e) {
e.printStackTrace(listener.fatalError(e.getMessage()));
}
}
}
}
/*
* The MIT License
*
* Copyright (c) 2004-2009, Sun Microsystems, Inc., Kohsuke Kawaguchi, David Seymore, Renaud Bruyeron
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE.
*/
package hudson.scm;
import hudson.remoting.Which;
import org.tmatesoft.svn.core.SVNCancelException;
import org.tmatesoft.svn.core.SVNErrorCode;
import org.tmatesoft.svn.core.SVNErrorMessage;
import org.tmatesoft.svn.core.SVNException;
import org.tmatesoft.svn.core.internal.wc.SVNExternal;
import org.tmatesoft.svn.core.wc.SVNEvent;
import org.tmatesoft.svn.core.wc.SVNEventAction;
import java.io.File;
import java.io.IOException;
import java.io.PrintStream;
import java.net.URL;
import java.util.List;
/**
* Just prints out the progress of svn update/checkout operation in a way similar to
* the svn CLI.
*
* This code also records all the referenced external locations.
*/
final class SubversionUpdateEventHandler extends SubversionEventHandlerImpl {
/**
* External urls that are fetched through svn:externals.
* We add to this collection as we find them.
*/
private final List<SubversionSCM.External> externals;
/**
* Relative path from the workspace root to the module root.
*/
private final String modulePath;
public SubversionUpdateEventHandler(PrintStream out, List<SubversionSCM.External> externals, File moduleDir, String modulePath) {
super(out,moduleDir);
this.externals = externals;
this.modulePath = modulePath;
}
public void handleEvent(SVNEvent event, double progress) throws SVNException {
File file = event.getFile();
String path = null;
if (file != null) {
try {
path = getRelativePath(file);
} catch (IOException e) {
throw new SVNException(SVNErrorMessage.create(SVNErrorCode.FS_GENERAL), e);
}
path = getLocalPath(path);
}
/*
* Gets the current action. An action is represented by SVNEventAction.
* In case of an update an action can be determined via comparing
* SVNEvent.getAction() and SVNEventAction.UPDATE_-like constants.
*/
SVNEventAction action = event.getAction();
if (action == SVNEventAction.UPDATE_EXTERNAL) {
// for externals definitions
SVNExternal ext = event.getExternalInfo();
if(ext==null) {
// prepare for the situation where the user created their own svnkit
URL jarFile = null;
try {
jarFile = Which.jarURL(SVNEvent.class);
} catch (IOException e) {
// ignore this failure
}
out.println("AssertionError: appears to be using unpatched svnkit at "+ jarFile);
} else {
out.println(Messages.SubversionUpdateEventHandler_FetchExternal(
ext.getResolvedURL(), ext.getRevision().getNumber(), event.getFile()));
//#1539 - an external inside an external needs to have the path appended
externals.add(new SubversionSCM.External(modulePath + "/" + path.substring(0
,path.length() - ext.getPath().length())
,ext));
}
return;
}
super.handleEvent(event,progress);
}
public void checkCancelled() throws SVNCancelException {
if(Thread.interrupted())
throw new SVNCancelException();
}
}
\ No newline at end of file
/*
* The MIT License
*
* Copyright (c) 2004-2009, Sun Microsystems, Inc., Kohsuke Kawaguchi
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE.
*/
package hudson.scm;
import org.tmatesoft.svn.core.SVNException;
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 java.io.File;
import java.util.ArrayList;
import java.util.Collection;
/**
* {@link ISVNAdminAreaFactorySelector} that uses 1.4 compatible workspace for new check out,
* but still supports 1.5 workspace, if asked to work with it.
*
* <p>
* Since there are many tools out there that still don't support Subversion 1.5 (including
* all the major Unix distributions that haven't bundled Subversion 1.5), using 1.4 as the
* default would reduce the likelihood of the user running into "this SVN client can't work
* with this workspace version..." problem when using other SVN tools.
*
* <p>
* The primary scenario of this is the use of command-line SVN client, either from shell
* script, Ant, or Maven.
*
* @author Kohsuke Kawaguchi
*/
public class SubversionWorkspaceSelector implements ISVNAdminAreaFactorySelector {
public SubversionWorkspaceSelector() {
// don't upgrade the workspace.
SVNAdminAreaFactory.setUpgradeEnabled(false);
}
@SuppressWarnings({"cast", "unchecked"})
public Collection getEnabledFactories(File path, Collection factories, boolean writeAccess) throws SVNException {
if(!writeAccess) // for reading, use all our available factories
return factories;
// for writing, use 1.4
Collection<SVNAdminAreaFactory> enabledFactories = new ArrayList<SVNAdminAreaFactory>();
for (SVNAdminAreaFactory factory : (Collection<SVNAdminAreaFactory>)factories)
if (factory.getSupportedVersion() == SVNAdminArea14.WC_FORMAT)
enabledFactories.add(factory);
return enabledFactories;
}
}
/*
* The MIT License
*
* Copyright (c) 2004-2009, Sun Microsystems, Inc., Kohsuke Kawaguchi, Daniel Dyer
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE.
*/
package hudson.scm.browsers;
import hudson.model.Descriptor;
import hudson.model.Descriptor.FormException;
import hudson.scm.EditType;
import hudson.scm.RepositoryBrowser;
import hudson.scm.SubversionChangeLogSet;
import hudson.scm.SubversionRepositoryBrowser;
import hudson.Extension;
import java.io.IOException;
import java.net.URL;
import net.sf.json.JSONObject;
import org.kohsuke.stapler.DataBoundConstructor;
import org.kohsuke.stapler.StaplerRequest;
/**
* {@link RepositoryBrowser} implementation for CollabNet hosted Subversion repositories.
* This enables Hudson to integrate with the repository browsers built-in to CollabNet-powered
* sites such as Java.net and Tigris.org.
* @author Daniel Dyer
*/
public class CollabNetSVN extends SubversionRepositoryBrowser
{
@Extension
public static class DescriptorImpl extends Descriptor<RepositoryBrowser<?>> {
public String getDisplayName() {
return "CollabNet";
}
@Override
public RepositoryBrowser<?> newInstance(StaplerRequest req, JSONObject formData) throws FormException {
return req.bindParameters(CollabNetSVN.class, "collabnet.svn.");
}
}
public final URL url;
/**
* @param url The repository browser URL for the root of the project.
* For example, a Java.net project called "myproject" would use
* https://myproject.dev.java.net/source/browse/myproject
*/
@DataBoundConstructor
public CollabNetSVN(URL url) {
this.url = normalizeToEndWithSlash(url);
}
/**
* {@inheritDoc}
*/
public URL getDiffLink(SubversionChangeLogSet.Path path) throws IOException {
if (path.getEditType() != EditType.EDIT) {
// No diff if the file is being added or deleted.
return null;
}
int revision = path.getLogEntry().getRevision();
QueryBuilder query = new QueryBuilder(null);
query.add("r1=" + (revision - 1));
query.add("r2=" + revision);
return new URL(url, trimHeadSlash(path.getValue()) + query);
}
/**
* {@inheritDoc}
*/
public URL getFileLink(SubversionChangeLogSet.Path path) throws IOException {
int revision = path.getLogEntry().getRevision();
QueryBuilder query = new QueryBuilder(null);
query.add("rev=" + revision);
query.add("view=log");
return new URL(url, trimHeadSlash(path.getValue()) + query);
}
/**
* {@inheritDoc}
*/
public URL getChangeSetLink(SubversionChangeLogSet.LogEntry changeSet) throws IOException {
int revision = changeSet.getRevision();
QueryBuilder query = new QueryBuilder(null);
query.add("rev=" + revision);
query.add("view=rev");
return new URL(url, query.toString());
}
}
/*
* The MIT License
*
* Copyright (c) 2004-2009, Sun Microsystems, Inc., Kohsuke Kawaguchi
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE.
*/
package hudson.scm.browsers;
import hudson.Extension;
import hudson.model.Descriptor;
import hudson.model.Hudson;
import hudson.scm.EditType;
import hudson.scm.RepositoryBrowser;
import hudson.scm.SubversionChangeLogSet.LogEntry;
import hudson.scm.SubversionChangeLogSet.Path;
import hudson.scm.SubversionRepositoryBrowser;
import hudson.util.FormValidation;
import hudson.util.FormValidation.URLCheck;
import org.kohsuke.stapler.DataBoundConstructor;
import org.kohsuke.stapler.QueryParameter;
import javax.servlet.ServletException;
import java.io.IOException;
import java.net.MalformedURLException;
import java.net.URL;
import java.util.regex.Pattern;
/**
* {@link RepositoryBrowser} for FishEye SVN.
*
* @author Kohsuke Kawaguchi
*/
public class FishEyeSVN extends SubversionRepositoryBrowser {
/**
* The URL of the FishEye repository.
*
* This is normally like <tt>http://fisheye5.cenqua.com/browse/glassfish/</tt>
* Normalized to have '/' at the tail.
*/
public final URL url;
/**
* Root SVN module name (like 'foo/bar' &mdash; normalized to
* have no leading nor trailing slash.) Can be empty.
*/
private final String rootModule;
@DataBoundConstructor
public FishEyeSVN(URL url, String rootModule) throws MalformedURLException {
this.url = normalizeToEndWithSlash(url);
// normalize
rootModule = rootModule.trim();
if(rootModule.startsWith("/"))
rootModule = rootModule.substring(1);
if(rootModule.endsWith("/"))
rootModule = rootModule.substring(0,rootModule.length()-1);
this.rootModule = rootModule;
}
public String getRootModule() {
if(rootModule==null)
return ""; // compatibility
return rootModule;
}
@Override
public URL getDiffLink(Path path) throws IOException {
if(path.getEditType()!= EditType.EDIT)
return null; // no diff if this is not an edit change
int r = path.getLogEntry().getRevision();
return new URL(url, getPath(path)+String.format("?r1=%d&r2=%d",r-1,r));
}
@Override
public URL getFileLink(Path path) throws IOException {
return new URL(url, getPath(path));
}
/**
* Trims off the root module portion to compute the path within FishEye.
*/
private String getPath(Path path) {
String s = trimHeadSlash(path.getValue());
if(s.startsWith(rootModule)) // this should be always true, but be defensive
s = trimHeadSlash(s.substring(rootModule.length()));
return s;
}
/**
* Pick up "FOOBAR" from "http://site/browse/FOOBAR/"
*/
private String getProjectName() {
String p = url.getPath();
if(p.endsWith("/")) p = p.substring(0,p.length()-1);
int idx = p.lastIndexOf('/');
return p.substring(idx+1);
}
@Override
public URL getChangeSetLink(LogEntry changeSet) throws IOException {
return new URL(url,"../../changelog/"+getProjectName()+"/?cs="+changeSet.getRevision());
}
@Extension
public static class DescriptorImpl extends Descriptor<RepositoryBrowser<?>> {
public String getDisplayName() {
return "FishEye";
}
/**
* Performs on-the-fly validation of the URL.
*/
public FormValidation doCheck(@QueryParameter(fixEmpty=true) String value) throws IOException, ServletException {
if(value==null) // nothing entered yet
return FormValidation.ok();
if(!value.endsWith("/")) value+='/';
if(!URL_PATTERN.matcher(value).matches())
return FormValidation.errorWithMarkup("The URL should end like <tt>.../browse/foobar/</tt>");
// Connect to URL and check content only if we have admin permission
if (!Hudson.getInstance().hasPermission(Hudson.ADMINISTER))
return FormValidation.ok();
final String finalValue = value;
return new URLCheck() {
@Override
protected FormValidation check() throws IOException, ServletException {
try {
if(findText(open(new URL(finalValue)),"FishEye")) {
return FormValidation.ok();
} else {
return FormValidation.error("This is a valid URL but it doesn't look like FishEye");
}
} catch (IOException e) {
return handleIOException(finalValue,e);
}
}
}.check();
}
private static final Pattern URL_PATTERN = Pattern.compile(".+/browse/[^/]+/");
}
private static final long serialVersionUID = 1L;
}
/*
* The MIT License
*
* Copyright (c) 2004-2009, Sun Microsystems, Inc., Kohsuke Kawaguchi, Stephen Connolly
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE.
*/
package hudson.scm.browsers;
import hudson.Extension;
import hudson.model.AbstractProject;
import hudson.model.Descriptor;
import hudson.model.Item;
import hudson.scm.EditType;
import hudson.scm.RepositoryBrowser;
import hudson.scm.SubversionChangeLogSet.LogEntry;
import hudson.scm.SubversionChangeLogSet.Path;
import hudson.scm.SubversionRepositoryBrowser;
import hudson.util.FormValidation;
import hudson.util.FormValidation.URLCheck;
import org.kohsuke.stapler.AncestorInPath;
import org.kohsuke.stapler.DataBoundConstructor;
import org.kohsuke.stapler.QueryParameter;
import javax.servlet.ServletException;
import java.io.IOException;
import java.net.MalformedURLException;
import java.net.URL;
import java.net.URLEncoder;
/**
* {@link RepositoryBrowser} for Sventon 1.x.
*
* @author Stephen Connolly
*/
public class Sventon extends SubversionRepositoryBrowser {
/**
* The URL of the Sventon 1.x repository.
*
* This is normally like <tt>http://somehost.com/svn/</tt>
* Normalized to have '/' at the tail.
*/
public final URL url;
/**
* Repository instance. Cannot be empty
*/
private final String repositoryInstance;
/**
* The charset to use when encoding paths in an URI (specified in RFC 3986).
*/
private static final String URL_CHARSET = "UTF-8";
@DataBoundConstructor
public Sventon(URL url, String repositoryInstance) throws MalformedURLException {
this.url = normalizeToEndWithSlash(url);
// normalize
repositoryInstance = repositoryInstance.trim();
this.repositoryInstance = repositoryInstance == null ? "" : repositoryInstance;
}
public String getRepositoryInstance() {
return repositoryInstance;
}
@Override
public URL getDiffLink(Path path) throws IOException {
if(path.getEditType()!= EditType.EDIT)
return null; // no diff if this is not an edit change
int r = path.getLogEntry().getRevision();
return new URL(url, String.format("diffprev.svn?name=%s&commitrev=%d&committedRevision=%d&revision=%d&path=%s",
repositoryInstance,r,r,r,URLEncoder.encode(getPath(path), URL_CHARSET)));
}
@Override
public URL getFileLink(Path path) throws IOException {
if (path.getEditType() == EditType.DELETE)
return null; // no file if it's gone
int r = path.getLogEntry().getRevision();
return new URL(url, String.format("goto.svn?name=%s&revision=%d&path=%s",
repositoryInstance,r,URLEncoder.encode(getPath(path), URL_CHARSET)));
}
/**
* Trims off the root module portion to compute the path within FishEye.
*/
private String getPath(Path path) {
String s = trimHeadSlash(path.getValue());
if(s.startsWith(repositoryInstance)) // this should be always true, but be defensive
s = trimHeadSlash(s.substring(repositoryInstance.length()));
return s;
}
@Override
public URL getChangeSetLink(LogEntry changeSet) throws IOException {
return new URL(url, String.format("revinfo.svn?name=%s&revision=%d",
repositoryInstance,changeSet.getRevision()));
}
@Extension
public static class DescriptorImpl extends Descriptor<RepositoryBrowser<?>> {
public String getDisplayName() {
return "Sventon 1.x";
}
/**
* Performs on-the-fly validation of the URL.
*/
public FormValidation doCheckUrl(@AncestorInPath AbstractProject project,
@QueryParameter(fixEmpty=true) final String value)
throws IOException, ServletException {
if(!project.hasPermission(Item.CONFIGURE)) return FormValidation.ok(); // can't check
if(value==null) // nothing entered yet
return FormValidation.ok();
return new URLCheck() {
protected FormValidation check() throws IOException, ServletException {
String v = value;
if(!v.endsWith("/")) v+='/';
try {
if (findText(open(new URL(v)),"sventon 1")) {
return FormValidation.ok();
} else if (findText(open(new URL(v)),"sventon")) {
return FormValidation.error("This is a valid Sventon URL but it doesn't look like Sventon 1.x");
} else{
return FormValidation.error("This is a valid URL but it doesn't look like Sventon");
}
} catch (IOException e) {
return handleIOException(v,e);
}
}
}.check();
}
}
private static final long serialVersionUID = 1L;
}
/*
* The MIT License
*
* Copyright (c) 2004-2009, Sun Microsystems, Inc., Kohsuke Kawaguchi, Stephen Connolly
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE.
*/
package hudson.scm.browsers;
import hudson.Extension;
import hudson.model.AbstractProject;
import hudson.model.Descriptor;
import hudson.model.Item;
import hudson.scm.EditType;
import hudson.scm.RepositoryBrowser;
import hudson.scm.SubversionChangeLogSet.LogEntry;
import hudson.scm.SubversionChangeLogSet.Path;
import hudson.scm.SubversionRepositoryBrowser;
import hudson.util.FormValidation;
import hudson.util.FormValidation.URLCheck;
import org.kohsuke.stapler.AncestorInPath;
import org.kohsuke.stapler.DataBoundConstructor;
import org.kohsuke.stapler.QueryParameter;
import javax.servlet.ServletException;
import java.io.IOException;
import java.io.UnsupportedEncodingException;
import java.net.MalformedURLException;
import java.net.URL;
import java.net.URLEncoder;
/**
* {@link RepositoryBrowser} for Sventon 2.x.
*
* @author Stephen Connolly
*/
public class Sventon2 extends SubversionRepositoryBrowser {
/**
* The URL of the Sventon 2.x repository.
*
* This is normally like <tt>http://somehost.com/svn/</tt>
* Normalized to have '/' at the tail.
*/
public final URL url;
/**
* Repository instance. Cannot be empty
*/
private final String repositoryInstance;
/**
* The charset to use when encoding paths in an URI (specified in RFC 3986).
*/
private static final String URL_CHARSET = "UTF-8";
@DataBoundConstructor
public Sventon2(URL url, String repositoryInstance) throws MalformedURLException {
this.url = normalizeToEndWithSlash(url);
// normalize
repositoryInstance = repositoryInstance.trim();
this.repositoryInstance = repositoryInstance == null ? "" : repositoryInstance;
}
public String getRepositoryInstance() {
return repositoryInstance;
}
@Override
public URL getDiffLink(Path path) throws IOException {
if(path.getEditType()!= EditType.EDIT)
return null; // no diff if this is not an edit change
int r = path.getLogEntry().getRevision();
return new URL(url, String.format("repos/%s/diff/%s?revision=%d",
repositoryInstance,encodePath(getPath(path)), r));
}
@Override
public URL getFileLink(Path path) throws IOException {
if (path.getEditType() == EditType.DELETE)
return null; // no file if it's gone
int r = path.getLogEntry().getRevision();
return new URL(url, String.format("repos/%s/goto/%s?revision=%d",
repositoryInstance,encodePath(getPath(path)), r));
}
/**
* Trims off the root module portion to compute the path within FishEye.
*/
private String getPath(Path path) {
String s = trimHeadSlash(path.getValue());
if(s.startsWith(repositoryInstance)) // this should be always true, but be defensive
s = trimHeadSlash(s.substring(repositoryInstance.length()));
return s;
}
private static String encodePath(String path)
throws UnsupportedEncodingException
{
StringBuilder buf = new StringBuilder( );
if (path.startsWith("/")) {
buf.append('/');
}
boolean first = true;
for (String pathElement: path.split( "/" )) {
if (first) {
first = false;
} else {
buf.append('/');
}
buf.append(URLEncoder.encode(pathElement, URL_CHARSET));
}
if (path.endsWith("/")) {
buf.append('/');
}
return buf.toString();
}
@Override
public URL getChangeSetLink(LogEntry changeSet) throws IOException {
return new URL(url, String.format("repos/%s/info?revision=%d",
repositoryInstance,changeSet.getRevision()));
}
@Extension
public static class DescriptorImpl extends Descriptor<RepositoryBrowser<?>> {
public String getDisplayName() {
return "Sventon 2.x";
}
/**
* Performs on-the-fly validation of the URL.
*/
public FormValidation doCheckUrl(@AncestorInPath AbstractProject project,
@QueryParameter(fixEmpty=true) final String value)
throws IOException, ServletException {
if(!project.hasPermission(Item.CONFIGURE)) return FormValidation.ok(); // can't check
if(value==null) // nothing entered yet
return FormValidation.ok();
return new URLCheck() {
protected FormValidation check() throws IOException, ServletException {
String v = value;
if(!v.endsWith("/")) v+='/';
try {
if (findText(open(new URL(v)),"sventon 2")) {
return FormValidation.ok();
} else if (findText(open(new URL(v)),"sventon")) {
return FormValidation.error("This is a valid Sventon URL but it doesn't look like Sventon 2.x");
} else{
return FormValidation.error("This is a valid URL but it doesn't look like Sventon");
}
} catch (IOException e) {
return handleIOException(v,e);
}
}
}.check();
}
}
private static final long serialVersionUID = 1L;
}
/*
* The MIT License
*
* Copyright (c) 2004-2009, Sun Microsystems, Inc., Kohsuke Kawaguchi
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE.
*/
package hudson.scm.browsers;
import hudson.model.Descriptor;
import hudson.scm.EditType;
import hudson.scm.RepositoryBrowser;
import hudson.scm.SubversionChangeLogSet;
import hudson.scm.SubversionChangeLogSet.Path;
import hudson.scm.SubversionRepositoryBrowser;
import hudson.Extension;
import org.kohsuke.stapler.StaplerRequest;
import org.kohsuke.stapler.DataBoundConstructor;
import java.io.IOException;
import java.net.MalformedURLException;
import java.net.URL;
/**
* {@link RepositoryBrowser} for Subversion.
*
* @author Kohsuke Kawaguchi
* @since 1.90
*/
// See http://viewvc.tigris.org/source/browse/*checkout*/viewvc/trunk/docs/url-reference.html
public class ViewSVN extends SubversionRepositoryBrowser {
/**
* The URL of the top of the site.
*
* Normalized to ends with '/', like <tt>http://svn.apache.org/viewvc/</tt>
* It may contain a query parameter like <tt>?root=foobar</tt>, so relative URL
* construction needs to be done with care.
*/
public final URL url;
@DataBoundConstructor
public ViewSVN(URL url) throws MalformedURLException {
this.url = normalizeToEndWithSlash(url);
}
@Override
public URL getDiffLink(Path path) throws IOException {
if(path.getEditType()!= EditType.EDIT)
return null; // no diff if this is not an edit change
int r = path.getLogEntry().getRevision();
return new URL(url,trimHeadSlash(path.getValue())+param().add("r1="+(r-1)).add("r2="+r));
}
@Override
public URL getFileLink(Path path) throws IOException {
return new URL(url,trimHeadSlash(path.getValue())+param());
}
@Override
public URL getChangeSetLink(SubversionChangeLogSet.LogEntry changeSet) throws IOException {
return new URL(url,"."+param().add("view=rev").add("rev="+changeSet.getRevision()));
}
private QueryBuilder param() {
return new QueryBuilder(url.getQuery());
}
private static final long serialVersionUID = 1L;
@Extension
public static final class DescriptorImpl extends Descriptor<RepositoryBrowser<?>> {
public String getDisplayName() {
return "ViewSVN";
}
}
}
/*
* The MIT License
*
* Copyright (c) 2004-2009, Sun Microsystems, Inc., Kohsuke Kawaguchi, Daniel Dyer
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE.
*/
package hudson.scm.browsers;
import hudson.model.Descriptor;
import hudson.scm.EditType;
import hudson.scm.RepositoryBrowser;
import hudson.scm.SubversionChangeLogSet;
import hudson.scm.SubversionChangeLogSet.Path;
import hudson.scm.SubversionRepositoryBrowser;
import hudson.Extension;
import org.kohsuke.stapler.StaplerRequest;
import org.kohsuke.stapler.DataBoundConstructor;
import java.io.IOException;
import java.net.MalformedURLException;
import java.net.URL;
/**
* {@link RepositoryBrowser} for Subversion. Assumes that WebSVN is
* configured with Multiviews enabled.
*
* @author jasonchaffee at dev.java.net
* @since 1.139
*/
public class WebSVN extends SubversionRepositoryBrowser {
@Extension
public static class DescriptorImpl extends Descriptor<RepositoryBrowser<?>> {
public String getDisplayName() {
return "WebSVN";
}
}
private static final long serialVersionUID = 1L;
/**
* The URL of the top of the site.
*
* <p>Normalized to ends with '/', like <tt>http://svn.apache.org/wsvn/</tt>
* It may contain a query parameter like <tt>?root=foobar</tt>, so relative
* URL construction needs to be done with care.</p>
*/
public final URL url;
/**
* Creates a new WebSVN object.
*
* @param url DOCUMENT ME!
*
* @throws MalformedURLException DOCUMENT ME!
*/
@DataBoundConstructor
public WebSVN(URL url) throws MalformedURLException {
this.url = normalizeToEndWithSlash(url);
}
/**
* Returns the diff link value.
*
* @param path the given path value.
*
* @return the diff link value.
*
* @throws IOException DOCUMENT ME!
*/
@Override public URL getDiffLink(Path path) throws IOException {
if (path.getEditType() != EditType.EDIT) {
return null; // no diff if this is not an edit change
}
int r = path.getLogEntry().getRevision();
return new URL(url,
trimHeadSlash(path.getValue()) +
param().add("op=diff").add("rev=" + r));
}
/**
* Returns the file link value.
*
* @param path the given path value.
*
* @return the file link value.
*
* @throws IOException DOCUMENT ME!
*/
@Override public URL getFileLink(Path path) throws IOException {
return new URL(url, trimHeadSlash(path.getValue()) + param());
}
/**
* Returns the change set link value.
*
* @param changeSet the given changeSet value.
*
* @return the change set link value.
*
* @throws IOException DOCUMENT ME!
*/
@Override public URL getChangeSetLink(SubversionChangeLogSet.LogEntry changeSet)
throws IOException {
return new URL(url,
"." +
param().add("rev=" + changeSet.getRevision()).add("sc=1"));
}
private QueryBuilder param() {
return new QueryBuilder(url.getQuery());
}
}
......@@ -32,7 +32,6 @@ import hudson.model.Hudson;
import hudson.model.User;
import hudson.scm.CVSSCM;
import hudson.scm.SCM;
import hudson.scm.SubversionSCM;
import java.util.HashMap;
import java.util.List;
......@@ -154,13 +153,6 @@ public abstract class MailAddressResolver implements ExtensionPoint {
String s = findMailAddressFor(u,cvsscm.getCvsRoot());
if(s!=null) return s;
}
if (scm instanceof SubversionSCM) {
SubversionSCM svn = (SubversionSCM) scm;
for (SubversionSCM.ModuleLocation loc : svn.getLocations(p.getLastBuild())) {
String s = findMailAddressFor(u,loc.remote);
if(s!=null) return s;
}
}
}
// didn't hit any known rules
......@@ -183,21 +175,16 @@ public abstract class MailAddressResolver implements ExtensionPoint {
static {
{// java.net
Pattern svnurl = Pattern.compile("https://[^.]+.dev.java.net/svn/([^/]+)(/.*)?");
String username = "([A-Za-z0-9_\\-])+";
String host = "(.*.dev.java.net|kohsuke.sfbay.*)";
Pattern cvsUrl = Pattern.compile(":pserver:"+username+"@"+host+":/cvs");
RULE_TABLE.put(svnurl,"@dev.java.net");
RULE_TABLE.put(cvsUrl,"@dev.java.net");
}
{// source forge
Pattern svnUrl = Pattern.compile("(http|https)://[^.]+.svn.(sourceforge|sf).net/svnroot/([^/]+)(/.*)?");
Pattern cvsUrl = Pattern.compile(":(pserver|ext):([^@]+)@([^.]+).cvs.(sourceforge|sf).net:.+");
RULE_TABLE.put(svnUrl,"@users.sourceforge.net");
RULE_TABLE.put(cvsUrl,"@users.sourceforge.net");
}
......
<!--
The MIT License
Copyright (c) 2004-2009, Sun Microsystems, Inc., Kohsuke Kawaguchi, Seiji Sogabe, id:cactusman
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in
all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
THE SOFTWARE.
-->
<j:jelly xmlns:j="jelly:core" xmlns:st="jelly:stapler" xmlns:d="jelly:define" xmlns:l="/lib/layout" xmlns:t="/lib/hudson" xmlns:f="/lib/form">
<st:documentation>
Displays the Subversion change log digest.
<st:attribute name="changesBaseUrl">
If specified, this is prepended in links to change details.
</st:attribute>
</st:documentation>
<j:set var="browser" value="${it.build.parent.scm.effectiveBrowser}"/>
<j:set var="rev" value="${it.revisionMap}" />
<j:choose>
<j:when test="${empty(rev)}">
<!-- nothing -->
</j:when>
<j:when test="${size(rev)==1}">
${%Revision}:
<j:forEach var="r" items="${rev}">${r.value}</j:forEach><!-- just print that one value-->
<br/>
</j:when>
<j:otherwise>
${%Revisions}
<ul>
<j:forEach var="r" items="${rev}">
<li>${r.key} : ${r.value}</li>
</j:forEach>
</ul>
</j:otherwise>
</j:choose>
<j:choose>
<j:when test="${it.emptySet}">
${%No changes.}
</j:when>
<j:otherwise>
${%Changes}
<ol>
<j:forEach var="cs" items="${it.logs}" varStatus="loop">
<li>
${cs.msgAnnotated}
(<a href="${changesBaseUrl}changes#detail${loop.index}">${%detail}</a>
<j:set var="cslink" value="${browser.getChangeSetLink(cs)}"/>
<j:if test="${cslink!=null}">
<j:text>/</j:text>
<a href="${cslink}">${browser.descriptor.displayName}</a>
</j:if>
<j:text>)</j:text>
</li>
</j:forEach>
</ol>
</j:otherwise>
</j:choose>
</j:jelly>
# The MIT License
#
# Copyright (c) 2004-2009, Sun Microsystems, Inc., Kohsuke Kawaguchi, Simon Wiest
#
# Permission is hereby granted, free of charge, to any person obtaining a copy
# of this software and associated documentation files (the "Software"), to deal
# in the Software without restriction, including without limitation the rights
# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
# copies of the Software, and to permit persons to whom the Software is
# furnished to do so, subject to the following conditions:
#
# The above copyright notice and this permission notice shall be included in
# all copies or substantial portions of the Software.
#
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
# THE SOFTWARE.
No\ changes.=Keine Änderungen.
# The MIT License
#
# Copyright (c) 2004-2009, Sun Microsystems, Inc., Kohsuke Kawaguchi, Eric Lefevre-Ardant
#
# Permission is hereby granted, free of charge, to any person obtaining a copy
# of this software and associated documentation files (the "Software"), to deal
# in the Software without restriction, including without limitation the rights
# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
# copies of the Software, and to permit persons to whom the Software is
# furnished to do so, subject to the following conditions:
#
# The above copyright notice and this permission notice shall be included in
# all copies or substantial portions of the Software.
#
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
# THE SOFTWARE.
No\ changes.=Aucun changement.
Revision=Révision
Revisions=Révisions
Changes=Changements
detail=détails
# The MIT License
#
# Copyright (c) 2004-2009, Sun Microsystems, Inc., Kohsuke Kawaguchi, Seiji Sogabe, id:cactusman
#
# Permission is hereby granted, free of charge, to any person obtaining a copy
# of this software and associated documentation files (the "Software"), to deal
# in the Software without restriction, including without limitation the rights
# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
# copies of the Software, and to permit persons to whom the Software is
# furnished to do so, subject to the following conditions:
#
# The above copyright notice and this permission notice shall be included in
# all copies or substantial portions of the Software.
#
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
# THE SOFTWARE.
Revision=\u30ea\u30d3\u30b8\u30e7\u30f3
Revisions=\u30ea\u30d3\u30b8\u30e7\u30f3
Changes=\u5909\u66f4
detail=\u8a73\u7d30
No\ changes.=\u5909\u66f4\u70b9\u306f\u3042\u308a\u307e\u305b\u3093\u3002
\ No newline at end of file
# The MIT License
#
# Copyright (c) 2004-2009, Sun Microsystems, Inc., Kohsuke Kawaguchi, id:sorokh
#
# Permission is hereby granted, free of charge, to any person obtaining a copy
# of this software and associated documentation files (the "Software"), to deal
# in the Software without restriction, including without limitation the rights
# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
# copies of the Software, and to permit persons to whom the Software is
# furnished to do so, subject to the following conditions:
#
# The above copyright notice and this permission notice shall be included in
# all copies or substantial portions of the Software.
#
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
# THE SOFTWARE.
No\ changes.=Geen wijzigingen.
# The MIT License
#
# Copyright (c) 2004-2009, Sun Microsystems, Inc., Kohsuke Kawaguchi, Reginaldo L. Russinholi
#
# Permission is hereby granted, free of charge, to any person obtaining a copy
# of this software and associated documentation files (the "Software"), to deal
# in the Software without restriction, including without limitation the rights
# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
# copies of the Software, and to permit persons to whom the Software is
# furnished to do so, subject to the following conditions:
#
# The above copyright notice and this permission notice shall be included in
# all copies or substantial portions of the Software.
#
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
# THE SOFTWARE.
No\ changes.=Sem mudan\u00E7as.
# The MIT License
#
# Copyright (c) 2004-2009, Sun Microsystems, Inc., Kohsuke Kawaguchi, Mike Salnikov
#
# Permission is hereby granted, free of charge, to any person obtaining a copy
# of this software and associated documentation files (the "Software"), to deal
# in the Software without restriction, including without limitation the rights
# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
# copies of the Software, and to permit persons to whom the Software is
# furnished to do so, subject to the following conditions:
#
# The above copyright notice and this permission notice shall be included in
# all copies or substantial portions of the Software.
#
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
# THE SOFTWARE.
No\ changes.=\u041d\u0435\u0442 \u0438\u0437\u043c\u0435\u043d\u0435\u043d\u0438\u0439.
# The MIT License
#
# Copyright (c) 2004-2009, Sun Microsystems, Inc., Kohsuke Kawaguchi, Oguz Dag
#
# Permission is hereby granted, free of charge, to any person obtaining a copy
# of this software and associated documentation files (the "Software"), to deal
# in the Software without restriction, including without limitation the rights
# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
# copies of the Software, and to permit persons to whom the Software is
# furnished to do so, subject to the following conditions:
#
# The above copyright notice and this permission notice shall be included in
# all copies or substantial portions of the Software.
#
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
# THE SOFTWARE.
No\ changes.=Herhangi\ bir\ de\u011fi\u015fiklik\ yok.
<!--
The MIT License
Copyright (c) 2004-2009, Sun Microsystems, Inc., Kohsuke Kawaguchi, id:cactusman
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in
all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
THE SOFTWARE.
-->
<!--
Displays the Subversion change log.
-->
<j:jelly xmlns:j="jelly:core" xmlns:st="jelly:stapler" xmlns:d="jelly:define" xmlns:l="/lib/layout" xmlns:t="/lib/hudson" xmlns:f="/lib/form">
<j:set var="browser" value="${it.build.parent.scm.effectiveBrowser}"/>
<h2>${%Summary}</h2>
<ol>
<j:forEach var="cs" items="${it.logs}">
<li><st:out value="${cs.msg}"/></li>
</j:forEach>
</ol>
<table class="pane" style="border:none">
<j:forEach var="cs" items="${it.logs}" varStatus="loop">
<tr class="pane">
<td colspan="2" class="changeset">
<a name="detail${loop.index}"></a>
<div class="changeset-message">
<b>
${%Revision}
<a href="${browser.getChangeSetLink(cs)}">${cs.revision}</a>
by <a href="${rootURL}/${cs.author.url}/">${cs.author}</a>:
</b><br/>
${cs.msgAnnotated}
</div>
</td>
</tr>
<j:forEach var="p" items="${cs.paths}">
<tr>
<td><t:editTypeIcon type="${p.editType}" /></td>
<td>
<a href="${browser.getFileLink(p)}">${p.value}</a>
<j:set var="diff" value="${browser.getDiffLink(p)}"/>
<j:if test="${diff!=null}">
<st:nbsp/>
<a href="${diff}">(diff)</a>
</j:if>
</td>
</tr>
</j:forEach>
</j:forEach>
</table>
</j:jelly>
\ No newline at end of file
# The MIT License
#
# Copyright (c) 2004-2009, Sun Microsystems, Inc., Kohsuke Kawaguchi, Simon Wiest
#
# Permission is hereby granted, free of charge, to any person obtaining a copy
# of this software and associated documentation files (the "Software"), to deal
# in the Software without restriction, including without limitation the rights
# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
# copies of the Software, and to permit persons to whom the Software is
# furnished to do so, subject to the following conditions:
#
# The above copyright notice and this permission notice shall be included in
# all copies or substantial portions of the Software.
#
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
# THE SOFTWARE.
Summary=Zusammenfassung
Revision=Revision
# The MIT License
#
# Copyright (c) 2004-2009, Sun Microsystems, Inc., Kohsuke Kawaguchi, Eric Lefevre-Ardant
#
# Permission is hereby granted, free of charge, to any person obtaining a copy
# of this software and associated documentation files (the "Software"), to deal
# in the Software without restriction, including without limitation the rights
# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
# copies of the Software, and to permit persons to whom the Software is
# furnished to do so, subject to the following conditions:
#
# The above copyright notice and this permission notice shall be included in
# all copies or substantial portions of the Software.
#
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
# THE SOFTWARE.
Summary=Résumé
Revision=Modification
# The MIT License
#
# Copyright (c) 2004-2009, Sun Microsystems, Inc., Kohsuke Kawaguchi, id:cactusman
#
# Permission is hereby granted, free of charge, to any person obtaining a copy
# of this software and associated documentation files (the "Software"), to deal
# in the Software without restriction, including without limitation the rights
# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
# copies of the Software, and to permit persons to whom the Software is
# furnished to do so, subject to the following conditions:
#
# The above copyright notice and this permission notice shall be included in
# all copies or substantial portions of the Software.
#
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
# THE SOFTWARE.
Summary=\u8981\u7d04
Revision=\u30ea\u30d3\u30b8\u30e7\u30f3
\ No newline at end of file
# The MIT License
#
# Copyright (c) 2004-2009, Sun Microsystems, Inc., Kohsuke Kawaguchi, id:sorokh
#
# Permission is hereby granted, free of charge, to any person obtaining a copy
# of this software and associated documentation files (the "Software"), to deal
# in the Software without restriction, including without limitation the rights
# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
# copies of the Software, and to permit persons to whom the Software is
# furnished to do so, subject to the following conditions:
#
# The above copyright notice and this permission notice shall be included in
# all copies or substantial portions of the Software.
#
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
# THE SOFTWARE.
Summary=Samenvatting
Revision=Revisie
# The MIT License
#
# Copyright (c) 2004-2009, Sun Microsystems, Inc., Kohsuke Kawaguchi, Reginaldo L. Russinholi
#
# Permission is hereby granted, free of charge, to any person obtaining a copy
# of this software and associated documentation files (the "Software"), to deal
# in the Software without restriction, including without limitation the rights
# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
# copies of the Software, and to permit persons to whom the Software is
# furnished to do so, subject to the following conditions:
#
# The above copyright notice and this permission notice shall be included in
# all copies or substantial portions of the Software.
#
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
# THE SOFTWARE.
Summary=Sum\u00E1rio
Revision=Revis\u00E3o
# The MIT License
#
# Copyright (c) 2004-2009, Sun Microsystems, Inc., Kohsuke Kawaguchi, Mike Salnikov
#
# Permission is hereby granted, free of charge, to any person obtaining a copy
# of this software and associated documentation files (the "Software"), to deal
# in the Software without restriction, including without limitation the rights
# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
# copies of the Software, and to permit persons to whom the Software is
# furnished to do so, subject to the following conditions:
#
# The above copyright notice and this permission notice shall be included in
# all copies or substantial portions of the Software.
#
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
# THE SOFTWARE.
Summary=\u0421\u0432\u043e\u0434\u043a\u0430
Revision=\u0420\u0435\u0432\u0438\u0437\u0438\u044f
# The MIT License
#
# Copyright (c) 2004-2009, Sun Microsystems, Inc., Kohsuke Kawaguchi, Oguz Dag
#
# Permission is hereby granted, free of charge, to any person obtaining a copy
# of this software and associated documentation files (the "Software"), to deal
# in the Software without restriction, including without limitation the rights
# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
# copies of the Software, and to permit persons to whom the Software is
# furnished to do so, subject to the following conditions:
#
# The above copyright notice and this permission notice shall be included in
# all copies or substantial portions of the Software.
#
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
# THE SOFTWARE.
Summary=\u00d6zet
Revision=Revizyon
<!--
The MIT License
Copyright (c) 2004-2009, Sun Microsystems, Inc., Kohsuke Kawaguchi, Seiji Sogabe
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in
all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
THE SOFTWARE.
-->
<j:jelly xmlns:j="jelly:core" xmlns:st="jelly:stapler" xmlns:d="jelly:define" xmlns:l="/lib/layout" xmlns:t="/lib/hudson" xmlns:f="/lib/form" xmlns:i="jelly:fmt">
<l:layout>
<l:header title="${%Subversion Authentication Successful}" />
<l:side-panel />
<l:main-panel>
${%Authentication was successful. Information is stored in Hudson now.}
</l:main-panel>
</l:layout>
</j:jelly>
\ No newline at end of file
# The MIT License
#
# Copyright (c) 2004-2009, Sun Microsystems, Inc., Kohsuke Kawaguchi, Eric Lefevre-Ardant
#
# Permission is hereby granted, free of charge, to any person obtaining a copy
# of this software and associated documentation files (the "Software"), to deal
# in the Software without restriction, including without limitation the rights
# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
# copies of the Software, and to permit persons to whom the Software is
# furnished to do so, subject to the following conditions:
#
# The above copyright notice and this permission notice shall be included in
# all copies or substantial portions of the Software.
#
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
# THE SOFTWARE.
Subversion\ Authentication\ Successful=Authentification Subversion réussie
Authentication\ was\ successful.\ Information\ is\ stored\ in\ Hudson\ now.= \
L''authentification est réussie. Stockage de l''information dans Hudson en cours.
# The MIT License
#
# Copyright (c) 2004-2009, Sun Microsystems, Inc., Kohsuke Kawaguchi, Seiji Sogabe
#
# Permission is hereby granted, free of charge, to any person obtaining a copy
# of this software and associated documentation files (the "Software"), to deal
# in the Software without restriction, including without limitation the rights
# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
# copies of the Software, and to permit persons to whom the Software is
# furnished to do so, subject to the following conditions:
#
# The above copyright notice and this permission notice shall be included in
# all copies or substantial portions of the Software.
#
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
# THE SOFTWARE.
Subversion\ Authentication\ Successful=Subversion\u306E\u8A8D\u8A3C\u306E\u6210\u529F
Authentication\ was\ successful.\ Information\ is\ stored\ in\ Hudson now.=\
\u8A8D\u8A3C\u304C\u6210\u529F\u3057\u307E\u3057\u305F\u3002\u60C5\u5831\u306FHudson\u306B\u4FDD\u5B58\u3055\u308C\u307E\u3059\u3002
\ No newline at end of file
<!--
The MIT License
Copyright (c) 2004-2009, Sun Microsystems, Inc., Kohsuke Kawaguchi, Seiji Sogabe
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in
all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
THE SOFTWARE.
-->
<j:jelly xmlns:j="jelly:core" xmlns:st="jelly:stapler" xmlns:d="jelly:define" xmlns:l="/lib/layout" xmlns:t="/lib/hudson" xmlns:f="/lib/form" xmlns:i="jelly:fmt">
<l:layout norefresh="true">
<l:header title="${%Subversion Authentication}" />
<l:side-panel />
<l:main-panel>
<h1>
<img src="${imagesURL}/48x48/secure.gif" width="48" height="48" alt=""/>
${%Subversion Authentication}
</h1>
<p>
${description}
</p>
<f:form method="post" action="postCredential" enctype="multipart/form-data">
<f:entry title="${%Repository URL}">
<f:textbox name="url" value="${request.queryString}" />
</f:entry>
<f:radioBlock name="kind" value="password" title="${%Username/password authentication}">
<f:entry title="${%User name}">
<f:textbox name="username1" />
</f:entry>
<f:entry title="${%Password}">
<input type="password" name="password1" class="setting-input" />
</f:entry>
</f:radioBlock>
<f:radioBlock name="kind" value="publickey" title="${%SSH public key authentication} (${%svn+ssh})">
<f:entry title="${%User name}">
<f:textbox name="username2" />
</f:entry>
<f:entry title="${%Pass phrase}" help="/help/subversion/pass-phrase.html">
<input type="password" name="password2" class="setting-input" />
</f:entry>
<f:entry title="${%Private key}">
<input type="file" name="privateKey" class="setting-input" />
</f:entry>
</f:radioBlock>
<f:radioBlock name="kind" value="certificate" title="${%HTTPS client certificate}">
<f:entry title="${%PKCS12 certificate}">
<input type="file" name="certificate" class="setting-input" />
</f:entry>
<f:entry title="${%Password}">
<input type="password" name="password3" class="setting-input" />
</f:entry>
</f:radioBlock>
<f:block>
<f:submit value="${%OK}" style="margin-top:1em;" />
</f:block>
</f:form>
</l:main-panel>
</l:layout>
</j:jelly>
\ No newline at end of file
# The MIT License
#
# Copyright (c) 2004-2009, Sun Microsystems, Inc., Kohsuke Kawaguchi, Seiji Sogabe
#
# Permission is hereby granted, free of charge, to any person obtaining a copy
# of this software and associated documentation files (the "Software"), to deal
# in the Software without restriction, including without limitation the rights
# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
# copies of the Software, and to permit persons to whom the Software is
# furnished to do so, subject to the following conditions:
#
# The above copyright notice and this permission notice shall be included in
# all copies or substantial portions of the Software.
#
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
# THE SOFTWARE.
description=\
Enter the authentication information needed to connect to the Subversion repository.\
This information will be stored in Hudson.
# The MIT License
#
# Copyright (c) 2004-2009, Sun Microsystems, Inc., Kohsuke Kawaguchi, Eric Lefevre-Ardant
#
# Permission is hereby granted, free of charge, to any person obtaining a copy
# of this software and associated documentation files (the "Software"), to deal
# in the Software without restriction, including without limitation the rights
# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
# copies of the Software, and to permit persons to whom the Software is
# furnished to do so, subject to the following conditions:
#
# The above copyright notice and this permission notice shall be included in
# all copies or substantial portions of the Software.
#
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
# THE SOFTWARE.
Subversion\ Authentication=Authentification Subversion
Repository\ URL=URL du repository
Username/password\ authentication=Authentification par nom d''utilisateur/mot de passe
User\ name=Nom d''utilisateur
Password=Mot de passe
SSH\ public\ key\ authentication=Authentification par clé publique SSH
svn+ssh=
Pass\ phrase=Phrase à retenir
Private\ key=Clé privée
HTTPS\ client\ certificate=Certificat HTTPS client
PKCS12\ certificate=Certificat PKCS12
OK=
description=\
Entrez les informations d''authentification nécessaires pour connecter au repository Subversion. \
Cette information sera stockée dans Hudson.
# The MIT License
#
# Copyright (c) 2004-2009, Sun Microsystems, Inc., Kohsuke Kawaguchi, Eric Lefevre-Ardant
#
# Permission is hereby granted, free of charge, to any person obtaining a copy
# of this software and associated documentation files (the "Software"), to deal
# in the Software without restriction, including without limitation the rights
# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
# copies of the Software, and to permit persons to whom the Software is
# furnished to do so, subject to the following conditions:
#
# The above copyright notice and this permission notice shall be included in
# all copies or substantial portions of the Software.
#
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
# THE SOFTWARE.
updateDescription=\
If checked, Hudson will use ''svn update'' whenever possible, making the build faster. \
But this causes the artifacts from the previous build to remain when a new build starts.
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册