package hudson.plugins.mantis;
import hudson.model.AbstractBuild;
import hudson.model.BuildListener;
import hudson.model.Hudson;
import hudson.model.Result;
import hudson.model.Run;
import hudson.model.AbstractBuild.DependencyChange;
import hudson.plugins.mantis.changeset.ChangeSet;
import hudson.plugins.mantis.changeset.ChangeSetFactory;
import hudson.plugins.mantis.model.MantisIssue;
import hudson.scm.ChangeLogSet.Entry;
import java.io.PrintStream;
import java.util.ArrayList;
import java.util.List;
import java.util.logging.Level;
import java.util.logging.Logger;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
/**
* Mantis update Logic.
*
* @author Seiji Sogabe
*/
final class Updater {
private static final String CRLF = System.getProperty("line.separator");
private final MantisIssueUpdater property;
Updater(final MantisIssueUpdater property) {
this.property = property;
}
boolean perform(final AbstractBuild<?, ?> build, final BuildListener listener) {
final PrintStream logger = listener.getLogger();
final MantisSite site = MantisSite.get(build.getProject());
if (site == null) {
Utility.log(logger, Messages.Updater_NoMantisSite());
build.setResult(Result.FAILURE);
return true;
}
final String rootUrl = Hudson.getInstance().getRootUrl();
if (rootUrl == null) {
Utility.log(logger, Messages.Updater_NoHudsonUrl());
build.setResult(Result.FAILURE);
return true;
}
final List<ChangeSet> chnageSets = findChangeSets(build);
if (chnageSets.isEmpty()) {
Utility.log(logger, Messages.Updater_NoIssuesFound());
return true;
}
final boolean update = !build.getResult().isWorseThan(Result.UNSTABLE);
if (!update) {
// Keep id for next build
Utility.log(logger, Messages.Updater_KeepMantisIssueIdsForNextBuild());
build.addAction(new MantisCarryOverChangeSetAction(chnageSets));
}
final List<MantisIssue> issues = new ArrayList<MantisIssue>();
for (final ChangeSet changeSet : chnageSets) {
try {
final MantisIssue issue = site.getIssue(changeSet.getId());
if (update) {
final String text = createUpdateText(build, changeSet, rootUrl);
site.updateIssue(changeSet.getId(), text, property.isKeepNotePrivate());
Utility.log(logger, Messages.Updater_Updating(changeSet.getId()));
}
issues.add(issue);
} catch (final MantisHandlingException e) {
Utility.log(logger, Messages.Updater_FailedToAddNote(changeSet, e.getMessage()));
LOGGER.log(Level.WARNING, Messages.Updater_FailedToAddNote_StarckTrace(changeSet), e);
}
}
final MantisProjectProperty mpp =
build.getParent().getProperty(MantisProjectProperty.class);
build.getActions().add(
new MantisBuildAction(mpp.getRegexpPattern(), issues.toArray(new MantisIssue[0])));
return true;
}
private String createUpdateText(final AbstractBuild<?, ?> build, final ChangeSet changeSet, final String rootUrl) {
final String prjName = build.getProject().getName();
final int prjNumber = build.getNumber();
final String url = rootUrl + build.getUrl();
final StringBuilder text = new StringBuilder();
text.append(Messages.Updater_IssueIntegrated(prjName, prjNumber, url));
text.append(CRLF).append(CRLF);
if (property.isRecordChangelog()) {
text.append(changeSet.createChangeLog());
}
return text.toString();
}
private List<ChangeSet> findChangeSets(final AbstractBuild<?, ?> build) {
final List<ChangeSet> chnageSets = new ArrayList<ChangeSet>();
final Run<?, ?> prev = build.getPreviousBuild();
if (prev != null) {
final MantisCarryOverChangeSetAction changeSetAction = prev.getAction(MantisCarryOverChangeSetAction.class);
if (changeSetAction != null) {
for (final ChangeSet changeSet : changeSetAction.getChangeSets()) {
chnageSets.add(changeSet);
}
}
}
chnageSets.addAll(findChangeSetsFromSCM(build));
for (final DependencyChange depc : build.getDependencyChanges(
build.getPreviousBuild()).values()) {
for (final AbstractBuild<?, ?> b : depc.getBuilds()) {
chnageSets.addAll(findChangeSetsFromSCM(b));
}
}
return chnageSets;
}
private List<ChangeSet> findChangeSetsFromSCM(final AbstractBuild<?, ?> build) {
final List<ChangeSet> changeSets = new ArrayList<ChangeSet>();
final MantisProjectProperty mpp = build.getParent().getProperty(MantisProjectProperty.class);
final Pattern pattern = mpp.getRegexpPattern();
for (final Entry change : build.getChangeSet()) {
final Matcher matcher = pattern.matcher(change.getMsg());
while (matcher.find()) {
int id;
try {
id = Integer.parseInt(matcher.group(1));
} catch (final NumberFormatException e) {
// if id is not number, skip
LOGGER.log(Level.WARNING, Messages.Updater_IllegalMantisId(matcher.group(1)));
continue;
}
changeSets.add(ChangeSetFactory.newInstance(id, build, change));
}
}
return changeSets;
}
private static final Logger LOGGER = Logger.getLogger(Updater.class.getName());
}