<tr><td><em>repository</em></td><td><em>required</em></td><td>repository name is part of the url (see examples below)</td></tr>\r
<tr><td>h=</td><td><em>optional</em><br/>default: HEAD</td><td>starting branch, ref, or commit id</td></tr>\r
<tr><td>l=</td><td><em>optional</em><br/>default: web.syndicationEntries</td><td>maximum return count</td></tr>\r
+<tr><td>pg=</td><td><em>optional</em><br/>default: 0</td><td>page number for paging<br/>(offset into history = pagenumber*maximum return count)</td></tr>\r
<tr><td colspan='3'><b>search query</b></td></tr>\r
<tr><td>s=</td><td><em>required</em></td><td>search string</td></tr>\r
<tr><td>st=</td><td><em>optional</em><br/>default: COMMIT</td><td>search type</td></tr>\r
\r
https://localhost:8443/feed/gitblit.git?l=50&h=refs/heads/master\r
https://localhost:8443/feed/gitblit.git?l=50&h=refs/heads/master&s=documentation\r
- https://localhost:8443/feed/gitblit.git?l=50&h=refs/heads/master&s=james&st=author\r
+ https://localhost:8443/feed/gitblit.git?l=50&h=refs/heads/master&s=james&st=author&pg=2\r
\r
## JSON Remote Procedure Call (RPC) Interface\r
\r
String repositoryName = url;\r
String objectId = request.getParameter("h");\r
String l = request.getParameter("l");\r
+ String page = request.getParameter("pg");\r
String searchString = request.getParameter("s");\r
Constants.SearchType searchType = Constants.SearchType.COMMIT;\r
if (!StringUtils.isEmpty(request.getParameter("st"))) {\r
} catch (NumberFormatException x) {\r
}\r
}\r
+ int offset = 0;\r
+ if (!StringUtils.isEmpty(page)) {\r
+ try {\r
+ offset = length * Integer.parseInt(page);\r
+ } catch (NumberFormatException x) {\r
+ }\r
+ }\r
\r
response.setContentType("application/rss+xml; charset=UTF-8");\r
Repository repository = GitBlit.self().getRepository(repositoryName);\r
List<RevCommit> commits;\r
if (StringUtils.isEmpty(searchString)) {\r
// standard log/history lookup\r
- commits = JGitUtils.getRevLog(repository, objectId, 0, length);\r
+ commits = JGitUtils.getRevLog(repository, objectId, offset, length);\r
} else {\r
// repository search\r
- commits = JGitUtils.searchRevlogs(repository, objectId, searchString, searchType, 0,\r
- length);\r
+ commits = JGitUtils.searchRevlogs(repository, objectId, searchString, searchType,\r
+ offset, length);\r
}\r
Map<ObjectId, List<RefModel>> allRefs = JGitUtils.getAllRefs(repository);\r
List<SyndicatedEntryModel> entries = new ArrayList<SyndicatedEntryModel>();\r
import java.awt.BorderLayout;\r
import java.awt.FlowLayout;\r
import java.awt.Insets;\r
+import java.awt.Rectangle;\r
import java.awt.event.ActionEvent;\r
import java.awt.event.ActionListener;\r
import java.awt.event.MouseAdapter;\r
\r
private JComboBox authorSelector;\r
\r
+ private int page;\r
+\r
+ private JButton prev;\r
+\r
+ private JButton next;\r
+\r
public FeedsPanel(GitblitClient gitblit) {\r
super();\r
this.gitblit = gitblit;\r
}\r
\r
private void initialize() {\r
+\r
+ prev = new JButton("<");\r
+ prev.setToolTipText(Translation.get("gb.pagePrevious"));\r
+ prev.setEnabled(false);\r
+ prev.addActionListener(new ActionListener() {\r
+ public void actionPerformed(ActionEvent e) {\r
+ refreshFeeds(--page);\r
+ }\r
+ });\r
+\r
+ next = new JButton(">");\r
+ next.setToolTipText(Translation.get("gb.pageNext"));\r
+ next.setEnabled(false);\r
+ next.addActionListener(new ActionListener() {\r
+ public void actionPerformed(ActionEvent e) {\r
+ refreshFeeds(++page);\r
+ }\r
+ });\r
+\r
JButton refreshFeeds = new JButton(Translation.get("gb.refresh"));\r
refreshFeeds.addActionListener(new ActionListener() {\r
public void actionPerformed(ActionEvent e) {\r
- refreshFeeds();\r
+ refreshFeeds(0);\r
}\r
});\r
\r
northControls.add(repositorySelector);\r
northControls.add(new JLabel(Translation.get("gb.author")));\r
northControls.add(authorSelector);\r
+// northControls.add(prev);\r
+// northControls.add(next);\r
\r
JPanel northPanel = new JPanel(new BorderLayout(0, Utils.MARGIN));\r
northPanel.add(header, BorderLayout.NORTH);\r
return Utils.INSETS;\r
}\r
\r
- protected void refreshFeeds() {\r
+ protected void refreshFeeds(final int page) {\r
+ this.page = page;\r
GitblitWorker worker = new GitblitWorker(FeedsPanel.this, null) {\r
@Override\r
protected Boolean doRequest() throws IOException {\r
- gitblit.refreshSubscribedFeeds();\r
+ gitblit.refreshSubscribedFeeds(page);\r
return true;\r
}\r
\r
tableModel.entries.addAll(gitblit.getSyndicatedEntries());\r
tableModel.fireTableDataChanged();\r
header.setText(Translation.get("gb.activity") + " ("\r
- + gitblit.getSyndicatedEntries().size() + ")");\r
+ + gitblit.getSyndicatedEntries().size() + (page > 0 ? (", pg " + (page + 1)) : "")\r
+ + ")");\r
if (pack) {\r
Utils.packColumns(table, Utils.MARGIN);\r
}\r
- // determine unique repositories\r
- Set<String> uniqueRepositories = new HashSet<String>();\r
- for (SyndicatedEntryModel entry : tableModel.entries) {\r
- uniqueRepositories.add(entry.repository);\r
- }\r
+ table.scrollRectToVisible(new Rectangle(table.getCellRect(0, 0, true)));\r
\r
- // repositories\r
- List<String> sortedRespositories = new ArrayList<String>(uniqueRepositories);\r
- StringUtils.sortRepositorynames(sortedRespositories);\r
- repositoryChoices.removeAllElements();\r
- repositoryChoices.addElement(ALL);\r
- for (String repo : sortedRespositories) {\r
- repositoryChoices.addElement(repo);\r
+ if (page == 0) {\r
+ // determine unique repositories\r
+ Set<String> uniqueRepositories = new HashSet<String>();\r
+ for (SyndicatedEntryModel entry : tableModel.entries) {\r
+ uniqueRepositories.add(entry.repository);\r
+ }\r
+\r
+ // repositories\r
+ List<String> sortedRespositories = new ArrayList<String>(uniqueRepositories);\r
+ StringUtils.sortRepositorynames(sortedRespositories);\r
+ repositoryChoices.removeAllElements();\r
+ repositoryChoices.addElement(ALL);\r
+ for (String repo : sortedRespositories) {\r
+ repositoryChoices.addElement(repo);\r
+ }\r
}\r
+\r
+ // update pagination buttons\r
+ next.setEnabled(tableModel.entries.size() > 0);\r
+ prev.setEnabled(page > 0);\r
}\r
\r
private void updateAuthors() {\r
refreshSettings();\r
refreshAvailableFeeds();\r
refreshRepositories();\r
-\r
- try {\r
- // RSS feeds may be disabled by server\r
- refreshSubscribedFeeds();\r
- } catch (IOException e) {\r
- e.printStackTrace();\r
- }\r
+ refreshSubscribedFeeds(0);\r
\r
try {\r
// credentials may not have administrator access\r
return availableFeeds;\r
}\r
\r
- public List<SyndicatedEntryModel> refreshSubscribedFeeds() throws IOException {\r
+ public List<SyndicatedEntryModel> refreshSubscribedFeeds(int page) throws IOException {\r
Set<SyndicatedEntryModel> allEntries = new HashSet<SyndicatedEntryModel>();\r
if (reg.feeds.size() > 0) {\r
for (FeedModel feed : reg.feeds) {\r
feed.lastRefreshDate = feed.currentRefreshDate;\r
feed.currentRefreshDate = new Date();\r
List<SyndicatedEntryModel> entries = SyndicationUtils.readFeed(url,\r
- feed.repository, feed.branch, -1, account, password);\r
+ feed.repository, feed.branch, -1, page, account, password);\r
allEntries.addAll(entries);\r
}\r
}\r
}\r
\r
public List<SyndicatedEntryModel> search(String repository, String branch, String fragment,\r
- Constants.SearchType type, int numberOfEntries) throws IOException {\r
+ Constants.SearchType type, int numberOfEntries, int page) throws IOException {\r
return SyndicationUtils.readSearchFeed(url, repository, branch, fragment, type,\r
- numberOfEntries, account, password);\r
+ numberOfEntries, page, account, password);\r
}\r
\r
public List<FederationModel> refreshFederationRegistrations() throws IOException {\r
import java.awt.BorderLayout;\r
import java.awt.FlowLayout;\r
import java.awt.Insets;\r
+import java.awt.Rectangle;\r
import java.awt.event.ActionEvent;\r
import java.awt.event.ActionListener;\r
import java.awt.event.MouseAdapter;\r
\r
private JComboBox maxHitsSelector;\r
\r
+ private int page;\r
+\r
+ private JButton prev;\r
+\r
+ private JButton next;\r
+\r
public SearchDialog(GitblitClient gitblit) {\r
super();\r
this.gitblit = gitblit;\r
\r
private void initialize() {\r
\r
+ prev = new JButton("<");\r
+ prev.setToolTipText(Translation.get("gb.pagePrevious"));\r
+ prev.setEnabled(false);\r
+ prev.addActionListener(new ActionListener() {\r
+ public void actionPerformed(ActionEvent e) {\r
+ search(--page);\r
+ }\r
+ });\r
+\r
+ next = new JButton(">");\r
+ next.setToolTipText(Translation.get("gb.pageNext"));\r
+ next.setEnabled(false);\r
+ next.addActionListener(new ActionListener() {\r
+ public void actionPerformed(ActionEvent e) {\r
+ search(++page);\r
+ }\r
+ });\r
+\r
final JButton search = new JButton(Translation.get("gb.search"));\r
search.addActionListener(new ActionListener() {\r
public void actionPerformed(ActionEvent e) {\r
- search();\r
+ search(0);\r
}\r
});\r
\r
searchTypeSelector.setSelectedItem(Constants.SearchType.COMMIT);\r
\r
maxHitsSelector = new JComboBox(new Integer[] { 25, 50, 75, 100 });\r
- maxHitsSelector.setSelectedIndex(-1);\r
+ maxHitsSelector.setSelectedIndex(0);\r
\r
searchFragment = new JTextField(25);\r
searchFragment.addActionListener(new ActionListener() {\r
public void actionPerformed(ActionEvent event) {\r
- search();\r
+ search(0);\r
}\r
});\r
\r
northControls.add(maxHitsSelector);\r
northControls.add(searchFragment);\r
northControls.add(search);\r
+ northControls.add(prev);\r
+ northControls.add(next);\r
\r
JPanel northPanel = new JPanel(new BorderLayout(0, Utils.MARGIN));\r
northPanel.add(header, BorderLayout.NORTH);\r
}\r
}\r
\r
- protected void search() {\r
+ protected void search(final int page) {\r
+ this.page = page;\r
final String repository = repositorySelector.getSelectedItem().toString();\r
final String branch = branchSelector.getSelectedIndex() > -1 ? branchSelector\r
.getSelectedItem().toString() : null;\r
final String fragment = searchFragment.getText();\r
final int maxEntryCount = maxHitsSelector.getSelectedIndex() > -1 ? ((Integer) maxHitsSelector\r
.getSelectedItem()) : -1;\r
+\r
if (StringUtils.isEmpty(fragment)) {\r
return;\r
}\r
SwingWorker<List<SyndicatedEntryModel>, Void> worker = new SwingWorker<List<SyndicatedEntryModel>, Void>() {\r
@Override\r
protected List<SyndicatedEntryModel> doInBackground() throws IOException {\r
- return gitblit.search(repository, branch, fragment, searchType, maxEntryCount);\r
+ return gitblit\r
+ .search(repository, branch, fragment, searchType, maxEntryCount, page);\r
}\r
\r
@Override\r
tableModel.entries.clear();\r
tableModel.entries.addAll(entries);\r
tableModel.fireTableDataChanged();\r
- setTitle(Translation.get("gb.search") + ": " + fragment + " (" + entries.size() + ")");\r
+ setTitle(Translation.get("gb.search") + ": " + fragment + " (" + entries.size()\r
+ + (page > 0 ? (", pg " + (page + 1)) : "") + ")");\r
header.setText(getTitle());\r
if (pack) {\r
Utils.packColumns(table, Utils.MARGIN);\r
}\r
+ table.scrollRectToVisible(new Rectangle(table.getCellRect(0, 0, true)));\r
+\r
+ // update pagination buttons\r
+ int maxHits = (Integer) maxHitsSelector.getSelectedItem();\r
+ next.setEnabled(entries.size() == maxHits);\r
+ prev.setEnabled(page > 0);\r
}\r
\r
protected SyndicatedEntryModel getSelectedSyndicatedEntry() {\r
content.setType(entryModel.contentType);\r
content.setValue(entryModel.content);\r
entry.setDescription(content);\r
- \r
+\r
entries.add(entry);\r
}\r
feed.setEntries(entries);\r
* @param numberOfEntries\r
* the number of entries to retrieve. if <= 0 the server default\r
* is used.\r
+ * @param page\r
+ * 0-indexed. used to paginate the results.\r
* @param username\r
* @param password\r
* @return a list of SyndicationModel entries\r
* @throws {@link IOException}\r
*/\r
public static List<SyndicatedEntryModel> readFeed(String url, String repository, String branch,\r
- int numberOfEntries, String username, char[] password) throws IOException {\r
+ int numberOfEntries, int page, String username, char[] password) throws IOException {\r
// build feed url\r
List<String> parameters = new ArrayList<String>();\r
if (numberOfEntries > 0) {\r
parameters.add("l=" + numberOfEntries);\r
}\r
+ if (page > 0) {\r
+ parameters.add("pg=" + page);\r
+ }\r
if (!StringUtils.isEmpty(branch)) {\r
parameters.add("h=" + branch);\r
}\r
* @param numberOfEntries\r
* the number of entries to retrieve. if <= 0 the server default\r
* is used.\r
+ * @param page\r
+ * 0-indexed. used to paginate the results.\r
* @param username\r
* @param password\r
* @return a list of SyndicationModel entries\r
*/\r
public static List<SyndicatedEntryModel> readSearchFeed(String url, String repository,\r
String branch, String fragment, Constants.SearchType searchType, int numberOfEntries,\r
- String username, char[] password) throws IOException {\r
+ int page, String username, char[] password) throws IOException {\r
// determine parameters\r
List<String> parameters = new ArrayList<String>();\r
parameters.add("s=" + StringUtils.encodeURL(fragment));\r
if (numberOfEntries > 0) {\r
parameters.add("l=" + numberOfEntries);\r
}\r
+ if (page > 0) {\r
+ parameters.add("pg=" + page);\r
+ }\r
if (!StringUtils.isEmpty(branch)) {\r
parameters.add("h=" + branch);\r
}\r
return newObjectParameter(repositoryName, objectId);\r
}\r
if (StringUtils.isEmpty(objectId)) {\r
- return new PageParameters("r=" + repositoryName + ",page=" + pageNumber);\r
+ return new PageParameters("r=" + repositoryName + ",pg=" + pageNumber);\r
}\r
- return new PageParameters("r=" + repositoryName + ",h=" + objectId + ",page=" + pageNumber);\r
+ return new PageParameters("r=" + repositoryName + ",h=" + objectId + ",pg=" + pageNumber);\r
}\r
\r
public static PageParameters newHistoryPageParameter(String repositoryName, String objectId,\r
return newObjectParameter(repositoryName, objectId);\r
}\r
if (StringUtils.isEmpty(objectId)) {\r
- return new PageParameters("r=" + repositoryName + ",f=" + path + ",page=" + pageNumber);\r
+ return new PageParameters("r=" + repositoryName + ",f=" + path + ",pg=" + pageNumber);\r
}\r
return new PageParameters("r=" + repositoryName + ",h=" + objectId + ",f=" + path\r
- + ",page=" + pageNumber);\r
+ + ",pg=" + pageNumber);\r
}\r
\r
public static PageParameters newBlobDiffParameter(String repositoryName, String baseCommitId,\r
String search, Constants.SearchType type, int pageNumber) {\r
if (StringUtils.isEmpty(commitId)) {\r
return new PageParameters("r=" + repositoryName + ",s=" + search + ",st=" + type.name()\r
- + ",page=" + pageNumber);\r
+ + ",pg=" + pageNumber);\r
}\r
return new PageParameters("r=" + repositoryName + ",h=" + commitId + ",s=" + search\r
- + ",st=" + type.name() + ",page=" + pageNumber);\r
+ + ",st=" + type.name() + ",pg=" + pageNumber);\r
}\r
\r
public static String getRepositoryName(PageParameters params) {\r
\r
public static int getPage(PageParameters params) {\r
// index from 1\r
- return params.getInt("page", 1);\r
+ return params.getInt("pg", 1);\r
}\r
\r
public static String getUsername(PageParameters params) {\r
import java.io.ByteArrayOutputStream;\r
import java.util.ArrayList;\r
import java.util.Date;\r
+import java.util.HashSet;\r
import java.util.List;\r
+import java.util.Set;\r
\r
import junit.framework.TestCase;\r
\r
}\r
\r
public void testFeedRead() throws Exception {\r
- List<SyndicatedEntryModel> feed = SyndicationUtils.readFeed("https://localhost:8443",\r
- "ticgit.git", "master", 5, "admin", "admin".toCharArray());\r
- assertTrue(feed != null);\r
- assertTrue(feed.size() > 0);\r
- assertEquals(5, feed.size());\r
+ Set<String> links = new HashSet<String>();\r
+ for (int i = 0; i < 2; i++) {\r
+ List<SyndicatedEntryModel> feed = SyndicationUtils.readFeed("https://localhost:8443",\r
+ "ticgit.git", "master", 5, i, "admin", "admin".toCharArray());\r
+ assertTrue(feed != null);\r
+ assertTrue(feed.size() > 0);\r
+ assertEquals(5, feed.size());\r
+ for (SyndicatedEntryModel entry : feed) {\r
+ links.add(entry.link);\r
+ }\r
+ }\r
+ // confirm we have 10 unique commits\r
+ assertEquals("Feed pagination failed", 10, links.size());\r
}\r
\r
public void testSearchFeedRead() throws Exception {\r
List<SyndicatedEntryModel> feed = SyndicationUtils.readSearchFeed("https://localhost:8443",\r
- "ticgit.git", null, "documentation", null, 5, "admin", "admin".toCharArray());\r
+ "ticgit.git", null, "documentation", null, 5, 0, "admin", "admin".toCharArray());\r
assertTrue(feed != null);\r
assertTrue(feed.size() > 0);\r
assertEquals(2, feed.size());\r