diff --git a/plugins/scm-hg-plugin/src/main/java/sonia/scm/repository/HgChangesetViewer.java b/plugins/scm-hg-plugin/src/main/java/sonia/scm/repository/HgChangesetViewer.java new file mode 100644 index 0000000000..e2f63d39c0 --- /dev/null +++ b/plugins/scm-hg-plugin/src/main/java/sonia/scm/repository/HgChangesetViewer.java @@ -0,0 +1,213 @@ +/** + * Copyright (c) 2010, Sebastian Sdorra + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * 3. Neither the name of SCM-Manager; nor the names of its + * contributors may be used to endorse or promote products derived from this + * software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY + * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON + * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * http://bitbucket.org/sdorra/scm-manager + * + */ + + + +package sonia.scm.repository; + +//~--- non-JDK imports -------------------------------------------------------- + +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import sonia.scm.io.Command; +import sonia.scm.io.CommandResult; +import sonia.scm.io.SimpleCommand; +import sonia.scm.util.IOUtil; +import sonia.scm.util.Util; + +//~--- JDK imports ------------------------------------------------------------ + +import java.io.IOException; +import java.io.InputStream; +import java.io.StringReader; + +import java.util.List; + +import javax.xml.bind.JAXBException; +import javax.xml.bind.Unmarshaller; +import javax.xml.bind.annotation.XmlElement; +import javax.xml.bind.annotation.XmlRootElement; + +/** + * + * @author Sebastian Sdorra + */ +public class HgChangesetViewer implements ChangesetViewer +{ + + /** Field description */ + public static final String ID_TIP = "tip"; + + /** Field description */ + public static final String TEMPLATE = + "{rev}:{short}{author|escape}{desc|escape}{date|isodatesec}"; + + /** the logger for HgChangesetViewer */ + private static final Logger logger = + LoggerFactory.getLogger(HgChangesetViewer.class); + + //~--- constructors --------------------------------------------------------- + + /** + * Constructs ... + * + * + * + * @param handler + * @param repository + */ + public HgChangesetViewer(HgRepositoryHandler handler, Repository repository) + { + this.handler = handler; + this.repository = repository; + } + + //~--- get methods ---------------------------------------------------------- + + /** + * TODO unmarshall date + * + * + * @param startId + * @param max + * + * @return + */ + @Override + public List getChangesets(String startId, int max) + { + List changesets = null; + InputStream in = null; + + try + { + String repositoryPath = getRepositoryPath(repository); + Command command = new SimpleCommand(handler.getConfig().getHgBinary(), + "-R", repositoryPath, "log", "-r", "tip:0", "-l", + String.valueOf(max), "--template", TEMPLATE); + CommandResult result = command.execute(); + + if (result.isSuccessfull()) + { + StringBuilder changesetLog = new StringBuilder(""); + + changesetLog.append(result.getOutput()); + changesetLog.append(""); + + StringReader reader = new StringReader(changesetLog.toString()); + Unmarshaller unmarshaller = handler.createChangesetUnmarshaller(); + Changesets cs = (Changesets) unmarshaller.unmarshal(reader); + + if ((cs != null) && Util.isNotEmpty(cs.changesets)) + { + changesets = cs.changesets; + } + else if (logger.isWarnEnabled()) + { + logger.warn("could not find any changeset from {} to +{}", startId, + max); + } + } + else + { + logger.error("could not load changesets, hg return code: {}\n{}", + result.getReturnCode(), result.getOutput()); + } + } + catch (IOException ex) + { + logger.error("could not load changesets", ex); + } + catch (JAXBException ex) + { + logger.error("could not unmarshall changesets", ex); + } + finally + { + IOUtil.close(in); + } + + return changesets; + } + + /** + * Method description + * + * + * @param max + * + * @return + */ + @Override + public List getLastChangesets(int max) + { + return getChangesets(ID_TIP, max); + } + + /** + * Method description + * + * + * @param repository + * + * @return + */ + private String getRepositoryPath(Repository repository) + { + return handler.getDirectory(repository).getAbsolutePath(); + } + + //~--- inner classes -------------------------------------------------------- + + /** + * Class description + * + * @author Sebastian Sdorra + */ + @XmlRootElement(name = "changesets") + private static class Changesets + { + + /** Field description */ + @XmlElement(name = "changeset") + private List changesets; + } + + + //~--- fields --------------------------------------------------------------- + + /** Field description */ + private HgRepositoryHandler handler; + + /** Field description */ + private Repository repository; +} diff --git a/plugins/scm-hg-plugin/src/main/java/sonia/scm/repository/HgRepositoryHandler.java b/plugins/scm-hg-plugin/src/main/java/sonia/scm/repository/HgRepositoryHandler.java index a71278c9fc..d11ae8b3d0 100644 --- a/plugins/scm-hg-plugin/src/main/java/sonia/scm/repository/HgRepositoryHandler.java +++ b/plugins/scm-hg-plugin/src/main/java/sonia/scm/repository/HgRepositoryHandler.java @@ -40,16 +40,19 @@ import com.google.inject.Singleton; import org.slf4j.LoggerFactory; +import sonia.scm.ConfigurationException; import sonia.scm.Type; import sonia.scm.installer.HgInstaller; import sonia.scm.installer.UnixHgInstaller; import sonia.scm.installer.WindowsHgInstaller; import sonia.scm.io.ExtendedCommand; +import sonia.scm.io.FileSystem; import sonia.scm.io.INIConfiguration; import sonia.scm.io.INIConfigurationWriter; import sonia.scm.io.INISection; import sonia.scm.plugin.ext.Extension; import sonia.scm.store.StoreFactory; +import sonia.scm.util.AssertUtil; import sonia.scm.util.SystemUtil; import sonia.scm.web.HgWebConfigWriter; @@ -57,7 +60,10 @@ import sonia.scm.web.HgWebConfigWriter; import java.io.File; import java.io.IOException; -import sonia.scm.io.FileSystem; + +import javax.xml.bind.JAXBContext; +import javax.xml.bind.JAXBException; +import javax.xml.bind.Unmarshaller; /** * @@ -89,11 +95,22 @@ public class HgRepositoryHandler * * * @param storeFactory + * @param fileSystem */ @Inject public HgRepositoryHandler(StoreFactory storeFactory, FileSystem fileSystem) { super(storeFactory, fileSystem); + + try + { + changesetContext = JAXBContext.newInstance(Changeset.class); + } + catch (JAXBException ex) + { + throw new ConfigurationException( + "could not create JAXBContext for Changeset-Class", ex); + } } //~--- methods -------------------------------------------------------------- @@ -174,6 +191,37 @@ public class HgRepositoryHandler //~--- get methods ---------------------------------------------------------- + /** + * Method description + * + * + * @param repository + * + * @return + */ + @Override + public ChangesetViewer getChangesetViewer(Repository repository) + { + HgChangesetViewer changesetViewer; + + AssertUtil.assertIsNotNull(repository); + + String type = repository.getType(); + + AssertUtil.assertIsNotEmpty(type); + + if (TYPE_NAME.equals(type)) + { + changesetViewer = new HgChangesetViewer(this, repository); + } + else + { + throw new IllegalArgumentException("mercurial repository is required"); + } + + return changesetViewer; + } + /** * Method description * @@ -188,6 +236,29 @@ public class HgRepositoryHandler //~--- methods -------------------------------------------------------------- + /** + * Method description + * + * + * @return + */ + Unmarshaller createChangesetUnmarshaller() + { + Unmarshaller unmarshaller = null; + + try + { + unmarshaller = changesetContext.createUnmarshaller(); + } + catch (JAXBException ex) + { + throw new ConfigurationException( + "could not create Unmarshaller for Changeset-Class", ex); + } + + return unmarshaller; + } + /** * Method description * @@ -247,4 +318,9 @@ public class HgRepositoryHandler { return HgConfig.class; } + + //~--- fields --------------------------------------------------------------- + + /** Field description */ + private JAXBContext changesetContext; }