package hudson.plugins.maven_scm; import hudson.FilePath; import hudson.FilePath.FileCallable; import hudson.Launcher; import hudson.model.AbstractBuild; import hudson.model.AbstractProject; import hudson.model.BuildListener; import hudson.model.TaskListener; import hudson.remoting.VirtualChannel; import hudson.scm.ChangeLogParser; import hudson.scm.SCM; import hudson.scm.SCMDescriptor; import org.apache.commons.io.FileUtils; import org.apache.maven.scm.ScmException; import org.apache.maven.scm.ScmFileSet; import org.apache.maven.scm.ScmResult; import org.apache.maven.scm.command.changelog.ChangeLogScmResult; import org.apache.maven.scm.command.checkout.CheckOutScmResult; import org.apache.maven.scm.manager.NoSuchScmProviderException; import org.apache.maven.scm.manager.ScmManager; import org.apache.maven.scm.repository.ScmRepository; import org.apache.maven.scm.repository.ScmRepositoryException; import java.io.File; import java.io.IOException; import java.io.PrintStream; import java.util.Date; import java.util.regex.Matcher; import java.util.regex.Pattern; /** * @author Kohsuke Kawaguchi */ public class MavenSCM extends SCM { /** * Maven SCM URL. */ public final String scmUrl; public MavenSCM(String scmUrl) { this.scmUrl = scmUrl; } /** * Gets the provider ID of SCM URL that identifies the provider, * such as "bazaar" * * @return * null if the prefix matching fails, which is most likely an operator error. */ public String getProvider() { Matcher m = PREFIX_PATTERN.matcher(scmUrl); if(m.find(0)) return m.group(1); else return null; } private static final Pattern PREFIX_PATTERN = Pattern.compile("scm:([a-z]+)[:|]"); @Override public boolean supportsPolling() { return false; } @Override public boolean pollChanges(AbstractProject project, Launcher launcher, FilePath workspace, TaskListener listener) throws IOException, InterruptedException { throw new UnsupportedOperationException(); } @Override public boolean checkout(AbstractBuild build, Launcher launcher, FilePath workspace, final BuildListener listener, File changelogFile) throws IOException, InterruptedException { final Date to = new Date(build.getTimestamp().getTimeInMillis()); final Date from; if(build.getPreviousBuild()!=null) from = new Date(build.getPreviousBuild().getTimestamp().getTimeInMillis()); else from = null; return workspace.act(new FileCallable<Boolean>() { public Boolean invoke(File ws, VirtualChannel channel) throws IOException { try { ScmManager scmManager = PluginImpl.MANAGER; ScmRepository repo = getScmRepository(scmManager); CheckOutScmResult result = scmManager.checkOut(repo, new ScmFileSet(ws) ); if(!result.isSuccess()) { listener.getLogger().println("Failed to checkout"); dumpFailure(result,listener); return false; } // remember what we've checked out FileUtils.writeStringToFile(new File(ws,".scmurl"),scmUrl,"UTF-8"); ChangeLogScmResult changelogResult = scmManager.changeLog(repo, new ScmFileSet(ws), from, to, -1, null); if(!changelogResult.isSuccess()) { listener.getLogger().println("Failed to compute changelog"); dumpFailure(changelogResult,listener); return false; } return true; } catch (ScmException e) { e.printStackTrace(listener.error("Failed to check out")); return false; } } }); } public ChangeLogParser createChangeLogParser() { // TODO throw new UnsupportedOperationException(); } /** * Use the best descriptor depending on our URL. */ @Override public SCMDescriptor<?> getDescriptor() { String provider = getProvider(); if(provider==null) return GenericMavenSCMDescriptor.INSTANCE; for (SCMDescriptor<?> d : SCM.all()) { if(d instanceof ProviderSpecificDescriptor && ((ProviderSpecificDescriptor)d).provider.equals(provider)) return d; } return GenericMavenSCMDescriptor.INSTANCE; } private void dumpFailure(ScmResult result, TaskListener listener) { PrintStream logger = listener.getLogger(); if(result.getProviderMessage()!=null) { logger.println("Provider message:"); logger.println(result.getProviderMessage()); } if(result.getCommandLine()!=null) { logger.println("Command line: "+result.getCommandLine()); } if(result.getCommandOutput()!=null) { logger.println("Command output:"); logger.println(result.getCommandOutput()); } } private ScmRepository getScmRepository(ScmManager scmManager) throws IOException { try { return scmManager.makeScmRepository(scmUrl); } catch (NoSuchScmProviderException ex) { throw new IOException("Could not find the SCM provider for "+scmUrl,ex); } catch (ScmRepositoryException ex) { throw new IOException("Error while connecting to "+scmUrl,ex); } } }