Skip to main content
summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorKevin Sawicki2011-08-01 22:01:59 +0000
committerKevin Sawicki2011-08-01 22:01:59 +0000
commit6c43a4d617667cf9c0e1ec2fa4b908e5814c6542 (patch)
tree5fc6b5b531908b26a643a16786c09b8d32335fac /org.eclipse.mylyn.github.core/src/org/eclipse
parent433497079eb3ee28c15ab23b3e4d2e9e8ae12bc5 (diff)
downloadegit-github-6c43a4d617667cf9c0e1ec2fa4b908e5814c6542.tar.gz
egit-github-6c43a4d617667cf9c0e1ec2fa4b908e5814c6542.tar.xz
egit-github-6c43a4d617667cf9c0e1ec2fa4b908e5814c6542.zip
Add task repository for pull requests.
Initially supports: * Editing summary & description * Browsing & adding comments * Browsing & opening associated commits * Closing & re-opening the pull request * Checking out the pull request's commits into a topic branch * Fetching pull request commits * Generating a context with the files modified in the pull request Change-Id: Iba75e999353dbc5d095dc95dd2977e9f21d694e6 Signed-off-by: Kevin Sawicki <kevin@github.com>
Diffstat (limited to 'org.eclipse.mylyn.github.core/src/org/eclipse')
-rw-r--r--org.eclipse.mylyn.github.core/src/org/eclipse/mylyn/internal/github/core/GitHub.java19
-rw-r--r--org.eclipse.mylyn.github.core/src/org/eclipse/mylyn/internal/github/core/GitHubException.java2
-rw-r--r--org.eclipse.mylyn.github.core/src/org/eclipse/mylyn/internal/github/core/gist/messages.properties2
-rw-r--r--org.eclipse.mylyn.github.core/src/org/eclipse/mylyn/internal/github/core/issue/IssueAttribute.java16
-rw-r--r--org.eclipse.mylyn.github.core/src/org/eclipse/mylyn/internal/github/core/issue/IssueConnector.java82
-rw-r--r--org.eclipse.mylyn.github.core/src/org/eclipse/mylyn/internal/github/core/issue/IssueOperation.java6
-rw-r--r--org.eclipse.mylyn.github.core/src/org/eclipse/mylyn/internal/github/core/issue/IssueTaskDataHandler.java9
-rw-r--r--org.eclipse.mylyn.github.core/src/org/eclipse/mylyn/internal/github/core/issue/Messages.java3
-rw-r--r--org.eclipse.mylyn.github.core/src/org/eclipse/mylyn/internal/github/core/issue/messages.properties1
-rw-r--r--org.eclipse.mylyn.github.core/src/org/eclipse/mylyn/internal/github/core/pr/Messages.java71
-rw-r--r--org.eclipse.mylyn.github.core/src/org/eclipse/mylyn/internal/github/core/pr/PullRequestAttribute.java121
-rw-r--r--org.eclipse.mylyn.github.core/src/org/eclipse/mylyn/internal/github/core/pr/PullRequestComposite.java58
-rw-r--r--org.eclipse.mylyn.github.core/src/org/eclipse/mylyn/internal/github/core/pr/PullRequestConnector.java265
-rw-r--r--org.eclipse.mylyn.github.core/src/org/eclipse/mylyn/internal/github/core/pr/PullRequestOperation.java72
-rw-r--r--org.eclipse.mylyn.github.core/src/org/eclipse/mylyn/internal/github/core/pr/PullRequestTaskDataHandler.java230
-rw-r--r--org.eclipse.mylyn.github.core/src/org/eclipse/mylyn/internal/github/core/pr/PullRequestUtils.java145
-rw-r--r--org.eclipse.mylyn.github.core/src/org/eclipse/mylyn/internal/github/core/pr/messages.properties14
17 files changed, 1048 insertions, 68 deletions
diff --git a/org.eclipse.mylyn.github.core/src/org/eclipse/mylyn/internal/github/core/GitHub.java b/org.eclipse.mylyn.github.core/src/org/eclipse/mylyn/internal/github/core/GitHub.java
index a98bbca2..5867f795 100644
--- a/org.eclipse.mylyn.github.core/src/org/eclipse/mylyn/internal/github/core/GitHub.java
+++ b/org.eclipse.mylyn.github.core/src/org/eclipse/mylyn/internal/github/core/GitHub.java
@@ -32,25 +32,28 @@ import org.eclipse.mylyn.tasks.core.TaskRepository;
public class GitHub {
/** BUNDLE_ID */
- public static final String BUNDLE_ID = "org.eclipse.mylyn.github.core";
+ public static final String BUNDLE_ID = "org.eclipse.mylyn.github.core"; //$NON-NLS-1$
/** CONNECTOR_KIND */
- public static final String CONNECTOR_KIND = "github";
+ public static final String CONNECTOR_KIND = "github"; //$NON-NLS-1$
/** HTTP_WWW_GITHUB_ORG */
- public static final String HTTP_WWW_GITHUB_ORG = "http://www.github.org";
+ public static final String HTTP_WWW_GITHUB_ORG = "http://www.github.org"; //$NON-NLS-1$
/** HTTP_GITHUB_COM */
- public static final String HTTP_GITHUB_COM = "http://github.com";
+ public static final String HTTP_GITHUB_COM = "http://github.com"; //$NON-NLS-1$
/** URL_PATTERN */
- public static final Pattern URL_PATTERN = Pattern.compile("(?:"
- + Pattern.quote(HTTP_WWW_GITHUB_ORG) + "|"
- + Pattern.quote(HTTP_GITHUB_COM) + ")/([^/]+)/([^/]+)");
+ public static final Pattern URL_PATTERN = Pattern.compile("(?:" //$NON-NLS-1$
+ + Pattern.quote(HTTP_WWW_GITHUB_ORG) + "|" //$NON-NLS-1$
+ + Pattern.quote(HTTP_GITHUB_COM) + ")/([^/]+)/([^/]+)"); //$NON-NLS-1$
/** USER_AGENT */
public static final String USER_AGENT = "GitHubEclipse/1.1.0"; //$NON-NLS-1$
+ /** REPOSITORY_SEGMENTS */
+ public static final String REPOSITORY_SEGMENTS = "/user/repository"; //$NON-NLS-1$
+
/**
* Configure client with standard configuration
*
@@ -130,7 +133,7 @@ public class GitHub {
*/
public static IStatus createErrorStatus(Throwable e) {
return createStatus(IStatus.ERROR,
- "Unexpected error: " + e.getLocalizedMessage(), e);
+ "Unexpected error: " + e.getLocalizedMessage(), e); //$NON-NLS-1$
}
/**
diff --git a/org.eclipse.mylyn.github.core/src/org/eclipse/mylyn/internal/github/core/GitHubException.java b/org.eclipse.mylyn.github.core/src/org/eclipse/mylyn/internal/github/core/GitHubException.java
index da31e61c..c6bde874 100644
--- a/org.eclipse.mylyn.github.core/src/org/eclipse/mylyn/internal/github/core/GitHubException.java
+++ b/org.eclipse.mylyn.github.core/src/org/eclipse/mylyn/internal/github/core/GitHubException.java
@@ -53,7 +53,7 @@ public class GitHubException extends IOException {
RequestError error = ((RequestException) getCause()).getError();
String errorMessage = error.getMessage();
if (errorMessage == null)
- errorMessage = "";
+ errorMessage = ""; //$NON-NLS-1$
StringBuilder message = new StringBuilder(errorMessage);
List<FieldError> errors = error.getErrors();
if (errors != null && errors.size() > 0) {
diff --git a/org.eclipse.mylyn.github.core/src/org/eclipse/mylyn/internal/github/core/gist/messages.properties b/org.eclipse.mylyn.github.core/src/org/eclipse/mylyn/internal/github/core/gist/messages.properties
index aa9f10a5..e416f05b 100644
--- a/org.eclipse.mylyn.github.core/src/org/eclipse/mylyn/internal/github/core/gist/messages.properties
+++ b/org.eclipse.mylyn.github.core/src/org/eclipse/mylyn/internal/github/core/gist/messages.properties
@@ -9,7 +9,7 @@ GistAttribute_LabelModified=Modified:
GistAttribute_LabelNewComment=New Comment
GistAttribute_LabelSummary=Summary
GistAttribute_LabelUrl=Url
-GistConnector_LabelConnector=Github Gists
+GistConnector_LabelConnector=GitHub Gists
GistTaskDataHandler_FilesMultiple={0} files
GistTaskDataHandler_FilesSingle=1 file
GistTaskDataHandler_SizeByte=1 byte
diff --git a/org.eclipse.mylyn.github.core/src/org/eclipse/mylyn/internal/github/core/issue/IssueAttribute.java b/org.eclipse.mylyn.github.core/src/org/eclipse/mylyn/internal/github/core/issue/IssueAttribute.java
index 58604166..2af15afd 100644
--- a/org.eclipse.mylyn.github.core/src/org/eclipse/mylyn/internal/github/core/issue/IssueAttribute.java
+++ b/org.eclipse.mylyn.github.core/src/org/eclipse/mylyn/internal/github/core/issue/IssueAttribute.java
@@ -109,21 +109,7 @@ public enum IssueAttribute {
*/
REPORTER_GRAVATAR(Messages.IssueAttribute_LabelReporterGravatar,
"github.issue.reporter.gravatar", TaskAttribute.TYPE_URL, null, //$NON-NLS-1$
- true, false),
-
- /**
- * URL to diff if issue is a pull request
- */
- PULL_REQUEST_DIFF(Messages.IssueAttribute_LabelPullRequestDiffUrl,
- "github.issue.pull.diff", //$NON-NLS-2$ //$NON-NLS-1$
- TaskAttribute.TYPE_URL, null, true, false),
-
- /**
- * Body of pull request if issue is a pull request
- */
- PULL_REQUEST_BODY(Messages.IssueAttribute_LabelPullRequestBody,
- "github.issue.pull.body", //$NON-NLS-2$
- TaskAttribute.TYPE_LONG_TEXT, null, true, false);
+ true, false);
private final GitHubAttributeMetadata metadata;
diff --git a/org.eclipse.mylyn.github.core/src/org/eclipse/mylyn/internal/github/core/issue/IssueConnector.java b/org.eclipse.mylyn.github.core/src/org/eclipse/mylyn/internal/github/core/issue/IssueConnector.java
index 427f29d6..399ebf1a 100644
--- a/org.eclipse.mylyn.github.core/src/org/eclipse/mylyn/internal/github/core/issue/IssueConnector.java
+++ b/org.eclipse.mylyn.github.core/src/org/eclipse/mylyn/internal/github/core/issue/IssueConnector.java
@@ -13,7 +13,6 @@
package org.eclipse.mylyn.internal.github.core.issue;
import java.io.IOException;
-import java.net.URL;
import java.util.Collections;
import java.util.HashMap;
import java.util.LinkedList;
@@ -28,26 +27,30 @@ import org.eclipse.core.runtime.IProgressMonitor;
import org.eclipse.core.runtime.IStatus;
import org.eclipse.core.runtime.Status;
import org.eclipse.egit.github.core.Comment;
+import org.eclipse.egit.github.core.IRepositoryIdProvider;
import org.eclipse.egit.github.core.Issue;
import org.eclipse.egit.github.core.Label;
import org.eclipse.egit.github.core.Milestone;
+import org.eclipse.egit.github.core.PullRequest;
+import org.eclipse.egit.github.core.Repository;
import org.eclipse.egit.github.core.RepositoryId;
import org.eclipse.egit.github.core.client.GitHubClient;
-import org.eclipse.egit.github.core.client.IGitHubConstants;
import org.eclipse.egit.github.core.service.IssueService;
import org.eclipse.egit.github.core.service.LabelService;
import org.eclipse.egit.github.core.service.MilestoneService;
import org.eclipse.egit.github.core.util.LabelComparator;
import org.eclipse.egit.github.core.util.MilestoneComparator;
+import org.eclipse.mylyn.commons.net.AuthenticationCredentials;
+import org.eclipse.mylyn.commons.net.AuthenticationType;
import org.eclipse.mylyn.commons.net.Policy;
import org.eclipse.mylyn.internal.github.core.GitHub;
import org.eclipse.mylyn.internal.github.core.QueryUtils;
import org.eclipse.mylyn.internal.github.core.RepositoryConnector;
+import org.eclipse.mylyn.internal.github.core.pr.PullRequestConnector;
+import org.eclipse.mylyn.internal.tasks.core.IRepositoryConstants;
import org.eclipse.mylyn.tasks.core.IRepositoryQuery;
-import org.eclipse.mylyn.tasks.core.ITask;
import org.eclipse.mylyn.tasks.core.TaskRepository;
import org.eclipse.mylyn.tasks.core.data.AbstractTaskDataHandler;
-import org.eclipse.mylyn.tasks.core.data.TaskAttribute;
import org.eclipse.mylyn.tasks.core.data.TaskData;
import org.eclipse.mylyn.tasks.core.data.TaskDataCollector;
import org.eclipse.mylyn.tasks.core.sync.ISynchronizationSession;
@@ -63,20 +66,48 @@ public class IssueConnector extends RepositoryConnector {
public static final String KIND = GitHub.CONNECTOR_KIND;
/**
+ * Get repository label for id provider
+ *
+ * @param repo
+ * @return label
+ */
+ public static String getRepositoryLabel(IRepositoryIdProvider repo) {
+ return repo.generateId() + Messages.IssueConnector_LabelIssues;
+ }
+
+ /**
+ * Create issue task repository
+ *
+ * @param repo
+ * @param username
+ * @param password
+ * @return task repository
+ */
+ public static TaskRepository createTaskRepository(Repository repo,
+ String username, String password) {
+ String url = GitHub.createGitHubUrl(repo.getOwner().getLogin(),
+ repo.getName());
+ TaskRepository repository = new TaskRepository(
+ PullRequestConnector.KIND, url);
+ repository.setProperty(IRepositoryConstants.PROPERTY_LABEL,
+ getRepositoryLabel(repo));
+ if (username != null && password != null)
+ repository.setCredentials(AuthenticationType.REPOSITORY,
+ new AuthenticationCredentials(username, password), true);
+ repository.setProperty(IRepositoryConstants.PROPERTY_CATEGORY,
+ IRepositoryConstants.CATEGORY_BUGS);
+ return repository;
+ }
+
+ /**
* Create client for repository
*
* @param repository
* @return client
*/
public static GitHubClient createClient(TaskRepository repository) {
- GitHubClient client;
- try {
- String host = new URL(repository.getRepositoryUrl()).getHost();
- host = IGitHubConstants.SUBDOMAIN_API + "." + host;
- client = new GitHubClient(host, -1, IGitHubConstants.PROTOCOL_HTTPS);
- } catch (IOException e) {
- throw new IllegalArgumentException(e);
- }
+ GitHubClient client = GitHubClient.createClient(repository
+ .getRepositoryUrl());
GitHub.addCredentials(client, repository);
return GitHub.configureClient(client);
}
@@ -295,7 +326,7 @@ public class IssueConnector extends RepositoryConnector {
// collect task data
for (Issue issue : issues) {
- if (issue.getPullRequest() == null)
+ if (isPullRequest(issue))
continue;
List<Comment> comments = null;
if (issue.getComments() > 0)
@@ -315,6 +346,11 @@ public class IssueConnector extends RepositoryConnector {
return result;
}
+ private boolean isPullRequest(Issue issue) {
+ PullRequest request = issue.getPullRequest();
+ return request != null && request.getDiffUrl() != null;
+ }
+
@Override
public TaskData getTaskData(TaskRepository repository, String taskId,
IProgressMonitor monitor) throws CoreException {
@@ -325,6 +361,8 @@ public class IssueConnector extends RepositoryConnector {
IssueService service = new IssueService(client);
Issue issue = service.getIssue(repo.getOwner(), repo.getName(),
taskId);
+ if (isPullRequest(issue))
+ return null;
List<Comment> comments = null;
if (issue.getComments() > 0)
comments = service.getComments(repo.getOwner(), repo.getName(),
@@ -375,22 +413,4 @@ public class IssueConnector extends RepositoryConnector {
refreshMilestones(taskRepository);
monitor.done();
}
-
- @Override
- public void updateTaskFromTaskData(TaskRepository taskRepository,
- ITask task, TaskData taskData) {
- if (!taskData.isNew()) {
- String diffUrl = null;
- TaskAttribute prDiff = taskData.getRoot().getAttribute(
- IssueAttribute.PULL_REQUEST_DIFF.getMetadata().getId());
- if (prDiff != null) {
- diffUrl = taskData.getAttributeMapper().getValue(prDiff);
- if (diffUrl.length() == 0)
- diffUrl = null;
- }
- task.setAttribute(IssueAttribute.PULL_REQUEST_DIFF.getMetadata()
- .getId(), diffUrl);
- }
- super.updateTaskFromTaskData(taskRepository, task, taskData);
- }
}
diff --git a/org.eclipse.mylyn.github.core/src/org/eclipse/mylyn/internal/github/core/issue/IssueOperation.java b/org.eclipse.mylyn.github.core/src/org/eclipse/mylyn/internal/github/core/issue/IssueOperation.java
index f8263859..647b8fe7 100644
--- a/org.eclipse.mylyn.github.core/src/org/eclipse/mylyn/internal/github/core/issue/IssueOperation.java
+++ b/org.eclipse.mylyn.github.core/src/org/eclipse/mylyn/internal/github/core/issue/IssueOperation.java
@@ -20,17 +20,17 @@ public enum IssueOperation {
/**
* LEAD
*/
- LEAVE("Leave "),
+ LEAVE("Leave "), //$NON-NLS-1$
/**
* REOPEN
*/
- REOPEN("Reopen"),
+ REOPEN("Reopen"), //$NON-NLS-1$
/**
* CLOSE
*/
- CLOSE("Close");
+ CLOSE("Close"); //$NON-NLS-1$
private final String label;
diff --git a/org.eclipse.mylyn.github.core/src/org/eclipse/mylyn/internal/github/core/issue/IssueTaskDataHandler.java b/org.eclipse.mylyn.github.core/src/org/eclipse/mylyn/internal/github/core/issue/IssueTaskDataHandler.java
index f1bf04e4..a9060f8d 100644
--- a/org.eclipse.mylyn.github.core/src/org/eclipse/mylyn/internal/github/core/issue/IssueTaskDataHandler.java
+++ b/org.eclipse.mylyn.github.core/src/org/eclipse/mylyn/internal/github/core/issue/IssueTaskDataHandler.java
@@ -24,7 +24,6 @@ import org.eclipse.egit.github.core.Comment;
import org.eclipse.egit.github.core.Issue;
import org.eclipse.egit.github.core.Label;
import org.eclipse.egit.github.core.Milestone;
-import org.eclipse.egit.github.core.PullRequest;
import org.eclipse.egit.github.core.RepositoryId;
import org.eclipse.egit.github.core.User;
import org.eclipse.egit.github.core.client.GitHubClient;
@@ -113,14 +112,6 @@ public class IssueTaskDataHandler extends GitHubTaskDataHandler {
createMilestones(repository, data, issue);
- PullRequest pr = issue.getPullRequest();
- String prDiffUrl = pr != null ? pr.getDiffUrl() : null;
- createAttribute(data, IssueAttribute.PULL_REQUEST_DIFF.getMetadata(),
- prDiffUrl);
- if (prDiffUrl != null)
- createAttribute(data,
- IssueAttribute.PULL_REQUEST_BODY.getMetadata(), ""); //$NON-NLS-1$
-
return data;
}
diff --git a/org.eclipse.mylyn.github.core/src/org/eclipse/mylyn/internal/github/core/issue/Messages.java b/org.eclipse.mylyn.github.core/src/org/eclipse/mylyn/internal/github/core/issue/Messages.java
index 7ac7f551..dd57e377 100644
--- a/org.eclipse.mylyn.github.core/src/org/eclipse/mylyn/internal/github/core/issue/Messages.java
+++ b/org.eclipse.mylyn.github.core/src/org/eclipse/mylyn/internal/github/core/issue/Messages.java
@@ -23,6 +23,9 @@ public class Messages extends NLS {
public static String IssueConnector_LabelConnector;
/** */
+ public static String IssueConnector_LabelIssues;
+
+ /** */
public static String IssueConector_TaskQuerying;
/** */
diff --git a/org.eclipse.mylyn.github.core/src/org/eclipse/mylyn/internal/github/core/issue/messages.properties b/org.eclipse.mylyn.github.core/src/org/eclipse/mylyn/internal/github/core/issue/messages.properties
index 350f6a86..ba0d170f 100644
--- a/org.eclipse.mylyn.github.core/src/org/eclipse/mylyn/internal/github/core/issue/messages.properties
+++ b/org.eclipse.mylyn.github.core/src/org/eclipse/mylyn/internal/github/core/issue/messages.properties
@@ -1,4 +1,5 @@
IssueConnector_LabelConnector=GitHub Issues
+IssueConnector_LabelIssues=\ issues
IssueConector_TaskQuerying=Querying repository...
IssueConnector_TaskUpdatingLabels=Updating labels
IssueConnector_TaskUpdatingMilestones=Updating milestones
diff --git a/org.eclipse.mylyn.github.core/src/org/eclipse/mylyn/internal/github/core/pr/Messages.java b/org.eclipse.mylyn.github.core/src/org/eclipse/mylyn/internal/github/core/pr/Messages.java
new file mode 100644
index 00000000..5ba25b68
--- /dev/null
+++ b/org.eclipse.mylyn.github.core/src/org/eclipse/mylyn/internal/github/core/pr/Messages.java
@@ -0,0 +1,71 @@
+/*******************************************************************************
+ * Copyright (c) 2011 GitHub Inc.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ * Kevin Sawicki (GitHub Inc.) - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.mylyn.internal.github.core.pr;
+
+import org.eclipse.osgi.util.NLS;
+
+/**
+ * NLS for Mylyn GitHub Core
+ */
+public class Messages extends NLS {
+
+ private static final String BUNDLE_NAME = "org.eclipse.mylyn.internal.github.core.pr.messages"; //$NON-NLS-1$
+
+ /** */
+ public static String PullRequestAttribute_LabelClosedAt;
+
+ /** */
+ public static String PullRequestAttribute_LabelComment;
+
+ /** */
+ public static String PullRequestAttribute_LabelCreatedAt;
+
+ /** */
+ public static String PullRequestAttribute_LabelDescription;
+
+ /** */
+ public static String PullRequestAttribute_LabelKey;
+
+ /** */
+ public static String PullRequestAttribute_LabelMergedAt;
+
+ /** */
+ public static String PullRequestAttribute_LabelModel;
+
+ /** */
+ public static String PullRequestAttribute_LabelModifiedAt;
+
+ /** */
+ public static String PullRequestAttribute_LabelReporter;
+
+ /** */
+ public static String PullRequestAttribute_LabelStatus;
+
+ /** */
+ public static String PullRequestAttribute_LabelSummary;
+
+ /** */
+ public static String PullRequestConnector_Label;
+
+ /** */
+ public static String PullRequestConnector_LabelPullRequests;
+
+ /** */
+ public static String PullRequestConnector_TaskFetching;
+
+ static {
+ // initialize resource bundle
+ NLS.initializeMessages(BUNDLE_NAME, Messages.class);
+ }
+
+ private Messages() {
+ }
+}
diff --git a/org.eclipse.mylyn.github.core/src/org/eclipse/mylyn/internal/github/core/pr/PullRequestAttribute.java b/org.eclipse.mylyn.github.core/src/org/eclipse/mylyn/internal/github/core/pr/PullRequestAttribute.java
new file mode 100644
index 00000000..1c12251d
--- /dev/null
+++ b/org.eclipse.mylyn.github.core/src/org/eclipse/mylyn/internal/github/core/pr/PullRequestAttribute.java
@@ -0,0 +1,121 @@
+/******************************************************************************
+ * Copyright (c) 2011 GitHub Inc.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ * Kevin Sawicki (GitHub Inc.) - initial API and implementation
+ *****************************************************************************/
+package org.eclipse.mylyn.internal.github.core.pr;
+
+import org.eclipse.mylyn.internal.github.core.GitHubAttributeMetadata;
+import org.eclipse.mylyn.tasks.core.data.TaskAttribute;
+
+/**
+ * GitHub pull request attributes
+ */
+public enum PullRequestAttribute {
+
+ /**
+ * Pull request key
+ */
+ KEY(Messages.PullRequestAttribute_LabelKey, TaskAttribute.TASK_KEY,
+ TaskAttribute.TYPE_SHORT_TEXT, true, true),
+
+ /**
+ * Pull request title
+ */
+ TITLE(Messages.PullRequestAttribute_LabelSummary, TaskAttribute.SUMMARY,
+ TaskAttribute.TYPE_SHORT_RICH_TEXT, false, true),
+
+ /**
+ * Pull request description
+ */
+ BODY(Messages.PullRequestAttribute_LabelDescription,
+ TaskAttribute.DESCRIPTION, TaskAttribute.TYPE_LONG_RICH_TEXT,
+ false, true),
+
+ /**
+ * Pull request creation date
+ */
+ CREATION_DATE(Messages.PullRequestAttribute_LabelCreatedAt,
+ TaskAttribute.DATE_CREATION, TaskAttribute.TYPE_DATETIME, true,
+ false),
+
+ /**
+ * Pull request modification date
+ */
+ MODIFICATION_DATE(Messages.PullRequestAttribute_LabelModifiedAt,
+ TaskAttribute.DATE_MODIFICATION, TaskAttribute.TYPE_DATETIME, true,
+ false),
+
+ /**
+ * Pull request closed date
+ */
+ CLOSED_DATE(Messages.PullRequestAttribute_LabelClosedAt,
+ TaskAttribute.DATE_COMPLETION, TaskAttribute.TYPE_DATETIME, true,
+ false),
+
+ /**
+ * Pull request merged date
+ */
+ MERGED_DATE(Messages.PullRequestAttribute_LabelMergedAt,
+ "github.pr.merged.at", TaskAttribute.TYPE_DATETIME, true, false), //$NON-NLS-1$
+
+ /**
+ * Pull request status
+ */
+ STATUS(Messages.PullRequestAttribute_LabelStatus, TaskAttribute.STATUS,
+ TaskAttribute.TYPE_SHORT_TEXT, false, true),
+
+ /**
+ * Pull request reporter
+ */
+ REPORTER(Messages.PullRequestAttribute_LabelReporter,
+ TaskAttribute.USER_REPORTER, TaskAttribute.TYPE_PERSON, true, false),
+
+ /**
+ * Comment being added to pull request
+ */
+ COMMENT_NEW(Messages.PullRequestAttribute_LabelComment,
+ TaskAttribute.COMMENT_NEW, TaskAttribute.TYPE_LONG_RICH_TEXT,
+ false, false),
+
+ /**
+ * Pull request reporter gravatar
+ */
+ REPORTER_GRAVATAR(Messages.PullRequestAttribute_LabelReporter,
+ "github.pr.reporter.gravatar", TaskAttribute.TYPE_URL, null, true, //$NON-NLS-1$
+ false),
+
+ /**
+ * Full pull request model stored as JSON
+ */
+ MODEL(Messages.PullRequestAttribute_LabelModel, "github.pr.model", //$NON-NLS-1$
+ TaskAttribute.TYPE_LONG_TEXT, null, true, false);
+
+ private final GitHubAttributeMetadata metadata;
+
+ private PullRequestAttribute(String label, String id, String type,
+ boolean readOnly, boolean initTask) {
+ metadata = new GitHubAttributeMetadata(id, label, type, readOnly,
+ initTask);
+ }
+
+ private PullRequestAttribute(String label, String id, String type,
+ String kind, boolean readOnly, boolean initTask) {
+ metadata = new GitHubAttributeMetadata(id, label, kind, type, readOnly,
+ initTask);
+ }
+
+ /**
+ * Get attribute metadata
+ *
+ * @return metadata
+ */
+ public GitHubAttributeMetadata getMetadata() {
+ return metadata;
+ }
+}
diff --git a/org.eclipse.mylyn.github.core/src/org/eclipse/mylyn/internal/github/core/pr/PullRequestComposite.java b/org.eclipse.mylyn.github.core/src/org/eclipse/mylyn/internal/github/core/pr/PullRequestComposite.java
new file mode 100644
index 00000000..c7b47ea5
--- /dev/null
+++ b/org.eclipse.mylyn.github.core/src/org/eclipse/mylyn/internal/github/core/pr/PullRequestComposite.java
@@ -0,0 +1,58 @@
+/******************************************************************************
+ * Copyright (c) 2011 GitHub Inc.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ * Kevin Sawicki (GitHub Inc.) - initial API and implementation
+ *****************************************************************************/
+package org.eclipse.mylyn.internal.github.core.pr;
+
+import java.util.List;
+
+import org.eclipse.egit.github.core.PullRequest;
+import org.eclipse.egit.github.core.PullRequestCommit;
+
+/**
+ * Pull request composite that includes commits
+ */
+public class PullRequestComposite {
+
+ private PullRequest request;
+
+ private List<PullRequestCommit> commits;
+
+ /**
+ * @return request
+ */
+ public PullRequest getRequest() {
+ return request;
+ }
+
+ /**
+ * @param request
+ * @return this pull request composite
+ */
+ public PullRequestComposite setRequest(PullRequest request) {
+ this.request = request;
+ return this;
+ }
+
+ /**
+ * @return commits
+ */
+ public List<PullRequestCommit> getCommits() {
+ return commits;
+ }
+
+ /**
+ * @param commits
+ * @return this pull request composite
+ */
+ public PullRequestComposite setCommits(List<PullRequestCommit> commits) {
+ this.commits = commits;
+ return this;
+ }
+}
diff --git a/org.eclipse.mylyn.github.core/src/org/eclipse/mylyn/internal/github/core/pr/PullRequestConnector.java b/org.eclipse.mylyn.github.core/src/org/eclipse/mylyn/internal/github/core/pr/PullRequestConnector.java
new file mode 100644
index 00000000..14355cb2
--- /dev/null
+++ b/org.eclipse.mylyn.github.core/src/org/eclipse/mylyn/internal/github/core/pr/PullRequestConnector.java
@@ -0,0 +1,265 @@
+/******************************************************************************
+ * Copyright (c) 2011 GitHub Inc.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ * Kevin Sawicki (GitHub Inc.) - initial API and implementation
+ *****************************************************************************/
+package org.eclipse.mylyn.internal.github.core.pr;
+
+import java.io.IOException;
+import java.util.List;
+
+import org.eclipse.core.runtime.CoreException;
+import org.eclipse.core.runtime.IProgressMonitor;
+import org.eclipse.core.runtime.IStatus;
+import org.eclipse.core.runtime.Status;
+import org.eclipse.egit.github.core.Comment;
+import org.eclipse.egit.github.core.IRepositoryIdProvider;
+import org.eclipse.egit.github.core.PullRequest;
+import org.eclipse.egit.github.core.Repository;
+import org.eclipse.egit.github.core.RepositoryId;
+import org.eclipse.egit.github.core.client.GitHubClient;
+import org.eclipse.egit.github.core.client.GsonUtils;
+import org.eclipse.egit.github.core.client.IGitHubConstants;
+import org.eclipse.egit.github.core.service.IssueService;
+import org.eclipse.egit.github.core.service.PullRequestService;
+import org.eclipse.mylyn.commons.net.AuthenticationCredentials;
+import org.eclipse.mylyn.commons.net.AuthenticationType;
+import org.eclipse.mylyn.internal.github.core.GitHub;
+import org.eclipse.mylyn.internal.github.core.QueryUtils;
+import org.eclipse.mylyn.internal.github.core.RepositoryConnector;
+import org.eclipse.mylyn.internal.github.core.issue.IssueConnector;
+import org.eclipse.mylyn.internal.tasks.core.IRepositoryConstants;
+import org.eclipse.mylyn.tasks.core.IRepositoryQuery;
+import org.eclipse.mylyn.tasks.core.TaskRepository;
+import org.eclipse.mylyn.tasks.core.data.AbstractTaskDataHandler;
+import org.eclipse.mylyn.tasks.core.data.TaskData;
+import org.eclipse.mylyn.tasks.core.data.TaskDataCollector;
+import org.eclipse.mylyn.tasks.core.sync.ISynchronizationSession;
+
+/**
+ * GitHub pull request connector.
+ */
+public class PullRequestConnector extends RepositoryConnector {
+
+ /**
+ * SEGMENT_PULL
+ */
+ public static final String SEGMENT_PULL = "/pull"; //$NON-NLS-1$
+
+ /**
+ * GitHub kind.
+ */
+ public static final String KIND = "githubPullRequests"; //$NON-NLS-1$
+
+ /**
+ * Get repository label for id provider.
+ *
+ * @param repo
+ * @return label
+ */
+ public static String getRepositoryLabel(IRepositoryIdProvider repo) {
+ return repo.generateId() + Messages.PullRequestConnector_LabelPullRequests;
+ }
+
+ /**
+ * Create pull request task repository
+ *
+ * @param repo
+ * @param username
+ * @param password
+ * @return task repository
+ */
+ public static TaskRepository createTaskRepository(Repository repo,
+ String username, String password) {
+ String url = PullRequestConnector.appendPulls(GitHub.createGitHubUrl(
+ repo.getOwner().getLogin(), repo.getName()));
+ TaskRepository repository = new TaskRepository(
+ PullRequestConnector.KIND, url);
+ repository.setProperty(IRepositoryConstants.PROPERTY_LABEL,
+ getRepositoryLabel(repo));
+ if (username != null && password != null)
+ repository.setCredentials(AuthenticationType.REPOSITORY,
+ new AuthenticationCredentials(username, password), true);
+ repository.setProperty(IRepositoryConstants.PROPERTY_CATEGORY,
+ IRepositoryConstants.CATEGORY_REVIEW);
+ return repository;
+ }
+
+ /**
+ * Appends a trailing '/pull's segment to the given url
+ *
+ * @param repoUrl
+ * @return appended string
+ */
+ public static String appendPulls(final String repoUrl) {
+ return repoUrl + IGitHubConstants.SEGMENT_PULLS;
+ }
+
+ /**
+ * Strip trailing '/pulls' segment from string if it ends with it.
+ *
+ * @param repoUrl
+ * @return stripped string
+ */
+ public static String stripPulls(String repoUrl) {
+ if (repoUrl.endsWith(IGitHubConstants.SEGMENT_PULLS))
+ repoUrl = repoUrl.substring(0, repoUrl.length()
+ - IGitHubConstants.SEGMENT_PULLS.length());
+ return repoUrl;
+ }
+
+ /**
+ * Get pull request from task data
+ *
+ * @param data
+ * @return pull request
+ */
+ public static PullRequestComposite getPullRequest(TaskData data) {
+ if (data == null)
+ return null;
+ String value = PullRequestAttribute.MODEL.getMetadata().getValue(data);
+ if (value.length() == 0)
+ return null;
+ return GsonUtils.fromJson(value, PullRequestComposite.class);
+ }
+
+ /**
+ * Get repository id from pull request task repository url
+ *
+ * @param prRepoUrl
+ * @return repository id
+ */
+ public static RepositoryId getRepository(String prRepoUrl) {
+ return GitHub.getRepository(stripPulls(prRepoUrl));
+ }
+
+ /**
+ * GitHub specific {@link AbstractTaskDataHandler}.
+ */
+ private final PullRequestTaskDataHandler taskDataHandler;
+
+ /**
+ * Create GitHub issue repository connector
+ */
+ public PullRequestConnector() {
+ taskDataHandler = new PullRequestTaskDataHandler(this);
+ }
+
+ /**
+ * {@inheritDoc}
+ *
+ * @see #KIND
+ */
+ @Override
+ public String getConnectorKind() {
+ return KIND;
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ @Override
+ public String getLabel() {
+ return Messages.PullRequestConnector_Label;
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ @Override
+ public AbstractTaskDataHandler getTaskDataHandler() {
+ return taskDataHandler;
+ }
+
+ @Override
+ public IStatus performQuery(TaskRepository repository,
+ IRepositoryQuery query, TaskDataCollector collector,
+ ISynchronizationSession session, IProgressMonitor monitor) {
+ IStatus result = Status.OK_STATUS;
+ List<String> statuses = QueryUtils.getAttributes(
+ IssueService.FILTER_STATE, query);
+
+ monitor.beginTask(Messages.PullRequestConnector_TaskFetching,
+ statuses.size());
+ try {
+ RepositoryId repo = getRepository(repository.getRepositoryUrl());
+
+ GitHubClient client = IssueConnector.createClient(repository);
+ PullRequestService service = new PullRequestService(client);
+ IssueService commentService = new IssueService(client);
+
+ for (String status : statuses) {
+ List<PullRequest> pulls = service.getPullRequests(repo, status);
+
+ // collect task data
+ for (PullRequest pr : pulls) {
+ pr = service.getPullRequest(repo, pr.getNumber());
+ PullRequestComposite prComp = new PullRequestComposite();
+ prComp.setRequest(pr);
+ List<Comment> comments = null;
+ if (pr.getComments() > 0)
+ comments = commentService.getComments(repo.getOwner(),
+ repo.getName(),
+ Integer.toString(pr.getNumber()));
+ if (pr.getCommits() > 0)
+ prComp.setCommits(service.getCommits(repo,
+ pr.getNumber()));
+ TaskData taskData = taskDataHandler.createTaskData(
+ repository, monitor, repo, prComp, comments);
+ collector.accept(taskData);
+ }
+ monitor.worked(1);
+ }
+ } catch (IOException e) {
+ result = GitHub.createWrappedStatus(e);
+ }
+
+ monitor.done();
+ return result;
+ }
+
+ @Override
+ public TaskData getTaskData(TaskRepository repository, String taskId,
+ IProgressMonitor monitor) throws CoreException {
+ RepositoryId repo = getRepository(repository.getRepositoryUrl());
+
+ try {
+ GitHubClient client = IssueConnector.createClient(repository);
+ PullRequestService service = new PullRequestService(client);
+ PullRequest pr = service.getPullRequest(repo,
+ Integer.parseInt(taskId));
+ PullRequestComposite prComp = new PullRequestComposite();
+ prComp.setRequest(pr);
+ IssueService commentService = new IssueService(client);
+ List<Comment> comments = null;
+ if (pr.getComments() > 0)
+ comments = commentService.getComments(repo.getOwner(),
+ repo.getName(), taskId);
+ if (pr.getCommits() > 0)
+ prComp.setCommits(service.getCommits(repo, pr.getNumber()));
+ return taskDataHandler.createTaskData(repository, monitor, repo,
+ prComp, comments);
+ } catch (IOException e) {
+ throw new CoreException(GitHub.createWrappedStatus(e));
+ }
+ }
+
+ @Override
+ public String getRepositoryUrlFromTaskUrl(String taskFullUrl) {
+ int lastPull = taskFullUrl.lastIndexOf(SEGMENT_PULL);
+ if (lastPull != -1)
+ return taskFullUrl.substring(0, lastPull)
+ + IGitHubConstants.SEGMENT_PULLS;
+ return null;
+ }
+
+ @Override
+ public String getTaskUrl(String repositoryUrl, String taskId) {
+ return stripPulls(repositoryUrl) + SEGMENT_PULL + "/" + taskId; //$NON-NLS-1$
+ }
+}
diff --git a/org.eclipse.mylyn.github.core/src/org/eclipse/mylyn/internal/github/core/pr/PullRequestOperation.java b/org.eclipse.mylyn.github.core/src/org/eclipse/mylyn/internal/github/core/pr/PullRequestOperation.java
new file mode 100644
index 00000000..6e2dabbd
--- /dev/null
+++ b/org.eclipse.mylyn.github.core/src/org/eclipse/mylyn/internal/github/core/pr/PullRequestOperation.java
@@ -0,0 +1,72 @@
+/******************************************************************************
+ * Copyright (c) 2011 GitHub Inc.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ * Kevin Sawicki (GitHub Inc.) - initial API and implementation
+ *****************************************************************************/
+package org.eclipse.mylyn.internal.github.core.pr;
+
+/**
+ * Enumeration of task operations
+ */
+public enum PullRequestOperation {
+
+ /**
+ * LEAD
+ */
+ LEAVE("Leave "), //$NON-NLS-1$
+
+ /**
+ * REOPEN
+ */
+ REOPEN("Reopen"), //$NON-NLS-1$
+
+ /**
+ * CLOSE
+ */
+ CLOSE("Close"); //$NON-NLS-1$
+
+ private final String label;
+
+ private PullRequestOperation(String label) {
+ this.label = label;
+ }
+
+ /**
+ * Get label
+ *
+ * @return label
+ */
+ public String getLabel() {
+ return label;
+ }
+
+ /**
+ * Get id
+ *
+ * @return id
+ */
+ public String getId() {
+ return name();
+ }
+
+ /**
+ * get the operation by its id
+ *
+ * @param opId
+ * the id, or null
+ * @return the operation, or null if the id was null or did not match any
+ * operation
+ */
+ public static PullRequestOperation fromId(final String opId) {
+ for (PullRequestOperation op : values())
+ if (op.getId().equals(opId))
+ return op;
+ return null;
+ }
+
+}
diff --git a/org.eclipse.mylyn.github.core/src/org/eclipse/mylyn/internal/github/core/pr/PullRequestTaskDataHandler.java b/org.eclipse.mylyn.github.core/src/org/eclipse/mylyn/internal/github/core/pr/PullRequestTaskDataHandler.java
new file mode 100644
index 00000000..d7f24620
--- /dev/null
+++ b/org.eclipse.mylyn.github.core/src/org/eclipse/mylyn/internal/github/core/pr/PullRequestTaskDataHandler.java
@@ -0,0 +1,230 @@
+/******************************************************************************
+ * Copyright (c) 2011 GitHub Inc.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ * Kevin Sawicki (GitHub Inc.) - initial API and implementation
+ *****************************************************************************/
+package org.eclipse.mylyn.internal.github.core.pr;
+
+import java.io.IOException;
+import java.util.List;
+import java.util.Set;
+
+import org.eclipse.core.runtime.CoreException;
+import org.eclipse.core.runtime.IProgressMonitor;
+import org.eclipse.egit.github.core.Comment;
+import org.eclipse.egit.github.core.IRepositoryIdProvider;
+import org.eclipse.egit.github.core.PullRequest;
+import org.eclipse.egit.github.core.RepositoryId;
+import org.eclipse.egit.github.core.User;
+import org.eclipse.egit.github.core.client.GitHubClient;
+import org.eclipse.egit.github.core.client.GsonUtils;
+import org.eclipse.egit.github.core.service.IssueService;
+import org.eclipse.egit.github.core.service.PullRequestService;
+import org.eclipse.mylyn.internal.github.core.GitHub;
+import org.eclipse.mylyn.internal.github.core.GitHubTaskDataHandler;
+import org.eclipse.mylyn.internal.github.core.issue.IssueConnector;
+import org.eclipse.mylyn.tasks.core.ITaskMapping;
+import org.eclipse.mylyn.tasks.core.RepositoryResponse;
+import org.eclipse.mylyn.tasks.core.RepositoryResponse.ResponseKind;
+import org.eclipse.mylyn.tasks.core.TaskRepository;
+import org.eclipse.mylyn.tasks.core.data.TaskAttribute;
+import org.eclipse.mylyn.tasks.core.data.TaskData;
+
+/**
+ * GitHub issue task data handler
+ */
+public class PullRequestTaskDataHandler extends GitHubTaskDataHandler {
+
+ private static final String DATA_VERSION = "1.1"; //$NON-NLS-1$
+
+ /**
+ * Create GitHub issue task data handler for connector
+ *
+ * @param connector
+ */
+ public PullRequestTaskDataHandler(PullRequestConnector connector) {
+ }
+
+ /**
+ * Create task data for pull request
+ *
+ * @param repository
+ * @param monitor
+ * @param repo
+ * @param prComp
+ * @return task data
+ */
+ public TaskData createTaskData(TaskRepository repository,
+ IProgressMonitor monitor, IRepositoryIdProvider repo,
+ PullRequestComposite prComp) {
+ PullRequest pr = prComp.getRequest();
+ String key = Integer.toString(pr.getNumber());
+ TaskData data = new TaskData(getAttributeMapper(repository),
+ PullRequestConnector.KIND, repository.getRepositoryUrl(), key);
+ data.setVersion(DATA_VERSION);
+
+ createOperations(data, pr);
+
+ createAttribute(data, PullRequestAttribute.KEY.getMetadata(), key);
+ createAttribute(data, PullRequestAttribute.TITLE.getMetadata(),
+ pr.getTitle());
+ createAttribute(data, PullRequestAttribute.BODY.getMetadata(),
+ pr.getBody());
+ createAttribute(data, PullRequestAttribute.STATUS.getMetadata(),
+ pr.getState());
+ createAttribute(data, PullRequestAttribute.CREATION_DATE.getMetadata(),
+ pr.getCreatedAt());
+ createAttribute(data,
+ PullRequestAttribute.MODIFICATION_DATE.getMetadata(),
+ pr.getUpdatedAt());
+ createAttribute(data, PullRequestAttribute.CLOSED_DATE.getMetadata(),
+ pr.getClosedAt());
+
+ User reporter = pr.getUser();
+ createAttribute(data, PullRequestAttribute.REPORTER.getMetadata(),
+ reporter, repository);
+ String reporterGravatar = reporter != null ? reporter.getAvatarUrl()
+ : null;
+ createAttribute(data,
+ PullRequestAttribute.REPORTER_GRAVATAR.getMetadata(),
+ reporterGravatar);
+
+ createAttribute(data, PullRequestAttribute.COMMENT_NEW.getMetadata());
+
+ createAttribute(data, PullRequestAttribute.MODEL.getMetadata(),
+ GsonUtils.toJson(prComp));
+
+ return data;
+ }
+
+ private void createOperations(TaskData data, PullRequest pr) {
+ createOperationAttribute(data);
+
+ if (data.isNew())
+ return;
+
+ String state = pr.getState();
+ if (state != null) {
+ addOperation(data, pr, PullRequestOperation.LEAVE, true);
+ if (state.equals(IssueService.STATE_OPEN))
+ addOperation(data, pr, PullRequestOperation.CLOSE, false);
+ else if (state.equals(IssueService.STATE_CLOSED))
+ addOperation(data, pr, PullRequestOperation.REOPEN, false);
+ }
+ }
+
+ private void addOperation(TaskData data, PullRequest pr,
+ PullRequestOperation operation, boolean isDefault) {
+ String id = operation.getId();
+ String label = createOperationLabel(pr, operation);
+ addOperation(data, id, label, isDefault);
+ }
+
+ private String createOperationLabel(PullRequest pr,
+ PullRequestOperation operation) {
+ return operation == PullRequestOperation.LEAVE ? operation.getLabel()
+ + pr.getState() : operation.getLabel();
+ }
+
+ /**
+ * Create task data for pull request
+ *
+ * @param repository
+ * @param monitor
+ * @param repo
+ * @param pr
+ * @param comments
+ * @return task data
+ */
+ public TaskData createTaskData(TaskRepository repository,
+ IProgressMonitor monitor, IRepositoryIdProvider repo,
+ PullRequestComposite pr, List<Comment> comments) {
+ TaskData taskData = createTaskData(repository, monitor, repo, pr);
+ taskData.setPartial(false);
+
+ addComments(taskData.getRoot(), comments, repository);
+
+ return taskData;
+ }
+
+ private PullRequest createPullRequest(TaskData taskData) {
+ PullRequest pr = new PullRequest();
+ if (!taskData.isNew())
+ pr.setNumber(Integer.parseInt(taskData.getTaskId()));
+
+ pr.setBody(getAttributeValue(taskData,
+ PullRequestAttribute.BODY.getMetadata()));
+ pr.setTitle(getAttributeValue(taskData,
+ PullRequestAttribute.TITLE.getMetadata()));
+
+ return pr;
+ }
+
+ @Override
+ public boolean initializeTaskData(TaskRepository repository, TaskData data,
+ ITaskMapping initializationData, IProgressMonitor monitor)
+ throws CoreException {
+ data.setVersion(DATA_VERSION);
+ for (PullRequestAttribute attr : PullRequestAttribute.values())
+ if (attr.getMetadata().isInitTask())
+ createAttribute(data, attr.getMetadata(), (String) null);
+ return true;
+ }
+
+ @Override
+ public RepositoryResponse postTaskData(TaskRepository repository,
+ TaskData taskData, Set<TaskAttribute> oldAttributes,
+ IProgressMonitor monitor) throws CoreException {
+ String taskId = taskData.getTaskId();
+ PullRequest pr = createPullRequest(taskData);
+ RepositoryId repo = PullRequestConnector.getRepository(repository
+ .getRepositoryUrl());
+ try {
+ GitHubClient client = IssueConnector.createClient(repository);
+ PullRequestService prService = new PullRequestService(client);
+ IssueService issueService = new IssueService(client);
+ if (taskData.isNew()) {
+ pr.setState(IssueService.STATE_OPEN);
+ pr = prService.createPullRequest(repo, pr);
+ taskId = Integer.toString(pr.getNumber());
+ } else {
+ // Handle new comment
+ String comment = getAttributeValue(taskData,
+ PullRequestAttribute.COMMENT_NEW.getMetadata());
+ if (comment != null && comment.length() > 0)
+ issueService.createComment(repo.getOwner(), repo.getName(),
+ taskId, comment);
+
+ // Handle state change
+ TaskAttribute operationAttribute = taskData.getRoot()
+ .getAttribute(TaskAttribute.OPERATION);
+ if (operationAttribute != null) {
+ PullRequestOperation operation = PullRequestOperation
+ .fromId(operationAttribute.getValue());
+ if (operation != PullRequestOperation.LEAVE)
+ switch (operation) {
+ case REOPEN:
+ pr.setState(IssueService.STATE_OPEN);
+ break;
+ case CLOSE:
+ pr.setState(IssueService.STATE_CLOSED);
+ break;
+ default:
+ break;
+ }
+ }
+ prService.editPullRequest(repo, pr);
+ }
+ return new RepositoryResponse(
+ taskData.isNew() ? ResponseKind.TASK_CREATED
+ : ResponseKind.TASK_UPDATED, taskId);
+ } catch (IOException e) {
+ throw new CoreException(GitHub.createWrappedStatus(e));
+ }
+ }
+}
diff --git a/org.eclipse.mylyn.github.core/src/org/eclipse/mylyn/internal/github/core/pr/PullRequestUtils.java b/org.eclipse.mylyn.github.core/src/org/eclipse/mylyn/internal/github/core/pr/PullRequestUtils.java
new file mode 100644
index 00000000..5eb734f4
--- /dev/null
+++ b/org.eclipse.mylyn.github.core/src/org/eclipse/mylyn/internal/github/core/pr/PullRequestUtils.java
@@ -0,0 +1,145 @@
+/******************************************************************************
+ * Copyright (c) 2011 GitHub Inc.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ * Kevin Sawicki (GitHub Inc.) - initial API and implementation
+ *****************************************************************************/
+package org.eclipse.mylyn.internal.github.core.pr;
+
+import java.io.File;
+import java.io.IOException;
+import java.net.URISyntaxException;
+
+import org.eclipse.egit.core.Activator;
+import org.eclipse.egit.core.RepositoryCache;
+import org.eclipse.egit.github.core.PullRequest;
+import org.eclipse.egit.github.core.PullRequestMarker;
+import org.eclipse.jgit.lib.ConfigConstants;
+import org.eclipse.jgit.lib.Constants;
+import org.eclipse.jgit.lib.Repository;
+import org.eclipse.jgit.lib.StoredConfig;
+import org.eclipse.jgit.transport.RefSpec;
+import org.eclipse.jgit.transport.RemoteConfig;
+import org.eclipse.jgit.transport.URIish;
+import org.eclipse.mylyn.internal.github.core.GitHub;
+
+/**
+ * Pull request utilities
+ */
+public abstract class PullRequestUtils {
+
+ /**
+ * HEAD_SOURCE
+ */
+ public static final String HEAD_SOURCE = '+' + Constants.R_HEADS + '*';
+
+ /**
+ * Get destination ref spec
+ *
+ * @param remote
+ * @return ref spec
+ */
+ public static String getDesintationRef(RemoteConfig remote) {
+ return Constants.R_REMOTES + remote.getName() + "/*"; //$NON-NLS-1$
+ }
+
+ /**
+ * Get branch name for pull request
+ *
+ * @param request
+ * @return non-null/non-empty branch name
+ */
+ public static String getBranchName(PullRequest request) {
+ return "pr-" + request.getNumber(); //$NON-NLS-1$
+ }
+
+ /**
+ * Get Git repository for pull request
+ *
+ * @param request
+ * @return repository or null if none found
+ */
+ public static Repository getRepository(PullRequest request) {
+ org.eclipse.egit.github.core.Repository remoteRepo = request.getBase()
+ .getRepository();
+ String id = remoteRepo.getOwner().getLogin() + '/'
+ + remoteRepo.getName() + Constants.DOT_GIT;
+ RepositoryCache cache = Activator.getDefault().getRepositoryCache();
+ for (String path : Activator.getDefault().getRepositoryUtil()
+ .getConfiguredRepositories())
+ try {
+ Repository repo = cache.lookupRepository(new File(path));
+ RemoteConfig rc = new RemoteConfig(repo.getConfig(),
+ Constants.DEFAULT_REMOTE_NAME);
+ for (URIish uri : rc.getURIs())
+ if (uri.toString().endsWith(id))
+ return repo;
+ } catch (IOException e) {
+ GitHub.logError(e);
+ continue;
+ } catch (URISyntaxException e) {
+ GitHub.logError(e);
+ continue;
+ }
+ return null;
+ }
+
+ /**
+ * Configure pull request topic branch to use head remote
+ *
+ * @param repo
+ * @param request
+ * @throws IOException
+ */
+ public static void configureTopicBranch(Repository repo, PullRequest request)
+ throws IOException {
+ String branch = getBranchName(request);
+ PullRequestMarker head = request.getHead();
+ String remote = head.getRepository().getOwner().getLogin();
+ StoredConfig config = repo.getConfig();
+ config.setString(ConfigConstants.CONFIG_BRANCH_SECTION, branch,
+ ConfigConstants.CONFIG_KEY_MERGE, Constants.R_REMOTES + remote
+ + "/" + head.getRef()); //$NON-NLS-1$
+ config.setString(ConfigConstants.CONFIG_BRANCH_SECTION, branch,
+ ConfigConstants.CONFIG_KEY_REMOTE, remote);
+ config.save();
+ }
+
+ /**
+ * Add remote for the head of a pull request if it doesn't exist
+ *
+ * @param repo
+ * @param request
+ * @return remote config
+ * @throws IOException
+ * @throws URISyntaxException
+ */
+ public static RemoteConfig addRemote(Repository repo, PullRequest request)
+ throws IOException, URISyntaxException {
+ StoredConfig config = repo.getConfig();
+ org.eclipse.egit.github.core.Repository head = request.getHead()
+ .getRepository();
+ String name = head.getOwner().getLogin();
+ for (RemoteConfig candidate : RemoteConfig.getAllRemoteConfigs(config))
+ if (name.equals(candidate.getName()))
+ return candidate;
+
+ RemoteConfig remote = new RemoteConfig(config, name);
+ if (head.isPrivate())
+ remote.addURI(new URIish(org.eclipse.egit.github.core.Repository
+ .createRemoteSshUrl(head)));
+ else
+ remote.addURI(new URIish(org.eclipse.egit.github.core.Repository
+ .createRemoteReadOnlyUrl(head)));
+
+ remote.addFetchRefSpec(new RefSpec(HEAD_SOURCE
+ + ":" + getDesintationRef(remote))); //$NON-NLS-1$
+ remote.update(config);
+ config.save();
+ return remote;
+ }
+}
diff --git a/org.eclipse.mylyn.github.core/src/org/eclipse/mylyn/internal/github/core/pr/messages.properties b/org.eclipse.mylyn.github.core/src/org/eclipse/mylyn/internal/github/core/pr/messages.properties
new file mode 100644
index 00000000..474d81f6
--- /dev/null
+++ b/org.eclipse.mylyn.github.core/src/org/eclipse/mylyn/internal/github/core/pr/messages.properties
@@ -0,0 +1,14 @@
+PullRequestAttribute_LabelClosedAt=Closed:
+PullRequestAttribute_LabelComment=Comment:
+PullRequestAttribute_LabelCreatedAt=Created:
+PullRequestAttribute_LabelDescription=Description
+PullRequestAttribute_LabelKey=Key
+PullRequestAttribute_LabelMergedAt=Merged:
+PullRequestAttribute_LabelModel=Model
+PullRequestAttribute_LabelModifiedAt=Modified:
+PullRequestAttribute_LabelReporter=Reporter
+PullRequestAttribute_LabelStatus=Status
+PullRequestAttribute_LabelSummary=Summary
+PullRequestConnector_Label=GitHub Pull Requests
+PullRequestConnector_LabelPullRequests=\ pull requests
+PullRequestConnector_TaskFetching=Fetching pull requests

Back to the top