Merge pull request #406

... with some further changes
This commit is contained in:
Kohsuke Kawaguchi
2018-01-13 09:47:37 -08:00
9 changed files with 247 additions and 114 deletions

View File

@@ -23,26 +23,22 @@
*/
package org.kohsuke.github;
import javax.annotation.CheckForNull;
import java.io.IOException;
import java.net.URL;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collection;
import java.util.Date;
import java.util.List;
import static org.kohsuke.github.Previews.*;
/**
* A pull request.
*
*
* @author Kohsuke Kawaguchi
* @see GHRepository#getPullRequest(int)
*/
@SuppressWarnings({"UnusedDeclaration"})
public class GHPullRequest extends GHIssue {
private static final String COMMENTS_ACTION = "/comments";
private String patch_url, diff_url, issue_url;
private GHCommitPointer base;
private String merged_at;
@@ -91,7 +87,7 @@ public class GHPullRequest extends GHIssue {
public URL getPatchUrl() {
return GitHub.parseURL(patch_url);
}
/**
* The URL of the patch file.
* like https://github.com/jenkinsci/jenkins/pull/100.patch
@@ -114,7 +110,7 @@ public class GHPullRequest extends GHIssue {
public GHCommitPointer getHead() {
return head;
}
@Deprecated
public Date getIssueUpdatedAt() throws IOException {
return super.getUpdatedAt();
@@ -262,7 +258,6 @@ public class GHPullRequest extends GHIssue {
return new PagedIterable<GHPullRequestReview>() {
public PagedIterator<GHPullRequestReview> _iterator(int pageSize) {
return new PagedIterator<GHPullRequestReview>(root.retrieve()
.withPreview(BLACK_CAT)
.asIterator(String.format("%s/reviews", getApiRoute()),
GHPullRequestReview[].class, pageSize)) {
@Override
@@ -282,7 +277,7 @@ public class GHPullRequest extends GHIssue {
public PagedIterable<GHPullRequestReviewComment> listReviewComments() throws IOException {
return new PagedIterable<GHPullRequestReviewComment>() {
public PagedIterator<GHPullRequestReviewComment> _iterator(int pageSize) {
return new PagedIterator<GHPullRequestReviewComment>(root.retrieve().asIterator(getApiRoute() + "/comments",
return new PagedIterator<GHPullRequestReviewComment>(root.retrieve().asIterator(getApiRoute() + COMMENTS_ACTION,
GHPullRequestReviewComment[].class, pageSize)) {
protected void wrapUp(GHPullRequestReviewComment[] page) {
for (GHPullRequestReviewComment c : page)
@@ -312,32 +307,8 @@ public class GHPullRequest extends GHIssue {
};
}
@Preview
@Deprecated
public GHPullRequestReview createReview(String body, @CheckForNull GHPullRequestReviewState event,
GHPullRequestReviewComment... comments)
throws IOException {
return createReview(body, event, Arrays.asList(comments));
}
@Preview
@Deprecated
public GHPullRequestReview createReview(String body, @CheckForNull GHPullRequestReviewState event,
List<GHPullRequestReviewComment> comments)
throws IOException {
// if (event == null) {
// event = GHPullRequestReviewState.PENDING;
// }
List<DraftReviewComment> draftComments = new ArrayList<DraftReviewComment>(comments.size());
for (GHPullRequestReviewComment c : comments) {
draftComments.add(new DraftReviewComment(c.getBody(), c.getPath(), c.getPosition()));
}
return new Requester(root).method("POST")
.with("body", body)
//.with("event", event.name())
._with("comments", draftComments)
.withPreview(BLACK_CAT)
.to(getApiRoute() + "/reviews", GHPullRequestReview.class).wrapUp(this);
public GHPullRequestReviewBuilder createReview() {
return new GHPullRequestReviewBuilder(this);
}
public GHPullRequestReviewComment createReviewComment(String body, String sha, String path, int position) throws IOException {
@@ -346,7 +317,7 @@ public class GHPullRequest extends GHIssue {
.with("commit_id", sha)
.with("path", path)
.with("position", position)
.to(getApiRoute() + "/comments", GHPullRequestReviewComment.class).wrapUp(this);
.to(getApiRoute() + COMMENTS_ACTION, GHPullRequestReviewComment.class).wrapUp(this);
}
/**
@@ -387,10 +358,10 @@ public class GHPullRequest extends GHIssue {
*/
public void merge(String msg, String sha, MergeMethod method) throws IOException {
new Requester(root).method("PUT")
.with("commit_message",msg)
.with("sha",sha)
.with("merge_method",method)
.to(getApiRoute()+"/merge");
.with("commit_message", msg)
.with("sha", sha)
.with("merge_method", method)
.to(getApiRoute() + "/merge");
}
public enum MergeMethod{ MERGE, SQUASH, REBASE }
@@ -401,28 +372,4 @@ public class GHPullRequest extends GHIssue {
fetchedIssueDetails = true;
}
}
private static class DraftReviewComment {
private String body;
private String path;
private int position;
public DraftReviewComment(String body, String path, int position) {
this.body = body;
this.path = path;
this.position = position;
}
public String getBody() {
return body;
}
public String getPath() {
return path;
}
public int getPosition() {
return position;
}
}
}

View File

@@ -23,17 +23,19 @@
*/
package org.kohsuke.github;
import edu.umd.cs.findbugs.annotations.SuppressFBWarnings;
import javax.annotation.CheckForNull;
import java.io.IOException;
import java.net.URL;
import static org.kohsuke.github.Previews.*;
/**
* Review to the pull request
* Review to a pull request.
*
* @see GHPullRequest#listReviews()
* @see GHPullRequest#createReview(String, GHPullRequestReviewState, GHPullRequestReviewComment...)
* @see GHPullRequestReviewBuilder
*/
@SuppressFBWarnings(value = {"UWF_UNWRITTEN_FIELD"}, justification = "JSON API")
public class GHPullRequestReview extends GHObject {
GHPullRequest owner;
@@ -72,6 +74,7 @@ public class GHPullRequestReview extends GHObject {
return commit_id;
}
@CheckForNull
public GHPullRequestReviewState getState() {
return state;
}
@@ -85,41 +88,41 @@ public class GHPullRequestReview extends GHObject {
return owner.getApiRoute()+"/reviews/"+id;
}
/**
* @deprecated
* Former preview method that changed when it got public. Left here for backward compatibility.
* Use {@link #submit(String, GHPullRequestReviewEvent)}
*/
public void submit(String body, GHPullRequestReviewState state) throws IOException {
submit(body,state.toEvent());
}
/**
* Updates the comment.
*/
@Preview
@Deprecated
public void submit(String body, GHPullRequestReviewState event) throws IOException {
public void submit(String body, GHPullRequestReviewEvent event) throws IOException {
new Requester(owner.root).method("POST")
.with("body", body)
.with("event", event.action())
.withPreview("application/vnd.github.black-cat-preview+json")
.to(getApiRoute()+"/events",this);
this.body = body;
this.state = event;
this.state = event.toState();
}
/**
* Deletes this review.
*/
@Preview
@Deprecated
public void delete() throws IOException {
new Requester(owner.root).method("DELETE")
.withPreview(BLACK_CAT)
.to(getApiRoute());
}
/**
* Dismisses this review.
*/
@Preview
@Deprecated
public void dismiss(String message) throws IOException {
new Requester(owner.root).method("PUT")
.with("message", message)
.withPreview(BLACK_CAT)
.to(getApiRoute()+"/dismissals");
state = GHPullRequestReviewState.DISMISSED;
}
@@ -127,14 +130,11 @@ public class GHPullRequestReview extends GHObject {
/**
* Obtains all the review comments associated with this pull request review.
*/
@Preview
@Deprecated
public PagedIterable<GHPullRequestReviewComment> listReviewComments() throws IOException {
return new PagedIterable<GHPullRequestReviewComment>() {
public PagedIterator<GHPullRequestReviewComment> _iterator(int pageSize) {
return new PagedIterator<GHPullRequestReviewComment>(
owner.root.retrieve()
.withPreview(BLACK_CAT)
.asIterator(getApiRoute() + "/comments",
GHPullRequestReviewComment[].class, pageSize)) {
protected void wrapUp(GHPullRequestReviewComment[] page) {
@@ -145,5 +145,4 @@ public class GHPullRequestReview extends GHObject {
}
};
}
}

View File

@@ -0,0 +1,91 @@
package org.kohsuke.github;
import java.io.IOException;
import java.util.ArrayList;
import java.util.List;
/**
* Builds up a creation of new {@link GHPullRequestReview}.
*
* @author Kohsuke Kawaguchi
* @see GHPullRequest#createReview()
*/
public class GHPullRequestReviewBuilder {
private final GHPullRequest pr;
private final Requester builder;
private final List<DraftReviewComment> comments = new ArrayList<DraftReviewComment>();
/*package*/ GHPullRequestReviewBuilder(GHPullRequest pr) {
this.pr = pr;
this.builder = new Requester(pr.root);
}
// public GHPullRequestReview createReview(@Nullable String commitId, String body, GHPullRequestReviewEvent event,
// List<GHPullRequestReviewComment> comments) throws IOException
/**
* The SHA of the commit that needs a review. Not using the latest commit SHA may render your review comment outdated if a subsequent commit modifies the line you specify as the position. Defaults to the most recent commit in the pull request when you do not specify a value.
*/
public GHPullRequestReviewBuilder commitId(String commitId) {
builder.with("commit_id",commitId);
return this;
}
/**
* Required when using REQUEST_CHANGES or COMMENT for the event parameter. The body text of the pull request review.
*/
public GHPullRequestReviewBuilder body(String body) {
builder.with("body",body);
return this;
}
/**
* The review action you want to perform. The review actions include: APPROVE, REQUEST_CHANGES, or COMMENT.
* By leaving this blank, you set the review action state to PENDING,
* which means you will need to {@linkplain GHPullRequestReview#submit() submit the pull request review} when you are ready.
*/
public GHPullRequestReviewBuilder event(GHPullRequestReviewEvent event) {
builder.with("event",event.action());
return this;
}
/**
* @param body The relative path to the file that necessitates a review comment.
* @param path The position in the diff where you want to add a review comment. Note this value is not the same as the line number in the file. For help finding the position value, read the note below.
* @param position Text of the review comment.
*/
public GHPullRequestReviewBuilder comment(String body, String path, int position) {
comments.add(new DraftReviewComment(body,path,position));
return this;
}
public GHPullRequestReview create() throws IOException {
return builder.method("POST")._with("comments",comments)
.to(pr.getApiRoute() + "/reviews", GHPullRequestReview.class)
.wrapUp(pr);
}
private static class DraftReviewComment {
private String body;
private String path;
private int position;
DraftReviewComment(String body, String path, int position) {
this.body = body;
this.path = path;
this.position = position;
}
public String getBody() {
return body;
}
public String getPath() {
return path;
}
public int getPosition() {
return position;
}
}
}

View File

@@ -25,6 +25,7 @@ package org.kohsuke.github;
import java.io.IOException;
import java.net.URL;
import javax.annotation.CheckForNull;
import static org.kohsuke.github.Previews.*;
@@ -41,8 +42,10 @@ public class GHPullRequestReviewComment extends GHObject implements Reactable {
private String body;
private GHUser user;
private String path;
private int position;
private int originalPosition;
private int position = -1;
private int original_position = -1;
private long in_reply_to_id = -1L;
public static GHPullRequestReviewComment draft(String body, String path, int position) {
GHPullRequestReviewComment result = new GHPullRequestReviewComment();
@@ -82,12 +85,19 @@ public class GHPullRequestReviewComment extends GHObject implements Reactable {
return path;
}
public int getPosition() {
return position;
@CheckForNull
public Integer getPosition() {
return position == -1 ? null : position;
}
public int getOriginalPosition() {
return originalPosition;
@CheckForNull
public Integer getOriginalPosition() {
return original_position == -1 ? null : original_position;
}
@CheckForNull
public Long getInReplyToId() {
return in_reply_to_id == -1 ? null : in_reply_to_id;
}
@Override
@@ -114,6 +124,17 @@ public class GHPullRequestReviewComment extends GHObject implements Reactable {
new Requester(owner.root).method("DELETE").to(getApiRoute());
}
/**
* Create a new comment that replies to this comment.
*/
public GHPullRequestReviewComment reply(String body) throws IOException {
return new Requester(owner.root).method("POST")
.with("body", body)
.with("in_reply_to", getId())
.to(getApiRoute() + "/comments", GHPullRequestReviewComment.class)
.wrapUp(owner);
}
@Preview @Deprecated
public GHReaction createReaction(ReactionContent content) throws IOException {
return new Requester(owner.root)
@@ -126,7 +147,7 @@ public class GHPullRequestReviewComment extends GHObject implements Reactable {
public PagedIterable<GHReaction> listReactions() {
return new PagedIterable<GHReaction>() {
public PagedIterator<GHReaction> _iterator(int pageSize) {
return new PagedIterator<GHReaction>(owner.root.retrieve().withPreview(SQUIRREL_GIRL).asIterator(getApiRoute()+"/reactions", GHReaction[].class, pageSize)) {
return new PagedIterator<GHReaction>(owner.root.retrieve().withPreview(SQUIRREL_GIRL).asIterator(getApiRoute() + "/reactions", GHReaction[].class, pageSize)) {
@Override
protected void wrapUp(GHReaction[] page) {
for (GHReaction c : page)

View File

@@ -0,0 +1,51 @@
/*
* The MIT License
*
* Copyright (c) 2011, Eric Maupin
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE.
*/
package org.kohsuke.github;
/**
* Action to perform on {@link GHPullRequestReview}.
*/
public enum GHPullRequestReviewEvent {
PENDING,
APPROVE,
REQUEST_CHANGES,
COMMENT;
/*package*/ String action() {
return this==PENDING ? null : name();
}
/**
* When a {@link GHPullRequestReview} is submitted with this event, it should transition to this state.
*/
/*package*/ GHPullRequestReviewState toState() {
switch (this) {
case PENDING: return GHPullRequestReviewState.PENDING;
case APPROVE: return GHPullRequestReviewState.APPROVED;
case REQUEST_CHANGES: return GHPullRequestReviewState.CHANGES_REQUESTED;
case COMMENT: return GHPullRequestReviewState.COMMENTED;
}
throw new IllegalStateException();
}
}

View File

@@ -1,19 +1,39 @@
package org.kohsuke.github;
/**
* Current state of {@link GHPullRequestReview}
*/
public enum GHPullRequestReviewState {
PENDING(null),
APPROVED("APPROVE"),
REQUEST_CHANGES("REQUEST_CHANGES"),
COMMENTED("COMMENT"),
DISMISSED(null);
PENDING,
APPROVED,
CHANGES_REQUESTED,
/**
* @deprecated
* This was the thing when this API was in preview, but it changed when it became public.
* Use {@link #CHANGES_REQUESTED}. Left here for compatibility.
*/
REQUEST_CHANGES,
COMMENTED,
DISMISSED;
private final String _action;
GHPullRequestReviewState(String action) {
_action = action;
/**
* @deprecated
* This was an internal method accidentally exposed.
* Left here for compatibility.
*/
public String action() {
GHPullRequestReviewEvent e = toEvent();
return e==null ? null : e.action();
}
public String action() {
return _action;
/*package*/ GHPullRequestReviewEvent toEvent() {
switch (this) {
case PENDING: return GHPullRequestReviewEvent.PENDING;
case APPROVED: return GHPullRequestReviewEvent.APPROVE;
case CHANGES_REQUESTED: return GHPullRequestReviewEvent.REQUEST_CHANGES;
case REQUEST_CHANGES: return GHPullRequestReviewEvent.REQUEST_CHANGES;
case COMMENTED: return GHPullRequestReviewEvent.COMMENT;
}
return null;
}
}

View File

@@ -8,5 +8,4 @@ package org.kohsuke.github;
static final String DRAX = "application/vnd.github.drax-preview+json";
static final String SQUIRREL_GIRL = "application/vnd.github.squirrel-girl-preview";
static final String CLOAK = "application/vnd.github.cloak-preview";
static final String BLACK_CAT = "application/vnd.github.black-cat-preview+json";
}

View File

@@ -135,6 +135,10 @@ class Requester {
return _with(key, value);
}
public Requester with(String key, long value) {
return _with(key, value);
}
public Requester with(String key, Integer value) {
if (value!=null)
_with(key, value);

View File

@@ -7,8 +7,7 @@ import java.io.IOException;
import java.util.Collection;
import java.util.List;
import static org.hamcrest.CoreMatchers.is;
import static org.hamcrest.CoreMatchers.notNullValue;
import static org.hamcrest.CoreMatchers.*;
/**
* @author Kohsuke Kawaguchi
@@ -33,9 +32,10 @@ public class PullRequestTest extends AbstractGitHubApiTestBase {
public void testPullRequestReviews() throws Exception {
String name = rnd.next();
GHPullRequest p = getRepository().createPullRequest(name, "stable", "master", "## test");
GHPullRequestReview draftReview = p.createReview("Some draft review", null,
GHPullRequestReviewComment.draft("Some niggle", "changelog.html", 1)
);
GHPullRequestReview draftReview = p.createReview()
.body("Some draft review")
.comment("Some niggle", "changelog.html", 1)
.create();
assertThat(draftReview.getState(), is(GHPullRequestReviewState.PENDING));
assertThat(draftReview.getBody(), is("Some draft review"));
assertThat(draftReview.getCommitId(), notNullValue());
@@ -45,15 +45,16 @@ public class PullRequestTest extends AbstractGitHubApiTestBase {
assertThat(review.getState(), is(GHPullRequestReviewState.PENDING));
assertThat(review.getBody(), is("Some draft review"));
assertThat(review.getCommitId(), notNullValue());
review.submit("Some review comment", GHPullRequestReviewState.COMMENTED);
draftReview.submit("Some review comment", GHPullRequestReviewEvent.COMMENT);
List<GHPullRequestReviewComment> comments = review.listReviewComments().asList();
assertEquals(1, comments.size());
GHPullRequestReviewComment comment = comments.get(0);
assertEquals("Some niggle", comment.getBody());
review = p.createReview("Some new review", null,
GHPullRequestReviewComment.draft("Some niggle", "changelog.html", 1)
);
review.delete();
draftReview = p.createReview()
.body("Some new review")
.comment("Some niggle", "changelog.html", 1)
.create();
draftReview.delete();
}
@Test