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
index eba4bc7c23..07df39aa03 100644
--- 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
@@ -54,7 +54,6 @@ import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.Date;
-import java.util.List;
import java.util.StringTokenizer;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
@@ -73,9 +72,12 @@ public class HgChangesetViewer implements ChangesetViewer
public static final String ID_TIP = "tip";
/** Field description */
- public static final String TEMPLATE =
+ public static final String TEMPLATE_CHANGESETS =
"{rev}:{node|short}{author|escape}{desc|escape}{date|isodatesec}\n";
+ /** Field description */
+ public static final String TEMPLATE_TOTAL = "{rev}";
+
/** the logger for HgChangesetViewer */
private static final Logger logger =
LoggerFactory.getLogger(HgChangesetViewer.class);
@@ -104,23 +106,34 @@ public class HgChangesetViewer implements ChangesetViewer
/**
*
- * @param startId
+ *
+ * @param start
* @param max
*
* @return
*/
@Override
- public List getChangesets(String startId, int max)
+ public ChangesetPagingResult getChangesets(int start, int max)
{
- List changesets = null;
+ ChangesetPagingResult changesets = null;
InputStream in = null;
try
{
String repositoryPath = getRepositoryPath(repository);
+ int total = getTotalChangesets(repositoryPath);
+ int startRev = total - start;
+ int endRev = startRev - max;
+
+ if (endRev < 0)
+ {
+ endRev = 0;
+ }
+
Command command = new SimpleCommand(handler.getConfig().getHgBinary(),
- "-R", repositoryPath, "log", "-r", "tip:0", "-l",
- String.valueOf(max), "--template", TEMPLATE);
+ "-R", repositoryPath, "log", "-r",
+ startRev + ":" + endRev, "--template",
+ TEMPLATE_CHANGESETS);
CommandResult result = command.execute();
if (result.isSuccessfull())
@@ -132,12 +145,12 @@ public class HgChangesetViewer implements ChangesetViewer
if ((cs != null) && Util.isNotEmpty(cs.getChangesets()))
{
- changesets = cs.getChangesets();
+ changesets = new ChangesetPagingResult(total, cs.getChangesets());
}
else if (logger.isWarnEnabled())
{
- logger.warn("could not find any changeset from {} to +{}", startId,
- max);
+ logger.warn("could not find any changeset from {} to {}", start,
+ start + max);
}
}
else
@@ -166,20 +179,6 @@ public class HgChangesetViewer implements ChangesetViewer
return changesets;
}
- /**
- * Method description
- *
- *
- * @param max
- *
- * @return
- */
- @Override
- public List getLastChangesets(int max)
- {
- return getChangesets(ID_TIP, max);
- }
-
/**
* Method description
*
@@ -231,6 +230,32 @@ public class HgChangesetViewer implements ChangesetViewer
return handler.getDirectory(repository).getAbsolutePath();
}
+ /**
+ * Method description
+ *
+ *
+ * @param repositoryPath
+ *
+ * @return
+ *
+ * @throws IOException
+ */
+ private int getTotalChangesets(String repositoryPath) throws IOException
+ {
+ int total = 0;
+ 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());
+ }
+
+ return total;
+ }
+
//~--- fields ---------------------------------------------------------------
/** Field description */
diff --git a/scm-core/src/main/java/sonia/scm/io/SimpleCommand.java b/scm-core/src/main/java/sonia/scm/io/SimpleCommand.java
index 37a09018f2..f85717f0df 100644
--- a/scm-core/src/main/java/sonia/scm/io/SimpleCommand.java
+++ b/scm-core/src/main/java/sonia/scm/io/SimpleCommand.java
@@ -117,7 +117,14 @@ public class SimpleCommand implements Command
{
if (logger.isDebugEnabled())
{
- logger.debug("start external process {}", command);
+ StringBuilder cmd = new StringBuilder();
+
+ for (String c : command)
+ {
+ cmd.append(c).append(" ");
+ }
+
+ logger.debug("start external process '{}'", cmd.toString());
}
ProcessBuilder processBuilder = new ProcessBuilder(command);
diff --git a/scm-core/src/main/java/sonia/scm/repository/ChangesetPagingResult.java b/scm-core/src/main/java/sonia/scm/repository/ChangesetPagingResult.java
new file mode 100644
index 0000000000..86c3a7694b
--- /dev/null
+++ b/scm-core/src/main/java/sonia/scm/repository/ChangesetPagingResult.java
@@ -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
+ *
+ */
+
+
+
+package sonia.scm.repository;
+
+//~--- JDK imports ------------------------------------------------------------
+
+import java.util.List;
+
+import javax.xml.bind.annotation.XmlAccessType;
+import javax.xml.bind.annotation.XmlAccessorType;
+import javax.xml.bind.annotation.XmlElement;
+import javax.xml.bind.annotation.XmlElementWrapper;
+import javax.xml.bind.annotation.XmlRootElement;
+
+/**
+ *
+ * @author Sebastian Sdorra
+ */
+@XmlRootElement(name = "changeset-paging")
+@XmlAccessorType(XmlAccessType.FIELD)
+public class ChangesetPagingResult
+{
+
+ /**
+ * Constructs ...
+ *
+ */
+ public ChangesetPagingResult() {}
+
+ /**
+ * Constructs ...
+ *
+ *
+ * @param total
+ * @param changesets
+ */
+ public ChangesetPagingResult(int total, List changesets)
+ {
+ this.total = total;
+ this.changesets = changesets;
+ }
+
+ //~--- get methods ----------------------------------------------------------
+
+ /**
+ * Method description
+ *
+ *
+ * @return
+ */
+ public List getChangesets()
+ {
+ return changesets;
+ }
+
+ /**
+ * Method description
+ *
+ *
+ * @return
+ */
+ public int getTotal()
+ {
+ return total;
+ }
+
+ //~--- set methods ----------------------------------------------------------
+
+ /**
+ * Method description
+ *
+ *
+ * @param changesets
+ */
+ public void setChangesets(List changesets)
+ {
+ this.changesets = changesets;
+ }
+
+ /**
+ * Method description
+ *
+ *
+ * @param total
+ */
+ public void setTotal(int total)
+ {
+ this.total = total;
+ }
+
+ //~--- fields ---------------------------------------------------------------
+
+ /** Field description */
+ @XmlElement(name = "changeset")
+ @XmlElementWrapper(name = "changesets")
+ private List changesets;
+
+ /** Field description */
+ private int total;
+}
diff --git a/scm-core/src/main/java/sonia/scm/repository/ChangesetViewer.java b/scm-core/src/main/java/sonia/scm/repository/ChangesetViewer.java
index 0d5c473f52..44285028f0 100644
--- a/scm-core/src/main/java/sonia/scm/repository/ChangesetViewer.java
+++ b/scm-core/src/main/java/sonia/scm/repository/ChangesetViewer.java
@@ -33,10 +33,6 @@
package sonia.scm.repository;
-//~--- JDK imports ------------------------------------------------------------
-
-import java.util.List;
-
/**
*
* @author Sebastian Sdorra
@@ -49,20 +45,11 @@ public interface ChangesetViewer
*
*
*
- * @param startId
+ *
+ * @param start
* @param max
*
* @return
*/
- public List getChangesets(String startId, int max);
-
- /**
- * Method description
- *
- *
- * @param max
- *
- * @return
- */
- public List getLastChangesets(int max);
+ public ChangesetPagingResult getChangesets(int start, int max);
}
diff --git a/scm-webapp/src/main/java/sonia/scm/api/rest/resources/RepositoryResource.java b/scm-webapp/src/main/java/sonia/scm/api/rest/resources/RepositoryResource.java
index 81fc735c5e..54248905e1 100644
--- a/scm-webapp/src/main/java/sonia/scm/api/rest/resources/RepositoryResource.java
+++ b/scm-webapp/src/main/java/sonia/scm/api/rest/resources/RepositoryResource.java
@@ -40,7 +40,7 @@ import com.google.inject.Provider;
import com.google.inject.Singleton;
import sonia.scm.config.ScmConfiguration;
-import sonia.scm.repository.Changeset;
+import sonia.scm.repository.ChangesetPagingResult;
import sonia.scm.repository.ChangesetViewer;
import sonia.scm.repository.Permission;
import sonia.scm.repository.PermissionType;
@@ -50,14 +50,12 @@ import sonia.scm.repository.RepositoryException;
import sonia.scm.repository.RepositoryHandler;
import sonia.scm.repository.RepositoryManager;
import sonia.scm.util.HttpUtil;
-import sonia.scm.util.Util;
import sonia.scm.web.security.WebSecurityContext;
//~--- JDK imports ------------------------------------------------------------
import java.util.ArrayList;
import java.util.Collection;
-import java.util.List;
import javax.servlet.http.HttpServletRequest;
@@ -116,8 +114,8 @@ public class RepositoryResource
*
*
* @param id
- * @param startId
- * @param max
+ * @param start
+ * @param limit
*
* @return
*
@@ -126,9 +124,9 @@ public class RepositoryResource
@GET
@Path("{id}/changesets")
@Produces({ MediaType.APPLICATION_XML, MediaType.APPLICATION_JSON })
- public Response getChangesets(@PathParam("id") String id,
- @QueryParam("changeset") String startId,
- @DefaultValue("25") @QueryParam("max") int max)
+ public Response getChangesets(@PathParam("id") String id,
+ @DefaultValue("0") @QueryParam("start") int start,
+ @DefaultValue("25") @QueryParam("limit") int limit)
throws RepositoryException
{
Response response = null;
@@ -141,19 +139,10 @@ public class RepositoryResource
if (changesetViewer != null)
{
- List changesets = null;
+ ChangesetPagingResult changesets = changesetViewer.getChangesets(start,
+ limit);
- if (Util.isNotEmpty(startId))
- {
- changesets = changesetViewer.getChangesets(startId, max);
- }
- else
- {
- changesets = changesetViewer.getLastChangesets(max);
- }
-
- response = Response.ok(new GenericEntity>(changesets) {}
- ).build();
+ response = Response.ok(changesets).build();
}
else
{
diff --git a/scm-webapp/src/main/webapp/resources/js/sonia.repository.js b/scm-webapp/src/main/webapp/resources/js/sonia.repository.js
index aab73030c2..11d7fd92aa 100644
--- a/scm-webapp/src/main/webapp/resources/js/sonia.repository.js
+++ b/scm-webapp/src/main/webapp/resources/js/sonia.repository.js
@@ -695,9 +695,14 @@ Sonia.repository.ChangesetViewerGrid = Ext.extend(Ext.grid.GridPanel, {
var changesetStore = new Ext.data.JsonStore({
id: 'changesetStore',
- url: restUrl + 'repositories/' + this.repository.id + '/changesets.json',
+ proxy: new Ext.data.HttpProxy({
+ url: restUrl + 'repositories/' + this.repository.id + '/changesets.json',
+ method: 'GET'
+ }),
fields: ['id', 'date', 'author', 'description'],
+ root: 'changesets',
idProperty: 'id',
+ totalProperty: 'total',
autoLoad: true,
autoDestroy: true
});
@@ -718,7 +723,13 @@ Sonia.repository.ChangesetViewerGrid = Ext.extend(Ext.grid.GridPanel, {
autoExpandColumn: 'changeset',
autoHeight: true,
store: changesetStore,
- colModel: changesetColModel
+ colModel: changesetColModel,
+ bbar: new Ext.PagingToolbar({
+ store: changesetStore,
+ displayInfo: true,
+ pageSize: 25,
+ prependButtons: true
+ })
}
Ext.apply(this, Ext.apply(this.initialConfig, config));