package com.mtvi.plateng.hudson.svnimport;
import hudson.Extension;
import hudson.FilePath;
import hudson.Launcher;
import hudson.FilePath.FileCallable;
import hudson.model.AbstractBuild;
import hudson.model.AbstractProject;
import hudson.model.BuildListener;
import hudson.model.Result;
import hudson.remoting.VirtualChannel;
import hudson.tasks.BuildStepDescriptor;
import hudson.tasks.BuildStepMonitor;
import hudson.tasks.Notifier;
import hudson.tasks.Publisher;
import java.io.File;
import java.io.IOException;
import java.util.ArrayList;
import java.util.List;
import java.util.logging.Logger;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
import org.kohsuke.stapler.DataBoundConstructor;
import org.tmatesoft.svn.core.SVNDepth;
import org.tmatesoft.svn.core.SVNException;
import org.tmatesoft.svn.core.SVNURL;
import org.tmatesoft.svn.core.wc.SVNClientManager;
public class SubversionImporter extends Notifier {
private static final Logger LOGGER = Logger.getLogger(SubversionImporter.class.getName());
public final String artifactExpression;
private final Pattern artifactPattern;
public final String baseUrl;
private final SVNURL baseSvnUrl;
public final String importExpression;
private final SVNClientManager svnClientManager;
@DataBoundConstructor
public SubversionImporter(String artficatExpression, String baseUrl, String importExpression)
throws SVNException {
this.artifactExpression = artficatExpression;
this.artifactPattern = Pattern.compile(artifactExpression);
this.baseUrl = baseUrl;
baseSvnUrl = SVNURL.parseURIEncoded(baseUrl);
this.importExpression = importExpression;
this.svnClientManager = SVNClientManager.newInstance();
}
public List<ImportItem> getItemsToImport(FilePath workspace) throws SVNException, IOException,
InterruptedException {
String workspaceURI = workspace.toURI().toString();
FilePath[] files = workspace.list("**/*");
List<ImportItem> items = new ArrayList<ImportItem>();
for (FilePath file : files) {
String filePath = file.toURI().toString().substring(workspaceURI.length() - 1);
String output = importExpression;
Matcher matcher = artifactPattern.matcher(filePath);
if (matcher.matches()) {
for (int i = 1; i <= matcher.groupCount(); i++) {
output = output.replace("$" + i, matcher.group(i));
}
items.add(new ImportItem(file, baseSvnUrl.appendPath(output, false)));
}
}
return items;
}
@Override
public boolean perform(AbstractBuild<?, ?> build, Launcher launcher, BuildListener listener)
throws InterruptedException, IOException {
try {
if (build.getResult() == Result.SUCCESS) {
FilePath workspace = build.getWorkspace();
List<ImportItem> items = getItemsToImport(workspace);
for (final ImportItem importItem : items) {
importItem.path.act(new FileCallable<Boolean>() {
public Boolean invoke(File f, VirtualChannel channel) throws IOException {
try {
svnClientManager.getCommitClient().doImport(f,
importItem.svnDestination, "", null, false, false, SVNDepth.EMPTY);
return true;
} catch (SVNException e) {
throw new IOException("Unable to import " + f.getAbsolutePath()
+ " " + e.getMessage());
}
}
});
}
}
} catch (SVNException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
return true;
}
public BuildStepMonitor getRequiredMonitorService() {
return BuildStepMonitor.BUILD;
}
@Extension
public static final class DescriptorImpl extends BuildStepDescriptor<Publisher> {
public DescriptorImpl() {
super(SubversionImporter.class);
}
@Override
public String getDisplayName() {
return "Subversion Importer";
}
@Override
public boolean isApplicable(Class<? extends AbstractProject> jobType) {
return true;
}
}
public class ImportItem {
public final FilePath path;
public final SVNURL svnDestination;
public ImportItem(FilePath path, SVNURL svnDestination) {
this.path = path;
this.svnDestination = svnDestination;
}
}
}