mirror of
https://github.com/jlengrand/github-api.git
synced 2026-03-17 15:50:20 +00:00
Compare commits
24 Commits
github-api
...
github-api
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
3dbb516084 | ||
|
|
32177283b3 | ||
|
|
3a66e90b7a | ||
|
|
a454fb10ec | ||
|
|
b5386a35ee | ||
|
|
11651da411 | ||
|
|
88d52c44ad | ||
|
|
2d7d4bbd4e | ||
|
|
e6ee278fde | ||
|
|
6380cf9ed0 | ||
|
|
2e78dc52c7 | ||
|
|
c5009ab44b | ||
|
|
0780e10fa2 | ||
|
|
0731f63237 | ||
|
|
a29896042b | ||
|
|
68ebc08c9d | ||
|
|
a1df526f93 | ||
|
|
0023ecefa4 | ||
|
|
511f156603 | ||
|
|
3f223b1ba0 | ||
|
|
a1528a1a63 | ||
|
|
b8bfddbf3a | ||
|
|
47fc813027 | ||
|
|
c7f2228a44 |
4
pom.xml
4
pom.xml
@@ -7,7 +7,7 @@
|
|||||||
</parent>
|
</parent>
|
||||||
|
|
||||||
<artifactId>github-api</artifactId>
|
<artifactId>github-api</artifactId>
|
||||||
<version>1.80</version>
|
<version>1.82</version>
|
||||||
<name>GitHub API for Java</name>
|
<name>GitHub API for Java</name>
|
||||||
<url>http://github-api.kohsuke.org/</url>
|
<url>http://github-api.kohsuke.org/</url>
|
||||||
<description>GitHub API for Java</description>
|
<description>GitHub API for Java</description>
|
||||||
@@ -16,7 +16,7 @@
|
|||||||
<connection>scm:git:git@github.com/kohsuke/${project.artifactId}.git</connection>
|
<connection>scm:git:git@github.com/kohsuke/${project.artifactId}.git</connection>
|
||||||
<developerConnection>scm:git:ssh://git@github.com/kohsuke/${project.artifactId}.git</developerConnection>
|
<developerConnection>scm:git:ssh://git@github.com/kohsuke/${project.artifactId}.git</developerConnection>
|
||||||
<url>http://${project.artifactId}.kohsuke.org/</url>
|
<url>http://${project.artifactId}.kohsuke.org/</url>
|
||||||
<tag>github-api-1.80</tag>
|
<tag>github-api-1.82</tag>
|
||||||
</scm>
|
</scm>
|
||||||
|
|
||||||
<distributionManagement>
|
<distributionManagement>
|
||||||
|
|||||||
64
src/main/java/org/kohsuke/github/GHBlob.java
Normal file
64
src/main/java/org/kohsuke/github/GHBlob.java
Normal file
@@ -0,0 +1,64 @@
|
|||||||
|
package org.kohsuke.github;
|
||||||
|
|
||||||
|
import org.apache.commons.codec.binary.Base64InputStream;
|
||||||
|
|
||||||
|
import java.io.ByteArrayInputStream;
|
||||||
|
import java.io.InputStream;
|
||||||
|
import java.io.UnsupportedEncodingException;
|
||||||
|
import java.net.URL;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @author Kanstantsin Shautsou
|
||||||
|
* @author Kohsuke Kawaguchi
|
||||||
|
* @see GHTreeEntry#asBlob()
|
||||||
|
* @see GHRepository#getBlob(String)
|
||||||
|
* @see <a href="https://developer.github.com/v3/git/blobs/#get-a-blob">Get a blob</a>
|
||||||
|
*/
|
||||||
|
public class GHBlob {
|
||||||
|
private String content, encoding, url, sha;
|
||||||
|
private long size;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* API URL of this blob.
|
||||||
|
*/
|
||||||
|
public URL getUrl() {
|
||||||
|
return GitHub.parseURL(url);
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getSha() {
|
||||||
|
return sha;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Number of bytes in this blob.
|
||||||
|
*/
|
||||||
|
public long getSize() {
|
||||||
|
return size;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getEncoding() {
|
||||||
|
return encoding;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Encoded content. You probably want {@link #read()}
|
||||||
|
*/
|
||||||
|
public String getContent() {
|
||||||
|
return content;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Retrieves the actual bytes of the blob.
|
||||||
|
*/
|
||||||
|
public InputStream read() {
|
||||||
|
if (encoding.equals("base64")) {
|
||||||
|
try {
|
||||||
|
return new Base64InputStream(new ByteArrayInputStream(content.getBytes("US-ASCII")), false);
|
||||||
|
} catch (UnsupportedEncodingException e) {
|
||||||
|
throw new AssertionError(e); // US-ASCII is mandatory
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
throw new UnsupportedOperationException("Unrecognized encoding: "+encoding);
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -37,6 +37,12 @@ public class GHCommit {
|
|||||||
|
|
||||||
private int comment_count;
|
private int comment_count;
|
||||||
|
|
||||||
|
static class Tree {
|
||||||
|
String sha;
|
||||||
|
}
|
||||||
|
|
||||||
|
private Tree tree;
|
||||||
|
|
||||||
@WithBridgeMethods(value = GHAuthor.class, castRequired = true)
|
@WithBridgeMethods(value = GHAuthor.class, castRequired = true)
|
||||||
public GitUser getAuthor() {
|
public GitUser getAuthor() {
|
||||||
return author;
|
return author;
|
||||||
@@ -224,6 +230,13 @@ public class GHCommit {
|
|||||||
return stats.deletions;
|
return stats.deletions;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Use this method to walk the tree
|
||||||
|
*/
|
||||||
|
public GHTree getTree() throws IOException {
|
||||||
|
return owner.getTree(getCommitShortInfo().tree.sha);
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* URL of this commit like "https://github.com/kohsuke/sandbox-ant/commit/8ae38db0ea5837313ab5f39d43a6f73de3bd9000"
|
* URL of this commit like "https://github.com/kohsuke/sandbox-ant/commit/8ae38db0ea5837313ab5f39d43a6f73de3bd9000"
|
||||||
*/
|
*/
|
||||||
|
|||||||
@@ -29,13 +29,15 @@ import edu.umd.cs.findbugs.annotations.SuppressFBWarnings;
|
|||||||
|
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
import java.net.URL;
|
import java.net.URL;
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.Arrays;
|
||||||
import java.util.Collection;
|
import java.util.Collection;
|
||||||
import java.util.Collections;
|
import java.util.Collections;
|
||||||
import java.util.Date;
|
import java.util.Date;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.Locale;
|
import java.util.Locale;
|
||||||
|
|
||||||
import static org.kohsuke.github.Previews.SQUIRREL_GIRL;
|
import static org.kohsuke.github.Previews.*;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Represents an issue on GitHub.
|
* Represents an issue on GitHub.
|
||||||
@@ -51,7 +53,8 @@ public class GHIssue extends GHObject implements Reactable{
|
|||||||
GHRepository owner;
|
GHRepository owner;
|
||||||
|
|
||||||
// API v3
|
// API v3
|
||||||
protected GHUser assignee;
|
protected GHUser assignee; // not sure what this field is now that 'assignees' exist
|
||||||
|
protected GHUser[] assignees;
|
||||||
protected String state;
|
protected String state;
|
||||||
protected int number;
|
protected int number;
|
||||||
protected String closed_at;
|
protected String closed_at;
|
||||||
@@ -81,6 +84,7 @@ public class GHIssue extends GHObject implements Reactable{
|
|||||||
/*package*/ GHIssue wrap(GitHub root) {
|
/*package*/ GHIssue wrap(GitHub root) {
|
||||||
this.root = root;
|
this.root = root;
|
||||||
if(assignee != null) assignee.wrapUp(root);
|
if(assignee != null) assignee.wrapUp(root);
|
||||||
|
if(assignees!=null) GHUser.wrap(assignees,root);
|
||||||
if(user != null) user.wrapUp(root);
|
if(user != null) user.wrapUp(root);
|
||||||
if(closed_by != null) closed_by.wrapUp(root);
|
if(closed_by != null) closed_by.wrapUp(root);
|
||||||
return this;
|
return this;
|
||||||
@@ -187,7 +191,7 @@ public class GHIssue extends GHObject implements Reactable{
|
|||||||
}
|
}
|
||||||
|
|
||||||
public void assignTo(GHUser user) throws IOException {
|
public void assignTo(GHUser user) throws IOException {
|
||||||
editIssue("assignee", user.getLogin());
|
setAssignees(user);
|
||||||
}
|
}
|
||||||
|
|
||||||
public void setLabels(String... labels) throws IOException {
|
public void setLabels(String... labels) throws IOException {
|
||||||
@@ -242,6 +246,40 @@ public class GHIssue extends GHObject implements Reactable{
|
|||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public void addAssignees(GHUser... assignees) throws IOException {
|
||||||
|
addAssignees(Arrays.asList(assignees));
|
||||||
|
}
|
||||||
|
|
||||||
|
public void addAssignees(Collection<GHUser> assignees) throws IOException {
|
||||||
|
List<String> names = toLogins(assignees);
|
||||||
|
root.retrieve().method("POST").with("assignees",names).to(getIssuesApiRoute()+"/assignees",this);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setAssignees(GHUser... assignees) throws IOException {
|
||||||
|
setAssignees(Arrays.asList(assignees));
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setAssignees(Collection<GHUser> assignees) throws IOException {
|
||||||
|
editIssue("assignees",toLogins(assignees));
|
||||||
|
}
|
||||||
|
|
||||||
|
public void removeAssignees(GHUser... assignees) throws IOException {
|
||||||
|
removeAssignees(Arrays.asList(assignees));
|
||||||
|
}
|
||||||
|
|
||||||
|
public void removeAssignees(Collection<GHUser> assignees) throws IOException {
|
||||||
|
List<String> names = toLogins(assignees);
|
||||||
|
root.retrieve().method("DELETE").with("assignees",names).inBody().to(getIssuesApiRoute()+"/assignees",this);
|
||||||
|
}
|
||||||
|
|
||||||
|
private List<String> toLogins(Collection<GHUser> assignees) {
|
||||||
|
List<String> names = new ArrayList<String>(assignees.size());
|
||||||
|
for (GHUser a : assignees) {
|
||||||
|
names.add(a.getLogin());
|
||||||
|
}
|
||||||
|
return names;
|
||||||
|
}
|
||||||
|
|
||||||
protected String getApiRoute() {
|
protected String getApiRoute() {
|
||||||
return getIssuesApiRoute();
|
return getIssuesApiRoute();
|
||||||
}
|
}
|
||||||
@@ -253,7 +291,11 @@ public class GHIssue extends GHObject implements Reactable{
|
|||||||
public GHUser getAssignee() {
|
public GHUser getAssignee() {
|
||||||
return assignee;
|
return assignee;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public List<GHUser> getAssignees() {
|
||||||
|
return Collections.unmodifiableList(Arrays.asList(assignees));
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* User who submitted the issue.
|
* User who submitted the issue.
|
||||||
*/
|
*/
|
||||||
|
|||||||
@@ -11,6 +11,7 @@ public class GHIssueBuilder {
|
|||||||
private final GHRepository repo;
|
private final GHRepository repo;
|
||||||
private final Requester builder;
|
private final Requester builder;
|
||||||
private List<String> labels = new ArrayList<String>();
|
private List<String> labels = new ArrayList<String>();
|
||||||
|
private List<String> assignees = new ArrayList<String>();
|
||||||
|
|
||||||
GHIssueBuilder(GHRepository repo, String title) {
|
GHIssueBuilder(GHRepository repo, String title) {
|
||||||
this.repo = repo;
|
this.repo = repo;
|
||||||
@@ -28,13 +29,13 @@ public class GHIssueBuilder {
|
|||||||
|
|
||||||
public GHIssueBuilder assignee(GHUser user) {
|
public GHIssueBuilder assignee(GHUser user) {
|
||||||
if (user!=null)
|
if (user!=null)
|
||||||
builder.with("assignee",user.getLogin());
|
assignees.add(user.getLogin());
|
||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
|
|
||||||
public GHIssueBuilder assignee(String user) {
|
public GHIssueBuilder assignee(String user) {
|
||||||
if (user!=null)
|
if (user!=null)
|
||||||
builder.with("assignee",user);
|
assignees.add(user);
|
||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -54,6 +55,6 @@ public class GHIssueBuilder {
|
|||||||
* Creates a new issue.
|
* Creates a new issue.
|
||||||
*/
|
*/
|
||||||
public GHIssue create() throws IOException {
|
public GHIssue create() throws IOException {
|
||||||
return builder.with("labels",labels).to(repo.getApiTailUrl("issues"),GHIssue.class).wrap(repo);
|
return builder.with("labels",labels).with("assignees",assignees).to(repo.getApiTailUrl("issues"),GHIssue.class).wrap(repo);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -41,6 +41,11 @@ public class GHIssueSearchBuilder extends GHSearchBuilder<GHIssue> {
|
|||||||
return q("is:merged");
|
return q("is:merged");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public GHIssueSearchBuilder order(GHDirection v) {
|
||||||
|
req.with("order",v);
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
public GHIssueSearchBuilder sort(Sort sort) {
|
public GHIssueSearchBuilder sort(Sort sort) {
|
||||||
req.with("sort",sort);
|
req.with("sort",sort);
|
||||||
return this;
|
return this;
|
||||||
|
|||||||
84
src/main/java/org/kohsuke/github/GHMembership.java
Normal file
84
src/main/java/org/kohsuke/github/GHMembership.java
Normal file
@@ -0,0 +1,84 @@
|
|||||||
|
package org.kohsuke.github;
|
||||||
|
|
||||||
|
import java.io.IOException;
|
||||||
|
import java.net.URL;
|
||||||
|
import java.util.Locale;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Represents a membership of a user in an organization.
|
||||||
|
*
|
||||||
|
* @author Kohsuke Kawaguchi
|
||||||
|
* @see GHMyself#listOrgMemberships()
|
||||||
|
*/
|
||||||
|
public class GHMembership /* extends GHObject --- but it doesn't have id, created_at, etc. */ {
|
||||||
|
GitHub root;
|
||||||
|
|
||||||
|
String url;
|
||||||
|
String state;
|
||||||
|
String role;
|
||||||
|
GHUser user;
|
||||||
|
GHOrganization organization;
|
||||||
|
|
||||||
|
public URL getUrl() {
|
||||||
|
return GitHub.parseURL(url);
|
||||||
|
}
|
||||||
|
|
||||||
|
public State getState() {
|
||||||
|
return Enum.valueOf(State.class, state.toUpperCase(Locale.ENGLISH));
|
||||||
|
}
|
||||||
|
|
||||||
|
public Role getRole() {
|
||||||
|
return Enum.valueOf(Role.class, role.toUpperCase(Locale.ENGLISH));
|
||||||
|
}
|
||||||
|
|
||||||
|
public GHUser getUser() {
|
||||||
|
return user;
|
||||||
|
}
|
||||||
|
|
||||||
|
public GHOrganization getOrganization() {
|
||||||
|
return organization;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Accepts a pending invitation to an organization.
|
||||||
|
*
|
||||||
|
* @see GHMyself#getMembership(GHOrganization)
|
||||||
|
*/
|
||||||
|
public void activate() throws IOException {
|
||||||
|
root.retrieve().method("PATCH").with("state",State.ACTIVE).to(url,this);
|
||||||
|
}
|
||||||
|
|
||||||
|
/*package*/ GHMembership wrap(GitHub root) {
|
||||||
|
this.root = root;
|
||||||
|
if (user!=null) user = root.getUser(user.wrapUp(root));
|
||||||
|
if (organization!=null) organization.wrapUp(root);
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*package*/ static void wrap(GHMembership[] page, GitHub root) {
|
||||||
|
for (GHMembership m : page)
|
||||||
|
m.wrap(root);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Role of a user in an organization.
|
||||||
|
*/
|
||||||
|
public enum Role {
|
||||||
|
/**
|
||||||
|
* Organization owner.
|
||||||
|
*/
|
||||||
|
ADMIN,
|
||||||
|
/**
|
||||||
|
* Non-owner organization member.
|
||||||
|
*/
|
||||||
|
MEMBER;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Whether a role is currently active or waiting for acceptance (pending)
|
||||||
|
*/
|
||||||
|
public enum State {
|
||||||
|
ACTIVE,
|
||||||
|
PENDING;
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -178,6 +178,39 @@ public class GHMyself extends GHUser {
|
|||||||
return listRepositories();
|
return listRepositories();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* List your organization memberships
|
||||||
|
*/
|
||||||
|
public PagedIterable<GHMembership> listOrgMemberships() {
|
||||||
|
return listOrgMemberships(null);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* List your organization memberships
|
||||||
|
*
|
||||||
|
* @param state
|
||||||
|
* Filter by a specific state
|
||||||
|
*/
|
||||||
|
public PagedIterable<GHMembership> listOrgMemberships(final GHMembership.State state) {
|
||||||
|
return new PagedIterable<GHMembership>() {
|
||||||
|
public PagedIterator<GHMembership> _iterator(int pageSize) {
|
||||||
|
return new PagedIterator<GHMembership>(root.retrieve().with("state",state).asIterator("/user/memberships/orgs", GHMembership[].class, pageSize)) {
|
||||||
|
@Override
|
||||||
|
protected void wrapUp(GHMembership[] page) {
|
||||||
|
GHMembership.wrap(page,root);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
}
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Gets your membership in a specific organization.
|
||||||
|
*/
|
||||||
|
public GHMembership getMembership(GHOrganization o) throws IOException {
|
||||||
|
return root.retrieve().to("/user/memberships/orgs/"+o.getLogin(),GHMembership.class).wrap(root);
|
||||||
|
}
|
||||||
|
|
||||||
// public void addEmails(Collection<String> emails) throws IOException {
|
// public void addEmails(Collection<String> emails) throws IOException {
|
||||||
//// new Requester(root,ApiVersion.V3).withCredential().to("/user/emails");
|
//// new Requester(root,ApiVersion.V3).withCredential().to("/user/emails");
|
||||||
// root.retrieveWithAuth3()
|
// root.retrieveWithAuth3()
|
||||||
|
|||||||
@@ -93,10 +93,10 @@ public abstract class GHPerson extends GHObject {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Loads repository list in a pagenated fashion.
|
* Loads repository list in a paginated fashion.
|
||||||
*
|
*
|
||||||
* <p>
|
* <p>
|
||||||
* For a person with a lot of repositories, GitHub returns the list of repositories in a pagenated fashion.
|
* For a person with a lot of repositories, GitHub returns the list of repositories in a paginated fashion.
|
||||||
* Unlike {@link #getRepositories()}, this method allows the caller to start processing data as it arrives.
|
* Unlike {@link #getRepositories()}, this method allows the caller to start processing data as it arrives.
|
||||||
*
|
*
|
||||||
* Every {@link Iterator#next()} call results in I/O. Exceptions that occur during the processing is wrapped
|
* Every {@link Iterator#next()} call results in I/O. Exceptions that occur during the processing is wrapped
|
||||||
|
|||||||
@@ -213,7 +213,7 @@ public class GHPullRequest extends GHIssue {
|
|||||||
public PagedIterable<GHPullRequestFileDetail> listFiles() {
|
public PagedIterable<GHPullRequestFileDetail> listFiles() {
|
||||||
return new PagedIterable<GHPullRequestFileDetail>() {
|
return new PagedIterable<GHPullRequestFileDetail>() {
|
||||||
public PagedIterator<GHPullRequestFileDetail> _iterator(int pageSize) {
|
public PagedIterator<GHPullRequestFileDetail> _iterator(int pageSize) {
|
||||||
return new PagedIterator<GHPullRequestFileDetail>(root.retrieve().asIterator(String.format("%s/files", getApiURL()),
|
return new PagedIterator<GHPullRequestFileDetail>(root.retrieve().asIterator(String.format("%s/files", getApiRoute()),
|
||||||
GHPullRequestFileDetail[].class, pageSize)) {
|
GHPullRequestFileDetail[].class, pageSize)) {
|
||||||
@Override
|
@Override
|
||||||
protected void wrapUp(GHPullRequestFileDetail[] page) {
|
protected void wrapUp(GHPullRequestFileDetail[] page) {
|
||||||
@@ -247,7 +247,7 @@ public class GHPullRequest extends GHIssue {
|
|||||||
return new PagedIterable<GHPullRequestCommitDetail>() {
|
return new PagedIterable<GHPullRequestCommitDetail>() {
|
||||||
public PagedIterator<GHPullRequestCommitDetail> _iterator(int pageSize) {
|
public PagedIterator<GHPullRequestCommitDetail> _iterator(int pageSize) {
|
||||||
return new PagedIterator<GHPullRequestCommitDetail>(root.retrieve().asIterator(
|
return new PagedIterator<GHPullRequestCommitDetail>(root.retrieve().asIterator(
|
||||||
String.format("%s/commits", getApiURL()),
|
String.format("%s/commits", getApiRoute()),
|
||||||
GHPullRequestCommitDetail[].class, pageSize)) {
|
GHPullRequestCommitDetail[].class, pageSize)) {
|
||||||
@Override
|
@Override
|
||||||
protected void wrapUp(GHPullRequestCommitDetail[] page) {
|
protected void wrapUp(GHPullRequestCommitDetail[] page) {
|
||||||
|
|||||||
@@ -31,6 +31,7 @@ import org.apache.commons.lang.StringUtils;
|
|||||||
|
|
||||||
import java.io.FileNotFoundException;
|
import java.io.FileNotFoundException;
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
|
import java.io.InputStream;
|
||||||
import java.io.InputStreamReader;
|
import java.io.InputStreamReader;
|
||||||
import java.io.InterruptedIOException;
|
import java.io.InterruptedIOException;
|
||||||
import java.io.Reader;
|
import java.io.Reader;
|
||||||
@@ -50,8 +51,8 @@ import java.util.Map;
|
|||||||
import java.util.Set;
|
import java.util.Set;
|
||||||
import java.util.TreeMap;
|
import java.util.TreeMap;
|
||||||
|
|
||||||
import static java.util.Arrays.asList;
|
import static java.util.Arrays.*;
|
||||||
import static org.kohsuke.github.Previews.DRAX;
|
import static org.kohsuke.github.Previews.*;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* A repository on GitHub.
|
* A repository on GitHub.
|
||||||
@@ -451,22 +452,22 @@ public class GHRepository extends GHObject {
|
|||||||
* @throws IOException
|
* @throws IOException
|
||||||
*/
|
*/
|
||||||
public PagedIterable<GHUser> listCollaborators() throws IOException {
|
public PagedIterable<GHUser> listCollaborators() throws IOException {
|
||||||
return new PagedIterable<GHUser>() {
|
return listUsers("collaborators");
|
||||||
public PagedIterator<GHUser> _iterator(int pageSize) {
|
}
|
||||||
|
|
||||||
return new PagedIterator<GHUser>(root.retrieve().asIterator(getApiTailUrl("collaborators"), GHUser[].class, pageSize)) {
|
/**
|
||||||
|
* Lists all <a href="https://help.github.com/articles/assigning-issues-and-pull-requests-to-other-github-users/">the available assignees</a>
|
||||||
@Override
|
* to which issues may be assigned.
|
||||||
protected void wrapUp(GHUser[] users) {
|
*/
|
||||||
for (GHUser user : users) {
|
public PagedIterable<GHUser> listAssignees() throws IOException {
|
||||||
user.wrapUp(root);
|
return listUsers("assignees");
|
||||||
}
|
}
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Checks if the given user is an assignee for this repository.
|
||||||
|
*/
|
||||||
|
public boolean hasAssignee(GHUser u) throws IOException {
|
||||||
|
return root.retrieve().asHttpStatusCode(getApiTailUrl("assignees/" + u.getLogin()))/100==2;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -504,7 +505,6 @@ public class GHRepository extends GHObject {
|
|||||||
}
|
}
|
||||||
|
|
||||||
private void modifyCollaborators(Collection<GHUser> users, String method) throws IOException {
|
private void modifyCollaborators(Collection<GHUser> users, String method) throws IOException {
|
||||||
verifyMine();
|
|
||||||
for (GHUser user : users) {
|
for (GHUser user : users) {
|
||||||
new Requester(root).method(method).to(getApiTailUrl("collaborators/" + user.getLogin()));
|
new Requester(root).method(method).to(getApiTailUrl("collaborators/" + user.getLogin()));
|
||||||
}
|
}
|
||||||
@@ -799,7 +799,7 @@ public class GHRepository extends GHObject {
|
|||||||
*/
|
*/
|
||||||
public GHTree getTree(String sha) throws IOException {
|
public GHTree getTree(String sha) throws IOException {
|
||||||
String url = String.format("/repos/%s/%s/git/trees/%s", getOwnerName(), name, sha);
|
String url = String.format("/repos/%s/%s/git/trees/%s", getOwnerName(), name, sha);
|
||||||
return root.retrieve().to(url, GHTree.class).wrap(root);
|
return root.retrieve().to(url, GHTree.class).wrap(this);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -814,7 +814,32 @@ public class GHRepository extends GHObject {
|
|||||||
*/
|
*/
|
||||||
public GHTree getTreeRecursive(String sha, int recursive) throws IOException {
|
public GHTree getTreeRecursive(String sha, int recursive) throws IOException {
|
||||||
String url = String.format("/repos/%s/%s/git/trees/%s?recursive=%d", getOwnerName(), name, sha, recursive);
|
String url = String.format("/repos/%s/%s/git/trees/%s?recursive=%d", getOwnerName(), name, sha, recursive);
|
||||||
return root.retrieve().to(url, GHTree.class).wrap(root);
|
return root.retrieve().to(url, GHTree.class).wrap(this);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Obtains the metadata & the content of a blob.
|
||||||
|
*
|
||||||
|
* <p>
|
||||||
|
* This method retrieves the whole content in memory, so beware when you are dealing with large BLOB.
|
||||||
|
*
|
||||||
|
* @see <a href="https://developer.github.com/v3/git/blobs/#get-a-blob">Get a blob</a>
|
||||||
|
* @see #readBlob(String)
|
||||||
|
*/
|
||||||
|
public GHBlob getBlob(String blobSha) throws IOException {
|
||||||
|
String target = getApiTailUrl("git/blobs/" + blobSha);
|
||||||
|
return root.retrieve().to(target, GHBlob.class);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Reads the content of a blob as a stream for better efficiency.
|
||||||
|
*
|
||||||
|
* @see <a href="https://developer.github.com/v3/git/blobs/#get-a-blob">Get a blob</a>
|
||||||
|
* @see #getBlob(String)
|
||||||
|
*/
|
||||||
|
public InputStream readBlob(String blobSha) throws IOException {
|
||||||
|
String target = getApiTailUrl("git/blobs/" + blobSha);
|
||||||
|
return root.retrieve().withHeader("Accept","application/vnd.github.VERSION.raw").asStream(target);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -1092,11 +1117,6 @@ public class GHRepository extends GHObject {
|
|||||||
// return root.retrieveWithAuth("/pulls/"+owner+'/'+name,JsonPullRequests.class).wrap(root);
|
// return root.retrieveWithAuth("/pulls/"+owner+'/'+name,JsonPullRequests.class).wrap(root);
|
||||||
// }
|
// }
|
||||||
|
|
||||||
private void verifyMine() throws IOException {
|
|
||||||
if (!root.login.equals(getOwnerName()))
|
|
||||||
throw new IOException("Operation not applicable to a repository owned by someone else: " + getOwnerName());
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Returns a set that represents the post-commit hook URLs.
|
* Returns a set that represents the post-commit hook URLs.
|
||||||
* The returned set is live, and changes made to them are reflected to GitHub.
|
* The returned set is live, and changes made to them are reflected to GitHub.
|
||||||
|
|||||||
@@ -57,6 +57,11 @@ public class GHRepositorySearchBuilder extends GHSearchBuilder<GHRepository> {
|
|||||||
return q("stars:"+v);
|
return q("stars:"+v);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public GHRepositorySearchBuilder order(GHDirection v) {
|
||||||
|
req.with("order",v);
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
public GHRepositorySearchBuilder sort(Sort sort) {
|
public GHRepositorySearchBuilder sort(Sort sort) {
|
||||||
req.with("sort",sort);
|
req.with("sort",sort);
|
||||||
return this;
|
return this;
|
||||||
|
|||||||
@@ -10,10 +10,12 @@ import java.util.List;
|
|||||||
* https://developer.github.com/v3/git/trees/
|
* https://developer.github.com/v3/git/trees/
|
||||||
*
|
*
|
||||||
* @author Daniel Teixeira - https://github.com/ddtxra
|
* @author Daniel Teixeira - https://github.com/ddtxra
|
||||||
|
* @see GHCommit#getTree()
|
||||||
* @see GHRepository#getTree(String)
|
* @see GHRepository#getTree(String)
|
||||||
|
* @see GHTreeEntry#asTree()
|
||||||
*/
|
*/
|
||||||
public class GHTree {
|
public class GHTree {
|
||||||
/* package almost final */GitHub root;
|
/* package almost final */GHRepository repo;
|
||||||
|
|
||||||
private boolean truncated;
|
private boolean truncated;
|
||||||
private String sha, url;
|
private String sha, url;
|
||||||
@@ -34,6 +36,19 @@ public class GHTree {
|
|||||||
return Collections.unmodifiableList(Arrays.asList(tree));
|
return Collections.unmodifiableList(Arrays.asList(tree));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Finds a tree entry by its name.
|
||||||
|
*
|
||||||
|
* IOW, find a directory entry by a file name.
|
||||||
|
*/
|
||||||
|
public GHTreeEntry getEntry(String path) {
|
||||||
|
for (GHTreeEntry e : tree) {
|
||||||
|
if (e.getPath().equals(path))
|
||||||
|
return e;
|
||||||
|
}
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Returns true if the number of items in the tree array exceeded the GitHub maximum limit.
|
* Returns true if the number of items in the tree array exceeded the GitHub maximum limit.
|
||||||
* @return true true if the number of items in the tree array exceeded the GitHub maximum limit otherwise false.
|
* @return true true if the number of items in the tree array exceeded the GitHub maximum limit otherwise false.
|
||||||
@@ -50,8 +65,11 @@ public class GHTree {
|
|||||||
return GitHub.parseURL(url);
|
return GitHub.parseURL(url);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* package */GHTree wrap(GitHub root) {
|
/* package */GHTree wrap(GHRepository repo) {
|
||||||
this.root = root;
|
this.repo = repo;
|
||||||
|
for (GHTreeEntry e : tree) {
|
||||||
|
e.tree = this;
|
||||||
|
}
|
||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -1,5 +1,7 @@
|
|||||||
package org.kohsuke.github;
|
package org.kohsuke.github;
|
||||||
|
|
||||||
|
import java.io.IOException;
|
||||||
|
import java.io.InputStream;
|
||||||
import java.net.URL;
|
import java.net.URL;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -10,6 +12,8 @@ import java.net.URL;
|
|||||||
* @see GHTree
|
* @see GHTree
|
||||||
*/
|
*/
|
||||||
public class GHTreeEntry {
|
public class GHTreeEntry {
|
||||||
|
/* package almost final */GHTree tree;
|
||||||
|
|
||||||
private String path, mode, type, sha, url;
|
private String path, mode, type, sha, url;
|
||||||
private long size;
|
private long size;
|
||||||
|
|
||||||
@@ -44,7 +48,7 @@ public class GHTreeEntry {
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* Gets the type such as:
|
* Gets the type such as:
|
||||||
* "blob"
|
* "blob", "tree", etc.
|
||||||
*
|
*
|
||||||
* @return The type
|
* @return The type
|
||||||
*/
|
*/
|
||||||
@@ -68,4 +72,37 @@ public class GHTreeEntry {
|
|||||||
public URL getUrl() {
|
public URL getUrl() {
|
||||||
return GitHub.parseURL(url);
|
return GitHub.parseURL(url);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* If this tree entry represents a file, then return its information.
|
||||||
|
* Otherwise null.
|
||||||
|
*/
|
||||||
|
public GHBlob asBlob() throws IOException {
|
||||||
|
if (type.equals("blob"))
|
||||||
|
return tree.repo.getBlob(sha);
|
||||||
|
else
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* If this tree entry represents a file, then return its content.
|
||||||
|
* Otherwise null.
|
||||||
|
*/
|
||||||
|
public InputStream readAsBlob() throws IOException {
|
||||||
|
if (type.equals("blob"))
|
||||||
|
return tree.repo.readBlob(sha);
|
||||||
|
else
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* If this tree entry represents a directory, then return it.
|
||||||
|
* Otherwise null.
|
||||||
|
*/
|
||||||
|
public GHTree asTree() throws IOException {
|
||||||
|
if (type.equals("tree"))
|
||||||
|
return tree.repo.getTree(sha);
|
||||||
|
else
|
||||||
|
return null;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -214,4 +214,9 @@ public class GHUser extends GHPerson {
|
|||||||
if (tail.length()>0 && !tail.startsWith("/")) tail='/'+tail;
|
if (tail.length()>0 && !tail.startsWith("/")) tail='/'+tail;
|
||||||
return "/users/" + login + tail;
|
return "/users/" + login + tail;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*package*/ GHUser wrapUp(GitHub root) {
|
||||||
|
super.wrapUp(root);
|
||||||
|
return this;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -49,6 +49,11 @@ public class GHUserSearchBuilder extends GHSearchBuilder<GHUser> {
|
|||||||
return q("followers:"+v);
|
return q("followers:"+v);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public GHUserSearchBuilder order(GHDirection v) {
|
||||||
|
req.with("order",v);
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
public GHUserSearchBuilder sort(Sort sort) {
|
public GHUserSearchBuilder sort(Sort sort) {
|
||||||
req.with("sort",sort);
|
req.with("sort",sort);
|
||||||
return this;
|
return this;
|
||||||
|
|||||||
@@ -340,7 +340,7 @@ public class GitHub {
|
|||||||
/**
|
/**
|
||||||
* Interns the given {@link GHUser}.
|
* Interns the given {@link GHUser}.
|
||||||
*/
|
*/
|
||||||
protected GHUser getUser(GHUser orig) throws IOException {
|
protected GHUser getUser(GHUser orig) {
|
||||||
GHUser u = users.get(orig.getLogin());
|
GHUser u = users.get(orig.getLogin());
|
||||||
if (u==null) {
|
if (u==null) {
|
||||||
orig.root = this;
|
orig.root = this;
|
||||||
|
|||||||
@@ -6,7 +6,7 @@ import java.util.List;
|
|||||||
import java.util.NoSuchElementException;
|
import java.util.NoSuchElementException;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Iterator over a pagenated data source.
|
* Iterator over a paginated data source.
|
||||||
*
|
*
|
||||||
* Aside from the normal iterator operation, this method exposes {@link #nextPage()}
|
* Aside from the normal iterator operation, this method exposes {@link #nextPage()}
|
||||||
* that allows the caller to retrieve items per page.
|
* that allows the caller to retrieve items per page.
|
||||||
|
|||||||
@@ -81,6 +81,7 @@ class Requester {
|
|||||||
* Current connection.
|
* Current connection.
|
||||||
*/
|
*/
|
||||||
private HttpURLConnection uc;
|
private HttpURLConnection uc;
|
||||||
|
private boolean forceBody;
|
||||||
|
|
||||||
private static class Entry {
|
private static class Entry {
|
||||||
String key;
|
String key;
|
||||||
@@ -197,6 +198,16 @@ class Requester {
|
|||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Small number of GitHub APIs use HTTP methods somewhat inconsistently, and use a body where it's not expected.
|
||||||
|
* Normally whether parameters go as query parameters or a body depends on the HTTP verb in use,
|
||||||
|
* but this method forces the parameters to be sent as a body.
|
||||||
|
*/
|
||||||
|
/*package*/ Requester inBody() {
|
||||||
|
forceBody = true;
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
public void to(String tailApiUrl) throws IOException {
|
public void to(String tailApiUrl) throws IOException {
|
||||||
to(tailApiUrl,null);
|
to(tailApiUrl,null);
|
||||||
}
|
}
|
||||||
@@ -230,7 +241,7 @@ class Requester {
|
|||||||
|
|
||||||
@SuppressFBWarnings("SBSC_USE_STRINGBUFFER_CONCATENATION")
|
@SuppressFBWarnings("SBSC_USE_STRINGBUFFER_CONCATENATION")
|
||||||
private <T> T _to(String tailApiUrl, Class<T> type, T instance) throws IOException {
|
private <T> T _to(String tailApiUrl, Class<T> type, T instance) throws IOException {
|
||||||
if (METHODS_WITHOUT_BODY.contains(method) && !args.isEmpty()) {
|
if (!isMethodWithBody() && !args.isEmpty()) {
|
||||||
boolean questionMarkFound = tailApiUrl.indexOf('?') != -1;
|
boolean questionMarkFound = tailApiUrl.indexOf('?') != -1;
|
||||||
tailApiUrl += questionMarkFound ? '&' : '?';
|
tailApiUrl += questionMarkFound ? '&' : '?';
|
||||||
for (Iterator<Entry> it = args.listIterator(); it.hasNext();) {
|
for (Iterator<Entry> it = args.listIterator(); it.hasNext();) {
|
||||||
@@ -340,11 +351,11 @@ class Requester {
|
|||||||
}
|
}
|
||||||
|
|
||||||
private boolean isMethodWithBody() {
|
private boolean isMethodWithBody() {
|
||||||
return !METHODS_WITHOUT_BODY.contains(method);
|
return forceBody || !METHODS_WITHOUT_BODY.contains(method);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Loads pagenated resources.
|
* Loads paginated resources.
|
||||||
*
|
*
|
||||||
* Every iterator call reports a new batch.
|
* Every iterator call reports a new batch.
|
||||||
*/
|
*/
|
||||||
|
|||||||
@@ -12,6 +12,7 @@ import org.kohsuke.github.GHCommit.File;
|
|||||||
import org.kohsuke.github.GHOrganization.Permission;
|
import org.kohsuke.github.GHOrganization.Permission;
|
||||||
|
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
|
import java.io.InputStream;
|
||||||
import java.net.URL;
|
import java.net.URL;
|
||||||
import java.util.*;
|
import java.util.*;
|
||||||
import java.util.Map.Entry;
|
import java.util.Map.Entry;
|
||||||
@@ -362,6 +363,11 @@ public class AppTest extends AbstractGitHubApiTestBase {
|
|||||||
assertEquals(48,f.getLinesChanged());
|
assertEquals(48,f.getLinesChanged());
|
||||||
assertEquals("modified",f.getStatus());
|
assertEquals("modified",f.getStatus());
|
||||||
assertEquals("changelog.html", f.getFileName());
|
assertEquals("changelog.html", f.getFileName());
|
||||||
|
|
||||||
|
// walk the tree
|
||||||
|
GHTree t = commit.getTree();
|
||||||
|
assertThat(IOUtils.toString(t.getEntry("todo.txt").readAsBlob()), containsString("executor rendering"));
|
||||||
|
assertNotNull(t.getEntry("war").asTree());
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
@@ -888,6 +894,41 @@ public class AppTest extends AbstractGitHubApiTestBase {
|
|||||||
a.delete();
|
a.delete();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void listOrgMemberships() throws Exception {
|
||||||
|
GHMyself me = gitHub.getMyself();
|
||||||
|
for (GHMembership m : me.listOrgMemberships()) {
|
||||||
|
assertThat(m.getUser(), is((GHUser)me));
|
||||||
|
assertNotNull(m.getState());
|
||||||
|
assertNotNull(m.getRole());
|
||||||
|
|
||||||
|
System.out.printf("%s %s %s\n",
|
||||||
|
m.getOrganization().getLogin(),
|
||||||
|
m.getState(),
|
||||||
|
m.getRole());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void blob() throws Exception {
|
||||||
|
GHRepository r = gitHub.getRepository("kohsuke/github-api");
|
||||||
|
String sha1 = "a12243f2fc5b8c2ba47dd677d0b0c7583539584d";
|
||||||
|
|
||||||
|
assertBlobContent(r.readBlob(sha1));
|
||||||
|
|
||||||
|
GHBlob blob = r.getBlob(sha1);
|
||||||
|
assertBlobContent(blob.read());
|
||||||
|
assertThat(blob.getSha(),is("a12243f2fc5b8c2ba47dd677d0b0c7583539584d"));
|
||||||
|
assertThat(blob.getSize(),is(1104L));
|
||||||
|
}
|
||||||
|
|
||||||
|
private void assertBlobContent(InputStream is) throws Exception {
|
||||||
|
String content = new String(IOUtils.toByteArray(is),"UTF-8");
|
||||||
|
assertThat(content,containsString("Copyright (c) 2011- Kohsuke Kawaguchi and other contributors"));
|
||||||
|
assertThat(content,containsString("FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR"));
|
||||||
|
assertThat(content.length(),is(1104));
|
||||||
|
}
|
||||||
|
|
||||||
private void kohsuke() {
|
private void kohsuke() {
|
||||||
String login = getUser().getLogin();
|
String login = getUser().getLogin();
|
||||||
Assume.assumeTrue(login.equals("kohsuke") || login.equals("kohsuke2"));
|
Assume.assumeTrue(login.equals("kohsuke") || login.equals("kohsuke2"));
|
||||||
|
|||||||
@@ -65,8 +65,7 @@
|
|||||||
"issues_url": "https://api.github.com/repos/baxterandthehackers/public-repo/issues{/number}",
|
"issues_url": "https://api.github.com/repos/baxterandthehackers/public-repo/issues{/number}",
|
||||||
"pulls_url": "https://api.github.com/repos/baxterandthehackers/public-repo/pulls{/number}",
|
"pulls_url": "https://api.github.com/repos/baxterandthehackers/public-repo/pulls{/number}",
|
||||||
"milestones_url": "https://api.github.com/repos/baxterandthehackers/public-repo/milestones{/number}",
|
"milestones_url": "https://api.github.com/repos/baxterandthehackers/public-repo/milestones{/number}",
|
||||||
"notifications_url": "https://api.github.com/repos/baxterandthehackers/public-repo/notifications{?since,all,
|
"notifications_url": "https://api.github.com/repos/baxterandthehackers/public-repo/notifications{?since,all,participating}",
|
||||||
participating}",
|
|
||||||
"labels_url": "https://api.github.com/repos/baxterandthehackers/public-repo/labels{/name}",
|
"labels_url": "https://api.github.com/repos/baxterandthehackers/public-repo/labels{/name}",
|
||||||
"releases_url": "https://api.github.com/repos/baxterandthehackers/public-repo/releases{/id}",
|
"releases_url": "https://api.github.com/repos/baxterandthehackers/public-repo/releases{/id}",
|
||||||
"deployments_url": "https://api.github.com/repos/baxterandthehackers/public-repo/deployments",
|
"deployments_url": "https://api.github.com/repos/baxterandthehackers/public-repo/deployments",
|
||||||
|
|||||||
@@ -2,8 +2,7 @@
|
|||||||
"action": "created",
|
"action": "created",
|
||||||
"milestone": {
|
"milestone": {
|
||||||
"url": "https://api.github.com/repos/baxterandthehackers/public-repo/milestones/3",
|
"url": "https://api.github.com/repos/baxterandthehackers/public-repo/milestones/3",
|
||||||
"html_url": "https://github.com/baxterandthehackers/public-repo/milestones/Test%20milestone%20creation%20webhook
|
"html_url": "https://github.com/baxterandthehackers/public-repo/milestones/Test%20milestone%20creation%20webhook%20from%20command%20line2",
|
||||||
%20from%20command%20line2",
|
|
||||||
"labels_url": "https://api.github.com/repos/baxterandthehackers/public-repo/milestones/3/labels",
|
"labels_url": "https://api.github.com/repos/baxterandthehackers/public-repo/milestones/3/labels",
|
||||||
"id": 2055681,
|
"id": 2055681,
|
||||||
"number": 3,
|
"number": 3,
|
||||||
@@ -96,8 +95,7 @@
|
|||||||
"issues_url": "https://api.github.com/repos/baxterandthehackers/public-repo/issues{/number}",
|
"issues_url": "https://api.github.com/repos/baxterandthehackers/public-repo/issues{/number}",
|
||||||
"pulls_url": "https://api.github.com/repos/baxterandthehackers/public-repo/pulls{/number}",
|
"pulls_url": "https://api.github.com/repos/baxterandthehackers/public-repo/pulls{/number}",
|
||||||
"milestones_url": "https://api.github.com/repos/baxterandthehackers/public-repo/milestones{/number}",
|
"milestones_url": "https://api.github.com/repos/baxterandthehackers/public-repo/milestones{/number}",
|
||||||
"notifications_url": "https://api.github.com/repos/baxterandthehackers/public-repo/notifications{?since,all,
|
"notifications_url": "https://api.github.com/repos/baxterandthehackers/public-repo/notifications{?since,all,participating}",
|
||||||
participating}",
|
|
||||||
"labels_url": "https://api.github.com/repos/baxterandthehackers/public-repo/labels{/name}",
|
"labels_url": "https://api.github.com/repos/baxterandthehackers/public-repo/labels{/name}",
|
||||||
"releases_url": "https://api.github.com/repos/baxterandthehackers/public-repo/releases{/id}",
|
"releases_url": "https://api.github.com/repos/baxterandthehackers/public-repo/releases{/id}",
|
||||||
"deployments_url": "https://api.github.com/repos/baxterandthehackers/public-repo/deployments",
|
"deployments_url": "https://api.github.com/repos/baxterandthehackers/public-repo/deployments",
|
||||||
|
|||||||
Reference in New Issue
Block a user