Merged #66 "Query tags using RSS feeds"
| | |
| | | changes: ~ |
| | | additions: |
| | | - Add FORK_REPOSITORY RPC request type (issue-371, pr-161, ticket-65) |
| | | - Add object type (ot) parameter for RSS queries to retrieve tag details (pr-165, ticket-66) |
| | | dependencyChanges: ~ |
| | | contributors: |
| | | - Manisha Gayathri |
| | | - Gerard Smyth |
| | | } |
| | | |
| | | # |
| | |
| | | }
|
| | |
|
| | | /**
|
| | | * Enumeration of the feed content object types.
|
| | | */
|
| | | public static enum FeedObjectType {
|
| | | COMMIT, TAG;
|
| | |
|
| | | public static FeedObjectType forName(String name) {
|
| | | for (FeedObjectType type : values()) {
|
| | | if (type.name().equalsIgnoreCase(name)) {
|
| | | return type;
|
| | | }
|
| | | }
|
| | | return COMMIT;
|
| | | }
|
| | |
|
| | | @Override
|
| | | public String toString() {
|
| | | return name().toLowerCase();
|
| | | }
|
| | | }
|
| | |
|
| | | /**
|
| | | * The types of objects that can be indexed and queried.
|
| | | */
|
| | | public static enum SearchObjectType {
|
| | |
| | | searchType = type;
|
| | | }
|
| | | }
|
| | |
|
| | | Constants.FeedObjectType objectType = Constants.FeedObjectType.COMMIT;
|
| | | if (!StringUtils.isEmpty(request.getParameter("ot"))) {
|
| | | Constants.FeedObjectType type = Constants.FeedObjectType.forName(request.getParameter("ot"));
|
| | | if (type != null) {
|
| | | objectType = type;
|
| | | }
|
| | | }
|
| | |
|
| | | int length = settings.getInteger(Keys.web.syndicationEntries, 25);
|
| | | if (StringUtils.isEmpty(objectId)) {
|
| | | objectId = org.eclipse.jgit.lib.Constants.HEAD;
|
| | |
| | |
|
| | |
|
| | | boolean mountParameters = settings.getBoolean(Keys.web.mountParameters, true);
|
| | | String urlPattern;
|
| | | if (mountParameters) {
|
| | | // mounted parameters
|
| | | urlPattern = "{0}/commit/{1}/{2}";
|
| | | } else {
|
| | | // parameterized parameters
|
| | | urlPattern = "{0}/commit/?r={1}&h={2}";
|
| | | }
|
| | |
|
| | | String gitblitUrl = settings.getString(Keys.web.canonicalUrl, null);
|
| | | if (StringUtils.isEmpty(gitblitUrl)) {
|
| | | gitblitUrl = HttpUtils.getGitblitURL(request);
|
| | |
| | | feedDescription = model.description;
|
| | | }
|
| | |
|
| | | List<RevCommit> commits;
|
| | | if (StringUtils.isEmpty(searchString)) {
|
| | | // standard log/history lookup
|
| | | commits = JGitUtils.getRevLog(repository, objectId, offset, length);
|
| | | if (objectType == Constants.FeedObjectType.TAG) {
|
| | |
|
| | | String urlPattern;
|
| | | if (mountParameters) {
|
| | | // mounted parameters
|
| | | urlPattern = "{0}/tag/{1}/{2}";
|
| | | } else {
|
| | | // parameterized parameters
|
| | | urlPattern = "{0}/tag/?r={1}&h={2}";
|
| | | }
|
| | |
|
| | | List<RefModel> tags = JGitUtils.getTags(repository, false, length, offset);
|
| | |
|
| | | for (RefModel tag : tags) {
|
| | | FeedEntryModel entry = new FeedEntryModel();
|
| | | entry.title = tag.getName();
|
| | | entry.author = tag.getAuthorIdent().getName();
|
| | | entry.link = MessageFormat.format(urlPattern, gitblitUrl,
|
| | | StringUtils.encodeURL(model.name.replace('/', fsc)), tag.getObjectId().getName());
|
| | | entry.published = tag.getDate();
|
| | | entry.contentType = "text/html";
|
| | | entry.content = tag.getFullMessage();
|
| | | entry.repository = model.name;
|
| | | entry.branch = objectId;
|
| | |
|
| | | entry.tags = new ArrayList<String>();
|
| | |
|
| | | // add tag id and referenced commit id
|
| | | entry.tags.add("tag:" + tag.getObjectId().getName());
|
| | | entry.tags.add("commit:" + tag.getReferencedObjectId().getName());
|
| | |
|
| | | entries.add(entry);
|
| | | }
|
| | | } else {
|
| | | // repository search
|
| | | commits = JGitUtils.searchRevlogs(repository, objectId, searchString, searchType,
|
| | | offset, length);
|
| | | }
|
| | | Map<ObjectId, List<RefModel>> allRefs = JGitUtils.getAllRefs(repository, model.showRemoteBranches);
|
| | | BugtraqProcessor processor = new BugtraqProcessor(settings);
|
| | |
|
| | | // convert RevCommit to SyndicatedEntryModel
|
| | | for (RevCommit commit : commits) {
|
| | | FeedEntryModel entry = new FeedEntryModel();
|
| | | entry.title = commit.getShortMessage();
|
| | | entry.author = commit.getAuthorIdent().getName();
|
| | | entry.link = MessageFormat.format(urlPattern, gitblitUrl,
|
| | | StringUtils.encodeURL(model.name.replace('/', fsc)), commit.getName());
|
| | | entry.published = commit.getCommitterIdent().getWhen();
|
| | | entry.contentType = "text/html";
|
| | | String message = processor.processCommitMessage(repository, model, commit.getFullMessage());
|
| | | entry.content = message;
|
| | | entry.repository = model.name;
|
| | | entry.branch = objectId;
|
| | | entry.tags = new ArrayList<String>();
|
| | |
|
| | | // add commit id and parent commit ids
|
| | | entry.tags.add("commit:" + commit.getName());
|
| | | for (RevCommit parent : commit.getParents()) {
|
| | | entry.tags.add("parent:" + parent.getName());
|
| | | String urlPattern;
|
| | | if (mountParameters) {
|
| | | // mounted parameters
|
| | | urlPattern = "{0}/commit/{1}/{2}";
|
| | | } else {
|
| | | // parameterized parameters
|
| | | urlPattern = "{0}/commit/?r={1}&h={2}";
|
| | | }
|
| | |
|
| | | // add refs to tabs list
|
| | | List<RefModel> refs = allRefs.get(commit.getId());
|
| | | if (refs != null && refs.size() > 0) {
|
| | | for (RefModel ref : refs) {
|
| | | entry.tags.add("ref:" + ref.getName());
|
| | | List<RevCommit> commits;
|
| | | if (StringUtils.isEmpty(searchString)) {
|
| | | // standard log/history lookup
|
| | | commits = JGitUtils.getRevLog(repository, objectId, offset, length);
|
| | | } else {
|
| | | // repository search
|
| | | commits = JGitUtils.searchRevlogs(repository, objectId, searchString, searchType,
|
| | | offset, length);
|
| | | }
|
| | | Map<ObjectId, List<RefModel>> allRefs = JGitUtils.getAllRefs(repository, model.showRemoteBranches);
|
| | | BugtraqProcessor processor = new BugtraqProcessor(settings);
|
| | |
|
| | | // convert RevCommit to SyndicatedEntryModel
|
| | | for (RevCommit commit : commits) {
|
| | | FeedEntryModel entry = new FeedEntryModel();
|
| | | entry.title = commit.getShortMessage();
|
| | | entry.author = commit.getAuthorIdent().getName();
|
| | | entry.link = MessageFormat.format(urlPattern, gitblitUrl,
|
| | | StringUtils.encodeURL(model.name.replace('/', fsc)), commit.getName());
|
| | | entry.published = commit.getCommitterIdent().getWhen();
|
| | | entry.contentType = "text/html";
|
| | | String message = processor.processCommitMessage(repository, model, commit.getFullMessage());
|
| | | entry.content = message;
|
| | | entry.repository = model.name;
|
| | | entry.branch = objectId;
|
| | | entry.tags = new ArrayList<String>();
|
| | |
|
| | | // add commit id and parent commit ids
|
| | | entry.tags.add("commit:" + commit.getName());
|
| | | for (RevCommit parent : commit.getParents()) {
|
| | | entry.tags.add("parent:" + parent.getName());
|
| | | }
|
| | |
|
| | | // add refs to tabs list
|
| | | List<RefModel> refs = allRefs.get(commit.getId());
|
| | | if (refs != null && refs.size() > 0) {
|
| | | for (RefModel ref : refs) {
|
| | | entry.tags.add("ref:" + ref.getName());
|
| | | }
|
| | | }
|
| | | entries.add(entry);
|
| | | }
|
| | | entries.add(entry);
|
| | | }
|
| | | }
|
| | |
|
| | |
| | | }
|
| | |
|
| | | /**
|
| | | * Returns the list of tags in the repository. If repository does not exist
|
| | | * or is empty, an empty list is returned.
|
| | | *
|
| | | * @param repository
|
| | | * @param fullName
|
| | | * if true, /refs/tags/yadayadayada is returned. If false,
|
| | | * yadayadayada is returned.
|
| | | * @param maxCount
|
| | | * if < 0, all tags are returned
|
| | | * @param offset
|
| | | * if maxCount provided sets the starting point of the records to return
|
| | | * @return list of tags
|
| | | */
|
| | | public static List<RefModel> getTags(Repository repository, boolean fullName, int maxCount, int offset) {
|
| | | return getRefs(repository, Constants.R_TAGS, fullName, maxCount, offset);
|
| | | }
|
| | |
|
| | | /**
|
| | | * Returns the list of local branches in the repository. If repository does
|
| | | * not exist or is empty, an empty list is returned.
|
| | | *
|
| | |
| | | */
|
| | | private static List<RefModel> getRefs(Repository repository, String refs, boolean fullName,
|
| | | int maxCount) {
|
| | | return getRefs(repository, refs, fullName, maxCount, 0);
|
| | | }
|
| | |
|
| | | /**
|
| | | * Returns a list of references in the repository matching "refs". If the
|
| | | * repository is null or empty, an empty list is returned.
|
| | | *
|
| | | * @param repository
|
| | | * @param refs
|
| | | * if unspecified, all refs are returned
|
| | | * @param fullName
|
| | | * if true, /refs/something/yadayadayada is returned. If false,
|
| | | * yadayadayada is returned.
|
| | | * @param maxCount
|
| | | * if < 0, all references are returned
|
| | | * @param offset
|
| | | * if maxCount provided sets the starting point of the records to return
|
| | | * @return list of references
|
| | | */
|
| | | private static List<RefModel> getRefs(Repository repository, String refs, boolean fullName,
|
| | | int maxCount, int offset) {
|
| | | List<RefModel> list = new ArrayList<RefModel>();
|
| | | if (maxCount == 0) {
|
| | | return list;
|
| | |
| | | Collections.sort(list);
|
| | | Collections.reverse(list);
|
| | | if (maxCount > 0 && list.size() > maxCount) {
|
| | | list = new ArrayList<RefModel>(list.subList(0, maxCount));
|
| | | if (offset < 0) {
|
| | | offset = 0;
|
| | | }
|
| | | int endIndex = offset + maxCount;
|
| | | if (endIndex > list.size()) {
|
| | | endIndex = list.size();
|
| | | }
|
| | | list = new ArrayList<RefModel>(list.subList(offset, endIndex));
|
| | | }
|
| | | } catch (IOException e) {
|
| | | error(e, repository, "{0} failed to retrieve {1}", refs);
|
| | |
| | | import java.util.List;
|
| | |
|
| | | import com.gitblit.Constants;
|
| | | import com.gitblit.Constants.FeedObjectType;
|
| | | import com.gitblit.GitBlitException;
|
| | | import com.gitblit.models.FeedEntryModel;
|
| | | import com.sun.syndication.feed.synd.SyndCategory;
|
| | |
| | | */
|
| | | public static List<FeedEntryModel> readFeed(String url, String repository, String branch,
|
| | | int numberOfEntries, int page, String username, char[] password) throws IOException {
|
| | | return readFeed(url, repository, branch, FeedObjectType.COMMIT, numberOfEntries,
|
| | | page, username, password);
|
| | | }
|
| | |
|
| | | /**
|
| | | * Reads tags from the specified repository.
|
| | | *
|
| | | * @param url
|
| | | * the url of the Gitblit server
|
| | | * @param repository
|
| | | * the repository name
|
| | | * @param branch
|
| | | * the branch name (optional)
|
| | | * @param numberOfEntries
|
| | | * the number of entries to retrieve. if <= 0 the server default
|
| | | * is used.
|
| | | * @param page
|
| | | * 0-indexed. used to paginate the results.
|
| | | * @param username
|
| | | * @param password
|
| | | * @return a list of SyndicationModel entries
|
| | | * @throws {@link IOException}
|
| | | */
|
| | | public static List<FeedEntryModel> readTags(String url, String repository,
|
| | | int numberOfEntries, int page, String username, char[] password) throws IOException {
|
| | | return readFeed(url, repository, null, FeedObjectType.TAG, numberOfEntries,
|
| | | page, username, password);
|
| | | }
|
| | |
|
| | | /**
|
| | | * Reads a Gitblit RSS feed.
|
| | | *
|
| | | * @param url
|
| | | * the url of the Gitblit server
|
| | | * @param repository
|
| | | * the repository name
|
| | | * @param branch
|
| | | * the branch name (optional)
|
| | | * @param objectType
|
| | | * the object type to return (optional, COMMIT assummed)
|
| | | * @param numberOfEntries
|
| | | * the number of entries to retrieve. if <= 0 the server default
|
| | | * is used.
|
| | | * @param page
|
| | | * 0-indexed. used to paginate the results.
|
| | | * @param username
|
| | | * @param password
|
| | | * @return a list of SyndicationModel entries
|
| | | * @throws {@link IOException}
|
| | | */
|
| | | private static List<FeedEntryModel> readFeed(String url, String repository, String branch,
|
| | | FeedObjectType objectType, int numberOfEntries, int page, String username,
|
| | | char[] password) throws IOException {
|
| | | // build feed url
|
| | | List<String> parameters = new ArrayList<String>();
|
| | | if (numberOfEntries > 0) {
|
| | |
| | | if (!StringUtils.isEmpty(branch)) {
|
| | | parameters.add("h=" + branch);
|
| | | }
|
| | | if (objectType != null) {
|
| | | parameters.add("ot=" + objectType.name());
|
| | | }
|
| | | return readFeed(url, parameters, repository, branch, username, password);
|
| | | }
|
| | |
|
| | |
| | | <tr><th>url parameter</th><th>default</th><th>description</th></tr>
|
| | | <tr><td colspan='3'><b>standard query</b></td></tr>
|
| | | <tr><td><em>repository</em></td><td><em>required</em></td><td>repository name is part of the url (see examples below)</td></tr>
|
| | | <tr><td>ot=</td><td><em>optional</em><br/>default: COMMIT</td><td>object type to return in results. COMMIT or TAG</td></tr>
|
| | | <tr><td>h=</td><td><em>optional</em><br/>default: HEAD</td><td>starting branch, ref, or commit id</td></tr>
|
| | | <tr><td>l=</td><td><em>optional</em><br/>default: web.syndicationEntries</td><td>maximum return count</td></tr>
|
| | | <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>
|
| | |
| | | import java.util.HashSet;
|
| | | import java.util.List;
|
| | | import java.util.Set;
|
| | | import java.util.concurrent.atomic.AtomicBoolean;
|
| | |
|
| | | import org.junit.AfterClass;
|
| | | import org.junit.BeforeClass;
|
| | | import org.junit.Test;
|
| | |
|
| | | import com.gitblit.Constants.SearchType;
|
| | |
| | | import com.gitblit.utils.SyndicationUtils;
|
| | |
|
| | | public class SyndicationUtilsTest extends GitblitUnitTest {
|
| | |
|
| | | private static final AtomicBoolean started = new AtomicBoolean(false);
|
| | |
|
| | | @BeforeClass
|
| | | public static void startGitblit() throws Exception {
|
| | | started.set(GitBlitSuite.startGitblit());
|
| | | }
|
| | |
|
| | | @AfterClass
|
| | | public static void stopGitblit() throws Exception {
|
| | | if (started.get()) {
|
| | | GitBlitSuite.stopGitblit();
|
| | | }
|
| | | }
|
| | |
|
| | | @Test
|
| | | public void testSyndication() throws Exception {
|
| | |
| | | }
|
| | |
|
| | | @Test
|
| | | public void testFeedRead() throws Exception {
|
| | | public void testFeedReadCommits() throws Exception {
|
| | | Set<String> links = new HashSet<String>();
|
| | | for (int i = 0; i < 2; i++) {
|
| | | List<FeedEntryModel> feed = SyndicationUtils.readFeed(GitBlitSuite.url, "ticgit.git",
|
| | |
| | | }
|
| | |
|
| | | @Test
|
| | | public void testFeedReadTags() throws Exception {
|
| | | Set<String> links = new HashSet<String>();
|
| | | for (int i = 0; i < 2; i++) {
|
| | | List<FeedEntryModel> feed = SyndicationUtils.readTags(GitBlitSuite.url, "test/gitective.git",
|
| | | 5, i, GitBlitSuite.account, GitBlitSuite.password.toCharArray());
|
| | | assertTrue(feed != null);
|
| | | assertTrue(feed.size() > 0);
|
| | | assertEquals(5, feed.size());
|
| | | for (FeedEntryModel entry : feed) {
|
| | | links.add(entry.link);
|
| | | }
|
| | | }
|
| | | // confirm we have 10 unique tags
|
| | | assertEquals("Feed pagination failed", 10, links.size());
|
| | | }
|
| | |
|
| | | @Test
|
| | | public void testSearchFeedRead() throws Exception {
|
| | | List<FeedEntryModel> feed = SyndicationUtils
|
| | | .readSearchFeed(GitBlitSuite.url, "ticgit.git", null, "test", null, 5, 0,
|