mirror of
https://github.com/scm-manager/scm-manager.git
synced 2025-11-10 15:35:49 +01:00
improve performance of mercurial changesetviewer
This commit is contained in:
@@ -37,7 +37,6 @@ package sonia.scm.repository;
|
|||||||
|
|
||||||
import com.google.inject.Inject;
|
import com.google.inject.Inject;
|
||||||
|
|
||||||
import java.io.IOException;
|
|
||||||
import org.slf4j.Logger;
|
import org.slf4j.Logger;
|
||||||
import org.slf4j.LoggerFactory;
|
import org.slf4j.LoggerFactory;
|
||||||
|
|
||||||
@@ -49,6 +48,8 @@ import sonia.scm.util.Util;
|
|||||||
|
|
||||||
//~--- JDK imports ------------------------------------------------------------
|
//~--- JDK imports ------------------------------------------------------------
|
||||||
|
|
||||||
|
import java.io.IOException;
|
||||||
|
|
||||||
import java.util.Set;
|
import java.util.Set;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -103,6 +104,8 @@ public class ChangesetViewerUtil extends CacheClearHook
|
|||||||
*
|
*
|
||||||
* @return
|
* @return
|
||||||
*
|
*
|
||||||
|
*
|
||||||
|
* @throws IOException
|
||||||
* @throws NotSupportedFeatuerException
|
* @throws NotSupportedFeatuerException
|
||||||
* @throws RepositoryException
|
* @throws RepositoryException
|
||||||
*/
|
*/
|
||||||
@@ -133,6 +136,8 @@ public class ChangesetViewerUtil extends CacheClearHook
|
|||||||
*
|
*
|
||||||
* @return
|
* @return
|
||||||
*
|
*
|
||||||
|
*
|
||||||
|
* @throws IOException
|
||||||
* @throws NotSupportedFeatuerException
|
* @throws NotSupportedFeatuerException
|
||||||
* @throws RepositoryException
|
* @throws RepositoryException
|
||||||
*/
|
*/
|
||||||
|
|||||||
@@ -38,25 +38,18 @@ package sonia.scm.repository;
|
|||||||
import org.slf4j.Logger;
|
import org.slf4j.Logger;
|
||||||
import org.slf4j.LoggerFactory;
|
import org.slf4j.LoggerFactory;
|
||||||
|
|
||||||
import org.xml.sax.InputSource;
|
import sonia.scm.util.AssertUtil;
|
||||||
import org.xml.sax.SAXException;
|
import sonia.scm.web.HgUtil;
|
||||||
|
|
||||||
import sonia.scm.io.Command;
|
|
||||||
import sonia.scm.io.CommandResult;
|
|
||||||
import sonia.scm.io.SimpleCommand;
|
|
||||||
import sonia.scm.util.IOUtil;
|
|
||||||
|
|
||||||
//~--- JDK imports ------------------------------------------------------------
|
//~--- JDK imports ------------------------------------------------------------
|
||||||
|
|
||||||
|
import java.io.File;
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
import java.io.InputStream;
|
|
||||||
import java.io.StringReader;
|
|
||||||
|
|
||||||
import java.util.HashMap;
|
import java.util.HashMap;
|
||||||
import java.util.List;
|
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
|
|
||||||
import javax.xml.parsers.ParserConfigurationException;
|
import javax.xml.bind.JAXBContext;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
*
|
*
|
||||||
@@ -65,30 +58,17 @@ import javax.xml.parsers.ParserConfigurationException;
|
|||||||
public class HgChangesetViewer implements ChangesetViewer
|
public class HgChangesetViewer implements ChangesetViewer
|
||||||
{
|
{
|
||||||
|
|
||||||
/** Field description */
|
|
||||||
public static final String ID_TIP = "tip";
|
|
||||||
|
|
||||||
/** Field description */
|
|
||||||
//J-
|
|
||||||
public static final String TEMPLATE_CHANGESETS =
|
|
||||||
"\"<changeset>"
|
|
||||||
+ "<id>{rev}:{node|short}</id>"
|
|
||||||
+ "<author>{author|escape}</author>"
|
|
||||||
+ "<description>{desc|escape}</description>"
|
|
||||||
+ "<date>{date|isodatesec}</date>"
|
|
||||||
+ "<tags>{tags}</tags>"
|
|
||||||
+ "<branches>{branches}</branches>"
|
|
||||||
+ "<files-added>{file_adds}</files-added>"
|
|
||||||
+ "<files-mods>{file_mods}</files-mods>"
|
|
||||||
+ "<files-dels>{file_dels}</files-dels>"
|
|
||||||
+ "</changeset>\"";
|
|
||||||
//J+
|
|
||||||
|
|
||||||
/** Field description */
|
/** Field description */
|
||||||
public static final String ENV_PENDING = "HG_PENDING";
|
public static final String ENV_PENDING = "HG_PENDING";
|
||||||
|
|
||||||
/** Field description */
|
/** Field description */
|
||||||
public static final String TEMPLATE_TOTAL = "{rev}";
|
public static final String ENV_REVISION_LIMIT = "SCM_REVISION_LIMIT";
|
||||||
|
|
||||||
|
/** Field description */
|
||||||
|
public static final String ENV_REVISION_START = "SCM_REVISION_START";
|
||||||
|
|
||||||
|
/** Field description */
|
||||||
|
public static final String RESOURCE_LOG = "/sonia/scm/hglog.py";
|
||||||
|
|
||||||
/** the logger for HgChangesetViewer */
|
/** the logger for HgChangesetViewer */
|
||||||
private static final Logger logger =
|
private static final Logger logger =
|
||||||
@@ -102,11 +82,16 @@ public class HgChangesetViewer implements ChangesetViewer
|
|||||||
*
|
*
|
||||||
*
|
*
|
||||||
* @param handler
|
* @param handler
|
||||||
* @param repository
|
* @param repositoryDirectory
|
||||||
|
* @param changesetPagingResultContext
|
||||||
*/
|
*/
|
||||||
public HgChangesetViewer(HgRepositoryHandler handler, Repository repository)
|
public HgChangesetViewer(HgRepositoryHandler handler,
|
||||||
|
File repositoryDirectory,
|
||||||
|
JAXBContext changesetPagingResultContext)
|
||||||
{
|
{
|
||||||
this(handler, handler.getDirectory(repository).getAbsolutePath());
|
this.handler = handler;
|
||||||
|
this.repositoryDirectory = repositoryDirectory;
|
||||||
|
this.changesetPagingResultContext = changesetPagingResultContext;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -114,12 +99,14 @@ public class HgChangesetViewer implements ChangesetViewer
|
|||||||
*
|
*
|
||||||
*
|
*
|
||||||
* @param handler
|
* @param handler
|
||||||
* @param repositoryPath
|
* @param repository
|
||||||
|
* @param changesetPagingResultContext
|
||||||
*/
|
*/
|
||||||
public HgChangesetViewer(HgRepositoryHandler handler, String repositoryPath)
|
public HgChangesetViewer(HgRepositoryHandler handler, Repository repository,
|
||||||
|
JAXBContext changesetPagingResultContext)
|
||||||
{
|
{
|
||||||
this.handler = handler;
|
this(handler, handler.getDirectory(repository),
|
||||||
this.repositoryPath = repositoryPath;
|
changesetPagingResultContext);
|
||||||
}
|
}
|
||||||
|
|
||||||
//~--- get methods ----------------------------------------------------------
|
//~--- get methods ----------------------------------------------------------
|
||||||
@@ -131,51 +118,14 @@ public class HgChangesetViewer implements ChangesetViewer
|
|||||||
* @param max
|
* @param max
|
||||||
*
|
*
|
||||||
* @return
|
* @return
|
||||||
|
*
|
||||||
|
* @throws IOException
|
||||||
*/
|
*/
|
||||||
@Override
|
@Override
|
||||||
public ChangesetPagingResult getChangesets(int start, int max)
|
public ChangesetPagingResult getChangesets(int start, int max)
|
||||||
|
throws IOException
|
||||||
{
|
{
|
||||||
ChangesetPagingResult changesets = null;
|
return getChangesets(String.valueOf(start), String.valueOf(max), false);
|
||||||
InputStream in = null;
|
|
||||||
|
|
||||||
try
|
|
||||||
{
|
|
||||||
int total = getTotalChangesets(repositoryPath);
|
|
||||||
int startRev = total - start;
|
|
||||||
int endRev = total - start - (max - 1);
|
|
||||||
|
|
||||||
if (endRev < 0)
|
|
||||||
{
|
|
||||||
endRev = 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
List<Changeset> changesetList = getChangesets(Integer.toString(startRev),
|
|
||||||
Integer.toString(endRev));
|
|
||||||
|
|
||||||
if (changesetList != null)
|
|
||||||
{
|
|
||||||
if (total == -1)
|
|
||||||
{
|
|
||||||
total = 0;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
total++;
|
|
||||||
}
|
|
||||||
|
|
||||||
changesets = new ChangesetPagingResult(total, changesetList);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
catch (IOException ex)
|
|
||||||
{
|
|
||||||
logger.error("could not load changesets", ex);
|
|
||||||
}
|
|
||||||
finally
|
|
||||||
{
|
|
||||||
IOUtil.close(in);
|
|
||||||
}
|
|
||||||
|
|
||||||
return changesets;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -183,66 +133,41 @@ public class HgChangesetViewer implements ChangesetViewer
|
|||||||
*
|
*
|
||||||
*
|
*
|
||||||
* @param startRev
|
* @param startRev
|
||||||
* @param endRev
|
* @param limit
|
||||||
* @param pending
|
* @param pending
|
||||||
*
|
*
|
||||||
* @return
|
* @return
|
||||||
*
|
*
|
||||||
* @throws IOException
|
* @throws IOException
|
||||||
*/
|
*/
|
||||||
public List<Changeset> getChangesets(String startRev, String endRev,
|
public ChangesetPagingResult getChangesets(String startRev, String limit,
|
||||||
boolean pending)
|
boolean pending)
|
||||||
throws IOException
|
throws IOException
|
||||||
{
|
{
|
||||||
List<Changeset> changesetList = null;
|
AssertUtil.assertIsNotEmpty(startRev);
|
||||||
InputStream in = null;
|
AssertUtil.assertIsNotEmpty(limit);
|
||||||
|
|
||||||
try
|
if (logger.isDebugEnabled())
|
||||||
{
|
{
|
||||||
SimpleCommand command =
|
logger.debug("get changesets for repository {}, start: {}, limit: {}",
|
||||||
new SimpleCommand(handler.getConfig().getHgBinary(), "-R",
|
new Object[] { repositoryDirectory.getName(),
|
||||||
repositoryPath, "log", "-r", startRev + ":" + endRev,
|
startRev, limit });
|
||||||
"--template", TEMPLATE_CHANGESETS);
|
|
||||||
|
|
||||||
if (pending)
|
|
||||||
{
|
|
||||||
Map<String, String> env = new HashMap<String, String>();
|
|
||||||
|
|
||||||
env.put(ENV_PENDING, repositoryPath);
|
|
||||||
command.setEnvironment(env);
|
|
||||||
}
|
|
||||||
|
|
||||||
CommandResult result = command.execute();
|
|
||||||
|
|
||||||
if (result.isSuccessfull())
|
|
||||||
{
|
|
||||||
StringBuilder sb = new StringBuilder("<changesets>");
|
|
||||||
|
|
||||||
sb.append(result.getOutput()).append("</changesets>");
|
|
||||||
changesetList = new HgChangesetParser().parse(
|
|
||||||
new InputSource(new StringReader(sb.toString())));
|
|
||||||
}
|
|
||||||
else if (logger.isErrorEnabled())
|
|
||||||
{
|
|
||||||
logger.error(
|
|
||||||
"command for fetching changesets failed with exit code {} and output {}",
|
|
||||||
result.getReturnCode(), result.getOutput());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
catch (ParserConfigurationException ex)
|
|
||||||
{
|
|
||||||
logger.error("could not parse changesets", ex);
|
|
||||||
}
|
|
||||||
catch (SAXException ex)
|
|
||||||
{
|
|
||||||
logger.error("could not unmarshall changesets", ex);
|
|
||||||
}
|
|
||||||
finally
|
|
||||||
{
|
|
||||||
IOUtil.close(in);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return changesetList;
|
Map<String, String> env = new HashMap<String, String>();
|
||||||
|
|
||||||
|
if (pending)
|
||||||
|
{
|
||||||
|
env.put(ENV_PENDING, repositoryDirectory.getAbsolutePath());
|
||||||
|
}
|
||||||
|
|
||||||
|
env.put(ENV_REVISION_START, startRev);
|
||||||
|
env.put(ENV_REVISION_LIMIT, limit);
|
||||||
|
|
||||||
|
return HgUtil.getResultFromScript(ChangesetPagingResult.class,
|
||||||
|
changesetPagingResultContext,
|
||||||
|
RESOURCE_LOG, handler,
|
||||||
|
repositoryDirectory, env);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -250,55 +175,26 @@ public class HgChangesetViewer implements ChangesetViewer
|
|||||||
*
|
*
|
||||||
*
|
*
|
||||||
* @param startRev
|
* @param startRev
|
||||||
* @param endRev
|
* @param limit
|
||||||
*
|
*
|
||||||
* @return
|
* @return
|
||||||
*
|
*
|
||||||
* @throws IOException
|
* @throws IOException
|
||||||
*/
|
*/
|
||||||
public List<Changeset> getChangesets(String startRev, String endRev)
|
public ChangesetPagingResult getChangesets(String startRev, String limit)
|
||||||
throws IOException
|
throws IOException
|
||||||
{
|
{
|
||||||
return getChangesets(startRev, endRev, false);
|
return getChangesets(startRev, limit, false);
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Method description
|
|
||||||
*
|
|
||||||
*
|
|
||||||
* @param repositoryPath
|
|
||||||
*
|
|
||||||
* @return
|
|
||||||
*
|
|
||||||
* @throws IOException
|
|
||||||
*/
|
|
||||||
private int getTotalChangesets(String repositoryPath) throws IOException
|
|
||||||
{
|
|
||||||
int total = -1;
|
|
||||||
Command command = new SimpleCommand(handler.getConfig().getHgBinary(),
|
|
||||||
"-R", repositoryPath, "tip", "--template",
|
|
||||||
TEMPLATE_TOTAL);
|
|
||||||
CommandResult result = command.execute();
|
|
||||||
|
|
||||||
if (result.isSuccessfull())
|
|
||||||
{
|
|
||||||
total = Integer.parseInt(result.getOutput().trim());
|
|
||||||
}
|
|
||||||
else if (logger.isErrorEnabled())
|
|
||||||
{
|
|
||||||
logger.error(
|
|
||||||
"could not read tip revision, command returned with exit code {} and content {}",
|
|
||||||
result.getReturnCode(), result.getOutput());
|
|
||||||
}
|
|
||||||
|
|
||||||
return total;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
//~--- fields ---------------------------------------------------------------
|
//~--- fields ---------------------------------------------------------------
|
||||||
|
|
||||||
|
/** Field description */
|
||||||
|
private JAXBContext changesetPagingResultContext;
|
||||||
|
|
||||||
/** Field description */
|
/** Field description */
|
||||||
private HgRepositoryHandler handler;
|
private HgRepositoryHandler handler;
|
||||||
|
|
||||||
/** Field description */
|
/** Field description */
|
||||||
private String repositoryPath;
|
private File repositoryDirectory;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -50,7 +50,6 @@ import java.io.InputStream;
|
|||||||
import java.io.OutputStream;
|
import java.io.OutputStream;
|
||||||
|
|
||||||
import javax.xml.bind.JAXBContext;
|
import javax.xml.bind.JAXBContext;
|
||||||
import javax.xml.bind.JAXBException;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
*
|
*
|
||||||
|
|||||||
@@ -115,6 +115,8 @@ public class HgRepositoryHandler
|
|||||||
{
|
{
|
||||||
this.browserResultContext = JAXBContext.newInstance(BrowserResult.class);
|
this.browserResultContext = JAXBContext.newInstance(BrowserResult.class);
|
||||||
this.blameResultContext = JAXBContext.newInstance(BlameResult.class);
|
this.blameResultContext = JAXBContext.newInstance(BlameResult.class);
|
||||||
|
this.changesetPagingResultContext =
|
||||||
|
JAXBContext.newInstance(ChangesetPagingResult.class);
|
||||||
}
|
}
|
||||||
catch (JAXBException ex)
|
catch (JAXBException ex)
|
||||||
{
|
{
|
||||||
@@ -240,7 +242,8 @@ public class HgRepositoryHandler
|
|||||||
|
|
||||||
if (TYPE_NAME.equals(type))
|
if (TYPE_NAME.equals(type))
|
||||||
{
|
{
|
||||||
changesetViewer = new HgChangesetViewer(this, repository);
|
changesetViewer = new HgChangesetViewer(this, repository,
|
||||||
|
changesetPagingResultContext);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
@@ -310,6 +313,27 @@ public class HgRepositoryHandler
|
|||||||
return TYPE;
|
return TYPE;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Method description
|
||||||
|
*
|
||||||
|
*
|
||||||
|
* @param repositoryDirectory
|
||||||
|
*
|
||||||
|
* @return
|
||||||
|
*/
|
||||||
|
HgChangesetViewer getChangesetViewer(File repositoryDirectory)
|
||||||
|
{
|
||||||
|
AssertUtil.assertIsNotNull(repositoryDirectory);
|
||||||
|
|
||||||
|
if (!repositoryDirectory.isDirectory())
|
||||||
|
{
|
||||||
|
throw new IllegalStateException("directory not found");
|
||||||
|
}
|
||||||
|
|
||||||
|
return new HgChangesetViewer(this, repositoryDirectory,
|
||||||
|
changesetPagingResultContext);
|
||||||
|
}
|
||||||
|
|
||||||
//~--- methods --------------------------------------------------------------
|
//~--- methods --------------------------------------------------------------
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -552,4 +576,7 @@ public class HgRepositoryHandler
|
|||||||
|
|
||||||
/** Field description */
|
/** Field description */
|
||||||
private JAXBContext browserResultContext;
|
private JAXBContext browserResultContext;
|
||||||
|
|
||||||
|
/** Field description */
|
||||||
|
private JAXBContext changesetPagingResultContext;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -110,8 +110,13 @@ public class HgRepositoryHookEvent extends AbstractRepositoryHookEvent
|
|||||||
logger.debug("load {}changesets for hook {}", pendingString, type);
|
logger.debug("load {}changesets for hook {}", pendingString, type);
|
||||||
}
|
}
|
||||||
|
|
||||||
changesets = createChangesetViewer().getChangesets(startRev, REV_TIP,
|
ChangesetPagingResult result =
|
||||||
pending);
|
createChangesetViewer().getChangesets(startRev, REV_TIP, pending);
|
||||||
|
|
||||||
|
if (result != null)
|
||||||
|
{
|
||||||
|
changesets = result.getChangesets();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
catch (IOException ex)
|
catch (IOException ex)
|
||||||
{
|
{
|
||||||
@@ -147,8 +152,7 @@ public class HgRepositoryHookEvent extends AbstractRepositoryHookEvent
|
|||||||
File directory = handler.getConfig().getRepositoryDirectory();
|
File directory = handler.getConfig().getRepositoryDirectory();
|
||||||
File repositoryDirectory = new File(directory, repositoryName);
|
File repositoryDirectory = new File(directory, repositoryName);
|
||||||
|
|
||||||
return new HgChangesetViewer(handler,
|
return handler.getChangesetViewer(repositoryDirectory);
|
||||||
repositoryDirectory.getAbsolutePath());
|
|
||||||
}
|
}
|
||||||
|
|
||||||
//~--- fields ---------------------------------------------------------------
|
//~--- fields ---------------------------------------------------------------
|
||||||
|
|||||||
@@ -39,7 +39,6 @@ import org.slf4j.Logger;
|
|||||||
import org.slf4j.LoggerFactory;
|
import org.slf4j.LoggerFactory;
|
||||||
|
|
||||||
import sonia.scm.SCMContext;
|
import sonia.scm.SCMContext;
|
||||||
import sonia.scm.repository.BrowserResult;
|
|
||||||
import sonia.scm.repository.HgConfig;
|
import sonia.scm.repository.HgConfig;
|
||||||
import sonia.scm.repository.HgRepositoryHandler;
|
import sonia.scm.repository.HgRepositoryHandler;
|
||||||
import sonia.scm.repository.Repository;
|
import sonia.scm.repository.Repository;
|
||||||
@@ -53,6 +52,7 @@ import java.io.IOException;
|
|||||||
import java.io.InputStream;
|
import java.io.InputStream;
|
||||||
import java.io.OutputStream;
|
import java.io.OutputStream;
|
||||||
|
|
||||||
|
import java.util.HashMap;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
|
|
||||||
import javax.xml.bind.JAXBContext;
|
import javax.xml.bind.JAXBContext;
|
||||||
@@ -96,16 +96,15 @@ public class HgUtil
|
|||||||
*
|
*
|
||||||
*
|
*
|
||||||
* @param handler
|
* @param handler
|
||||||
* @param repository
|
* @param directory
|
||||||
* @param revision
|
* @param extraEnv
|
||||||
* @param path
|
|
||||||
*
|
*
|
||||||
* @return
|
* @return
|
||||||
*
|
*
|
||||||
* @throws IOException
|
* @throws IOException
|
||||||
*/
|
*/
|
||||||
public static Process createPythonProcess(HgRepositoryHandler handler,
|
public static Process createPythonProcess(HgRepositoryHandler handler,
|
||||||
Repository repository, String revision, String path)
|
File directory, Map<String, String> extraEnv)
|
||||||
throws IOException
|
throws IOException
|
||||||
{
|
{
|
||||||
HgConfig config = handler.getConfig();
|
HgConfig config = handler.getConfig();
|
||||||
@@ -113,12 +112,8 @@ public class HgUtil
|
|||||||
Map<String, String> env = pb.environment();
|
Map<String, String> env = pb.environment();
|
||||||
|
|
||||||
env.put(ENV_PYTHON_PATH, Util.nonNull(config.getPythonPath()));
|
env.put(ENV_PYTHON_PATH, Util.nonNull(config.getPythonPath()));
|
||||||
|
env.put(ENV_REPOSITORY_PATH, directory.getAbsolutePath());
|
||||||
String directory = handler.getDirectory(repository).getAbsolutePath();
|
env.putAll(extraEnv);
|
||||||
|
|
||||||
env.put(ENV_REPOSITORY_PATH, directory);
|
|
||||||
env.put(ENV_REVISION, getRevision(revision));
|
|
||||||
env.put(ENV_PATH, Util.nonNull(path));
|
|
||||||
|
|
||||||
return pb.start();
|
return pb.start();
|
||||||
}
|
}
|
||||||
@@ -145,21 +140,6 @@ public class HgUtil
|
|||||||
return new File(cgiDirectory, CGI_NAME);
|
return new File(cgiDirectory, CGI_NAME);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* Method description
|
|
||||||
*
|
|
||||||
*
|
|
||||||
* @param revision
|
|
||||||
*
|
|
||||||
* @return
|
|
||||||
*/
|
|
||||||
public static String getRevision(String revision)
|
|
||||||
{
|
|
||||||
return Util.isEmpty(revision)
|
|
||||||
? REVISION_TIP
|
|
||||||
: revision;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Method description
|
* Method description
|
||||||
*
|
*
|
||||||
@@ -168,23 +148,21 @@ public class HgUtil
|
|||||||
* @param context
|
* @param context
|
||||||
* @param scriptResource
|
* @param scriptResource
|
||||||
* @param handler
|
* @param handler
|
||||||
* @param repository
|
* @param directory
|
||||||
* @param revision
|
* @param extraEnv
|
||||||
* @param path
|
|
||||||
* @param <T>
|
* @param <T>
|
||||||
*
|
*
|
||||||
* @return
|
* @return
|
||||||
*
|
*
|
||||||
* @throws IOException
|
* @throws IOException
|
||||||
*/
|
*/
|
||||||
public static <T> T getResultFromScript(Class<T> resultType, JAXBContext context,
|
public static <T> T getResultFromScript(Class<T> resultType,
|
||||||
String scriptResource,
|
JAXBContext context, String scriptResource,
|
||||||
HgRepositoryHandler handler,
|
HgRepositoryHandler handler, File directory,
|
||||||
Repository repository, String revision,
|
Map<String, String> extraEnv)
|
||||||
String path)
|
|
||||||
throws IOException
|
throws IOException
|
||||||
{
|
{
|
||||||
Process p = createPythonProcess(handler, repository, revision, path);
|
Process p = createPythonProcess(handler, directory, extraEnv);
|
||||||
T result = null;
|
T result = null;
|
||||||
InputStream resource = null;
|
InputStream resource = null;
|
||||||
InputStream input = null;
|
InputStream input = null;
|
||||||
@@ -213,4 +191,79 @@ public class HgUtil
|
|||||||
|
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Method description
|
||||||
|
*
|
||||||
|
*
|
||||||
|
* @param resultType
|
||||||
|
* @param context
|
||||||
|
* @param scriptResource
|
||||||
|
* @param handler
|
||||||
|
* @param repository
|
||||||
|
* @param extraEnv
|
||||||
|
* @param <T>
|
||||||
|
*
|
||||||
|
* @return
|
||||||
|
*
|
||||||
|
* @throws IOException
|
||||||
|
*/
|
||||||
|
public static <T> T getResultFromScript(Class<T> resultType,
|
||||||
|
JAXBContext context, String scriptResource,
|
||||||
|
HgRepositoryHandler handler, Repository repository,
|
||||||
|
Map<String, String> extraEnv)
|
||||||
|
throws IOException
|
||||||
|
{
|
||||||
|
File directory = handler.getDirectory(repository);
|
||||||
|
|
||||||
|
return getResultFromScript(resultType, context, scriptResource, handler,
|
||||||
|
directory, extraEnv);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Method description
|
||||||
|
*
|
||||||
|
*
|
||||||
|
* @param resultType
|
||||||
|
* @param context
|
||||||
|
* @param scriptResource
|
||||||
|
* @param handler
|
||||||
|
* @param repository
|
||||||
|
* @param revision
|
||||||
|
* @param path
|
||||||
|
* @param <T>
|
||||||
|
*
|
||||||
|
* @return
|
||||||
|
*
|
||||||
|
* @throws IOException
|
||||||
|
*/
|
||||||
|
public static <T> T getResultFromScript(Class<T> resultType,
|
||||||
|
JAXBContext context, String scriptResource,
|
||||||
|
HgRepositoryHandler handler, Repository repository, String revision,
|
||||||
|
String path)
|
||||||
|
throws IOException
|
||||||
|
{
|
||||||
|
Map<String, String> extraEnv = new HashMap<String, String>();
|
||||||
|
|
||||||
|
extraEnv.put(ENV_REVISION, getRevision(revision));
|
||||||
|
extraEnv.put(ENV_PATH, Util.nonNull(path));
|
||||||
|
|
||||||
|
return getResultFromScript(resultType, context, scriptResource, handler,
|
||||||
|
repository, extraEnv);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Method description
|
||||||
|
*
|
||||||
|
*
|
||||||
|
* @param revision
|
||||||
|
*
|
||||||
|
* @return
|
||||||
|
*/
|
||||||
|
public static String getRevision(String revision)
|
||||||
|
{
|
||||||
|
return Util.isEmpty(revision)
|
||||||
|
? REVISION_TIP
|
||||||
|
: revision;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
131
scm-plugins/scm-hg-plugin/src/main/resources/sonia/scm/hglog.py
Normal file
131
scm-plugins/scm-hg-plugin/src/main/resources/sonia/scm/hglog.py
Normal file
@@ -0,0 +1,131 @@
|
|||||||
|
#
|
||||||
|
# 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
|
||||||
|
#
|
||||||
|
#
|
||||||
|
|
||||||
|
import sys, os
|
||||||
|
|
||||||
|
pythonPath = os.environ['SCM_PYTHON_PATH']
|
||||||
|
|
||||||
|
if len(pythonPath) > 0:
|
||||||
|
pathParts = pythonPath.split(os.pathsep)
|
||||||
|
for i in range(len(pathParts)):
|
||||||
|
sys.path.insert(i, pathParts[i])
|
||||||
|
|
||||||
|
from mercurial import hg, ui, commands
|
||||||
|
from mercurial.node import hex
|
||||||
|
from xml.sax.saxutils import escape
|
||||||
|
import datetime, time
|
||||||
|
|
||||||
|
repositoryPath = os.environ['SCM_REPOSITORY_PATH']
|
||||||
|
repo = hg.repository(ui.ui(), path = repositoryPath)
|
||||||
|
|
||||||
|
start = os.environ['SCM_REVISION_START']
|
||||||
|
limit = os.environ['SCM_REVISION_LIMIT']
|
||||||
|
|
||||||
|
total = len(repo)
|
||||||
|
limit = int(limit)
|
||||||
|
|
||||||
|
try:
|
||||||
|
start = int(start)
|
||||||
|
startRev = total - start - 1
|
||||||
|
if startRev < 0:
|
||||||
|
startRev = 0
|
||||||
|
except ValueError:
|
||||||
|
startRev = repo[start].rev()
|
||||||
|
|
||||||
|
endRev = startRev - limit
|
||||||
|
if endRev < -1:
|
||||||
|
endRev = -1
|
||||||
|
|
||||||
|
# header
|
||||||
|
print '<changeset-paging>'
|
||||||
|
print ' <total>' + str(total) + '</total>'
|
||||||
|
print ' <changesets>'
|
||||||
|
|
||||||
|
# changesets
|
||||||
|
for i in range(startRev, endRev, -1):
|
||||||
|
ctx = repo[i]
|
||||||
|
time = int(ctx.date()[0]) * 1000
|
||||||
|
branch = ctx.branch()
|
||||||
|
tags = ctx.tags()
|
||||||
|
status = repo.status(ctx.p1().node(), ctx.node())
|
||||||
|
mods = status[0]
|
||||||
|
added = status[1]
|
||||||
|
deleted = status[2]
|
||||||
|
|
||||||
|
print ' <changeset>'
|
||||||
|
print ' <id>' + str(i) + ':' + hex(ctx.node()[:6]) + '</id>'
|
||||||
|
print ' <author>' + escape(ctx.user()) + '</author>'
|
||||||
|
print ' <description>' + escape(ctx.description()) + '</description>'
|
||||||
|
print ' <date>' + str(time).split('.')[0] + '</date>'
|
||||||
|
|
||||||
|
# branches
|
||||||
|
if branch != 'default':
|
||||||
|
print ' <branches>'
|
||||||
|
print ' <branch>' + branch + '</branch>'
|
||||||
|
print ' </branches>'
|
||||||
|
|
||||||
|
# tags
|
||||||
|
if tags:
|
||||||
|
print ' <tags>'
|
||||||
|
for t in tags:
|
||||||
|
print ' <tag>' + t + '</tag>'
|
||||||
|
print ' </tags>'
|
||||||
|
|
||||||
|
# modifications
|
||||||
|
print ' <modifications>'
|
||||||
|
|
||||||
|
# files added
|
||||||
|
if added:
|
||||||
|
print ' <added>'
|
||||||
|
for add in added:
|
||||||
|
print ' <file>' + add + '</file>'
|
||||||
|
print ' </added>'
|
||||||
|
|
||||||
|
# files modified
|
||||||
|
if mods:
|
||||||
|
print ' <modified>'
|
||||||
|
for mod in mods:
|
||||||
|
print ' <file>' + mod + '</file>'
|
||||||
|
print ' </modified>'
|
||||||
|
|
||||||
|
# files deleted
|
||||||
|
if deleted:
|
||||||
|
print ' <deleted>'
|
||||||
|
for dele in deleted:
|
||||||
|
print ' <file>' + dele + '</file>'
|
||||||
|
print ' </deleted>'
|
||||||
|
|
||||||
|
print ' </modifications>'
|
||||||
|
print ' </changeset>'
|
||||||
|
|
||||||
|
# footer
|
||||||
|
print ' </changesets>'
|
||||||
|
print '</changeset-paging>'
|
||||||
Reference in New Issue
Block a user