hudson.scm.SubversionRepositoryStatus Maven / Gradle / Ivy
Show all versions of subversion Show documentation
/*
* The MIT License
*
* Copyright (c) 2004-2011, Sun Microsystems, Inc., Kohsuke Kawaguchi, Patrick van Dissel (id:pvdissel).
*
* 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.AbstractProject;
import hudson.model.Hudson;
import hudson.scm.SubversionSCM.ModuleLocation;
import hudson.scm.SubversionSCM.SvnInfo;
import hudson.triggers.SCMTrigger;
import hudson.util.QueryParameterMap;
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.*;
import java.util.logging.Logger;
import javax.servlet.ServletException;
import static javax.servlet.http.HttpServletResponse.SC_OK;
import org.apache.commons.io.IOUtils;
import org.kohsuke.stapler.StaplerRequest;
import org.kohsuke.stapler.StaplerResponse;
import org.tmatesoft.svn.core.SVNException;
/**
* 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.
*
*
* 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 post-commit script set up.
*/
public void doNotifyCommit(StaplerRequest req, StaplerResponse rsp) throws ServletException, IOException {
requirePOST();
// compute the affected paths
Set affectedPath = new HashSet();
String line;
BufferedReader r = new BufferedReader(req.getReader());
try {
while ((line = r.readLine()) != null) {
if (LOGGER.isLoggable(FINER)) {
LOGGER.finer("Reading line: " + line);
}
affectedPath.add(line.substring(4));
if (line.startsWith("svnlook changed --revision ")) {
String msg = "Expecting the output from the svnlook command but instead you just sent me the svnlook invocation command line: " + line;
LOGGER.warning(msg);
throw new IllegalArgumentException(msg);
}
}
} finally {
IOUtils.closeQuietly(r);
}
if (LOGGER.isLoggable(FINE)) {
LOGGER.fine("Change reported to Subversion repository " + uuid + " on " + affectedPath);
}
boolean scmFound = false, triggerFound = false, uuidFound = false, pathFound = false;
// we can't reliably use req.getParameter() as it can try to parse the payload, which we've already consumed above.
// servlet container relies on Content-type to decide if it wants to parse the payload or not, and at least
// in case of Jetty, it doesn't check if the payload is
QueryParameterMap query = new QueryParameterMap(req);
String revParam = query.get("rev");
long rev = -1;
if (revParam != null) {
rev = Long.parseLong(revParam);
} else {
revParam = req.getHeader("X-Hudson-Subversion-Revision");
if (revParam != null) {
rev = Long.parseLong(revParam);
}
}
OUTER:
for (AbstractProject, ?> p : Hudson.getInstance().getItems(AbstractProject.class)) {
try {
SCM scm = p.getScm();
if (scm instanceof SubversionSCM) {
scmFound = true;
} else {
continue;
}
SCMTrigger trigger = p.getTrigger(SCMTrigger.class);
if (trigger != null) {
triggerFound = true;
} else {
continue;
}
if (p.isDisabled()) {
continue;
}
SubversionSCM sscm = (SubversionSCM) scm;
if (sscm.isIgnoreCommitNotification()) {
continue;
}
for (ModuleLocation loc : sscm.getLocations()) {
if (loc.getUUID(p).equals(uuid)) {
uuidFound = true;
} else {
continue;
}
String m = loc.getSVNURL().getPath();
String n = loc.getRepositoryRoot(p).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 + '/';
final RevisionParameterAction[] actions;
if (rev != -1) {
SvnInfo info[] = {new SvnInfo(loc.getURL(), rev)};
RevisionParameterAction action = new RevisionParameterAction(info);
actions = new RevisionParameterAction[]{action};
} else {
actions = new RevisionParameterAction[0];
}
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 change
LOGGER.info("Scheduling the immediate polling of " + p);
trigger.run(actions);
pathFound = true;
continue OUTER;
}
}
}
} catch (SVNException e) {
LOGGER.log(WARNING, "Failed to handle Subversion commit notification", e);
}
}
if (!scmFound) {
LOGGER.warning("No subversion jobs found");
} else if (!triggerFound) {
LOGGER.warning("No subversion jobs using SCM polling");
} else if (!uuidFound) {
LOGGER.warning("No enabled subversion jobs using repository: " + uuid);
} else if (!pathFound) {
LOGGER.fine("No jobs found matching the modified files");
}
rsp.setStatus(SC_OK);
}
private static final Logger LOGGER = Logger.getLogger(SubversionRepositoryStatus.class.getName());
}