package hudson.plugins.mercurial; import hudson.Util; import hudson.model.Run; import hudson.scm.ChangeLogParser; import hudson.scm.RepositoryBrowser; import hudson.util.Digester2; import hudson.util.IOException2; import java.io.File; import java.io.IOException; import java.util.ArrayList; import java.util.Collections; import java.util.Comparator; import java.util.Iterator; import java.util.Set; import org.apache.commons.digester.Digester; import org.xml.sax.SAXException; /** * Parses the changelog.xml. * * See {@link MercurialChangeSet#CHANGELOG_TEMPLATE} for the format. */ public class MercurialChangeLogParser extends ChangeLogParser { private final Set<String> modules; public MercurialChangeLogParser(Set<String> modules) { this.modules = modules; } @Override public MercurialChangeSetList parse(Run build, RepositoryBrowser<?> browser, File changelogFile) throws IOException, SAXException { Digester digester = new Digester2(); ArrayList<MercurialChangeSet> r = new ArrayList<MercurialChangeSet>(); digester.push(r); digester.addObjectCreate("*/changeset", MercurialChangeSet.class); digester.addSetProperties("*/changeset"); digester.addSetProperties("*/changeset", "author", "user"); digester.addBeanPropertySetter("*/changeset/msg"); digester.addBeanPropertySetter("*/changeset/added"); digester.addBeanPropertySetter("*/changeset/deleted"); digester.addBeanPropertySetter("*/changeset/files"); digester.addBeanPropertySetter("*/changeset/parents"); digester.addSetNext("*/changeset", "add"); 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 + ": '" + Util.loadFile(changelogFile) + "'", e); } if (modules != null) { Iterator<MercurialChangeSet> it = r.iterator(); while (it.hasNext()) { boolean include = false; INCLUDE: for (String path : it.next().getAffectedPaths()) { for (String module : modules) { if (path.startsWith(module)) { include = true; break INCLUDE; } } } if (!include) { it.remove(); } } } // sort the changes from oldest to newest, this gives the best result in // the Jenkins changes view, // and is like the old situation where 'hg incoming' was used to // determine the changelog Collections.sort(r, new Comparator<MercurialChangeSet>() { public int compare(MercurialChangeSet o1, MercurialChangeSet o2) { // don't do return o1.getRev() - o2.getRev(), as that is // susceptible to integer overflow if (o1.getRev() < o2.getRev()) { return -1; } if (o1.getRev() == o2.getRev()) { return 0; } else { return 1; } } }); return new MercurialChangeSetList(build, browser, r); } }