Skip to content

Commit ac470dd

Browse files
authored
Merge branch 'master' into add-create-repo-with-template-support
2 parents b194a19 + 2b2be05 commit ac470dd

File tree

6 files changed

+164
-13
lines changed

6 files changed

+164
-13
lines changed

src/main/java/org/kohsuke/github/GHRepository.java

Lines changed: 23 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -46,6 +46,7 @@
4646
import java.util.HashMap;
4747
import java.util.HashSet;
4848
import java.util.Iterator;
49+
import java.util.LinkedHashSet;
4950
import java.util.List;
5051
import java.util.Map;
5152
import java.util.Objects;
@@ -68,7 +69,9 @@ public class GHRepository extends GHObject {
6869
/* package almost final */ transient GitHub root;
6970

7071
private String nodeId, description, homepage, name, full_name;
72+
7173
private String html_url; // this is the UI
74+
7275
/*
7376
* The license information makes use of the preview API.
7477
*
@@ -77,22 +80,30 @@ public class GHRepository extends GHObject {
7780
private GHLicense license;
7881

7982
private String git_url, ssh_url, clone_url, svn_url, mirror_url;
83+
8084
private GHUser owner; // not fully populated. beware.
85+
8186
private boolean has_issues, has_wiki, fork, has_downloads, has_pages, archived, has_projects;
8287

8388
private boolean allow_squash_merge;
89+
8490
private boolean allow_merge_commit;
91+
8592
private boolean allow_rebase_merge;
8693

8794
private boolean delete_branch_on_merge;
8895

8996
@JsonProperty("private")
9097
private boolean _private;
98+
9199
private int forks_count, stargazers_count, watchers_count, size, open_issues_count, subscribers_count;
100+
92101
private String pushed_at;
102+
93103
private Map<Integer, GHMilestone> milestones = new WeakHashMap<Integer, GHMilestone>();
94104

95105
private String default_branch, language;
106+
96107
private Map<String, GHCommit> commits = new WeakHashMap<String, GHCommit>();
97108

98109
@SkipFromToString
@@ -970,12 +981,12 @@ private void modifyCollaborators(@NonNull Collection<GHUser> users,
970981
@NonNull String method,
971982
@CheckForNull GHOrganization.Permission permission) throws IOException {
972983
Requester requester = root.createRequest().method(method);
973-
974984
if (permission != null) {
975985
requester = requester.with("permission", permission).inBody();
976986
}
977987

978-
for (GHUser user : users) {
988+
// Make sure that the users collection doesn't have any duplicates
989+
for (GHUser user : new LinkedHashSet<GHUser>(users)) {
979990
requester.withUrlPath(getApiTailUrl("collaborators/" + user.getLogin())).send();
980991
}
981992
}
@@ -1002,8 +1013,9 @@ public void setEmailServiceHook(String address) throws IOException {
10021013

10031014
private void edit(String key, String value) throws IOException {
10041015
Requester requester = root.createRequest();
1005-
if (!key.equals("name"))
1016+
if (!key.equals("name")) {
10061017
requester.with("name", name); // even when we don't change the name, we need to send it in
1018+
}
10071019
requester.with(key, value).method("PATCH").withUrlPath(getApiTailUrl("")).send();
10081020
}
10091021

@@ -1248,8 +1260,9 @@ public GHRepository fork() throws IOException {
12481260
// this API is asynchronous. we need to wait for a bit
12491261
for (int i = 0; i < 10; i++) {
12501262
GHRepository r = root.getMyself().getRepository(name);
1251-
if (r != null)
1263+
if (r != null) {
12521264
return r;
1265+
}
12531266
try {
12541267
Thread.sleep(3000);
12551268
} catch (InterruptedException e) {
@@ -1278,8 +1291,9 @@ public GHRepository forkTo(GHOrganization org) throws IOException {
12781291
// this API is asynchronous. we need to wait for a bit
12791292
for (int i = 0; i < 10; i++) {
12801293
GHRepository r = org.getRepository(name);
1281-
if (r != null)
1294+
if (r != null) {
12821295
return r;
1296+
}
12831297
try {
12841298
Thread.sleep(3000);
12851299
} catch (InterruptedException e) {
@@ -2721,8 +2735,9 @@ public boolean equals(Object obj) {
27212735
}
27222736

27232737
String getApiTailUrl(String tail) {
2724-
if (tail.length() > 0 && !tail.startsWith("/"))
2738+
if (tail.length() > 0 && !tail.startsWith("/")) {
27252739
tail = '/' + tail;
2740+
}
27262741
return "/repos/" + getOwnerName() + "/" + name + tail;
27272742
}
27282743

@@ -2829,8 +2844,9 @@ public GHTagObject createTag(String tag, String message, String object, String t
28292844
* The IO exception
28302845
*/
28312846
void populate() throws IOException {
2832-
if (root.isOffline())
2847+
if (root.isOffline()) {
28332848
return; // can't populate if the root is offline
2849+
}
28342850

28352851
final URL url = Objects.requireNonNull(getUrl(), "Missing instance URL!");
28362852

src/main/java/org/kohsuke/github/GitHubRequest.java

Lines changed: 2 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -671,13 +671,9 @@ public B withUrlPath(@Nonnull String urlPath, @Nonnull String... urlPathItems) {
671671
tailUrlPath += "/" + String.join("/", urlPathItems);
672672
}
673673

674-
if (this.urlPath.endsWith("/")) {
675-
tailUrlPath = StringUtils.stripStart(tailUrlPath, "/");
676-
} else {
677-
tailUrlPath = StringUtils.prependIfMissing(tailUrlPath, "/");
678-
}
674+
tailUrlPath = StringUtils.prependIfMissing(tailUrlPath, "/");
679675

680-
this.urlPath += urlPathEncode(tailUrlPath);
676+
this.urlPath = urlPathEncode(tailUrlPath);
681677
return (B) this;
682678
}
683679

src/test/java/org/kohsuke/github/GHRepositoryTest.java

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -191,6 +191,7 @@ public void addCollaborators() throws Exception {
191191
List<GHUser> users = new ArrayList<GHUser>();
192192

193193
users.add(user);
194+
users.add(gitHub.getUser("jimmysombrero2"));
194195
repo.addCollaborators(users, GHOrganization.Permission.PUSH);
195196

196197
GHPersonSet<GHUser> collabs = repo.getCollaborators();
Lines changed: 45 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,45 @@
1+
{
2+
"login": "jimmysombrero2",
3+
"id": 12157727,
4+
"node_id": "MDQ6VXNlcjEyMTU3NzI3",
5+
"avatar_url": "https://avatars3.githubusercontent.com/u/12157727?v=4",
6+
"gravatar_id": "",
7+
"url": "https://api.github.com/users/jimmysombrero",
8+
"html_url": "https://github.com/jimmysombrero",
9+
"followers_url": "https://api.github.com/users/jimmysombrero/followers",
10+
"following_url": "https://api.github.com/users/jimmysombrero/following{/other_user}",
11+
"gists_url": "https://api.github.com/users/jimmysombrero/gists{/gist_id}",
12+
"starred_url": "https://api.github.com/users/jimmysombrero/starred{/owner}{/repo}",
13+
"subscriptions_url": "https://api.github.com/users/jimmysombrero/subscriptions",
14+
"organizations_url": "https://api.github.com/users/jimmysombrero/orgs",
15+
"repos_url": "https://api.github.com/users/jimmysombrero/repos",
16+
"events_url": "https://api.github.com/users/jimmysombrero/events{/privacy}",
17+
"received_events_url": "https://api.github.com/users/jimmysombrero/received_events",
18+
"type": "User",
19+
"site_admin": false,
20+
"name": null,
21+
"company": null,
22+
"blog": "",
23+
"location": null,
24+
"email": null,
25+
"hireable": null,
26+
"bio": null,
27+
"public_repos": 4,
28+
"public_gists": 0,
29+
"followers": 1,
30+
"following": 0,
31+
"created_at": "2015-04-28T17:47:19Z",
32+
"updated_at": "2020-02-02T04:43:58Z",
33+
"private_gists": 0,
34+
"total_private_repos": 0,
35+
"owned_private_repos": 0,
36+
"disk_usage": 19,
37+
"collaborators": 0,
38+
"two_factor_authentication": false,
39+
"plan": {
40+
"name": "free",
41+
"space": 976562499,
42+
"collaborators": 0,
43+
"private_repos": 10000
44+
}
45+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,48 @@
1+
{
2+
"id": "3d80b19e-05f4-4ad9-a610-5f573abc4363",
3+
"name": "repos_hub4j-test-org_github-api_collaborators_jimmysombrero2",
4+
"request": {
5+
"url": "/repos/hub4j-test-org/github-api/collaborators/jimmysombrero2",
6+
"method": "PUT",
7+
"headers": {
8+
"Accept": {
9+
"equalTo": "text/html, image/gif, image/jpeg, *; q=.2, */*; q=.2"
10+
}
11+
},
12+
"bodyPatterns": [
13+
{
14+
"equalToJson": "{\"permission\":\"push\"}",
15+
"ignoreArrayOrder": true,
16+
"ignoreExtraElements": true
17+
}
18+
]
19+
},
20+
"response": {
21+
"status": 201,
22+
"body": "[]",
23+
"headers": {
24+
"Server": "GitHub.com",
25+
"Date": "Sun, 02 Feb 2020 04:59:39 GMT",
26+
"Content-Type": "application/json; charset=utf-8",
27+
"Status": "201 Created",
28+
"X-RateLimit-Limit": "5000",
29+
"X-RateLimit-Remaining": "4892",
30+
"X-RateLimit-Reset": "1580620983",
31+
"X-OAuth-Scopes": "admin:enterprise, admin:gpg_key, admin:org, admin:org_hook, admin:public_key, admin:repo_hook, delete:packages, delete_repo, gist, notifications, read:packages, repo, user, workflow, write:discussion, write:packages",
32+
"X-Accepted-OAuth-Scopes": "",
33+
"X-GitHub-Media-Type": "unknown, github.v3",
34+
"Access-Control-Expose-Headers": "ETag, Link, Location, Retry-After, X-GitHub-OTP, X-RateLimit-Limit, X-RateLimit-Remaining, X-RateLimit-Reset, X-OAuth-Scopes, X-Accepted-OAuth-Scopes, X-Poll-Interval, X-GitHub-Media-Type",
35+
"Access-Control-Allow-Origin": "*",
36+
"Strict-Transport-Security": "max-age=31536000; includeSubdomains; preload",
37+
"X-Frame-Options": "deny",
38+
"X-Content-Type-Options": "nosniff",
39+
"X-XSS-Protection": "1; mode=block",
40+
"Referrer-Policy": "origin-when-cross-origin, strict-origin-when-cross-origin",
41+
"Content-Security-Policy": "default-src 'none'",
42+
"X-GitHub-Request-Id": "C903:768E:16C4966:2BA11B0:5E36573B"
43+
}
44+
},
45+
"uuid": "3d80b19e-05f4-4ad9-a610-5f573abc4363",
46+
"persistent": true,
47+
"insertionIndex": 4
48+
}
Lines changed: 45 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,45 @@
1+
{
2+
"id": "6685376c-451b-486d-88cd-502af9a7c5d2",
3+
"name": "users_jimmysombrero2",
4+
"request": {
5+
"url": "/users/jimmysombrero2",
6+
"method": "GET",
7+
"headers": {
8+
"Accept": {
9+
"equalTo": "text/html, image/gif, image/jpeg, *; q=.2, */*; q=.2"
10+
}
11+
}
12+
},
13+
"response": {
14+
"status": 200,
15+
"bodyFileName": "users_jimmysombrero2.json",
16+
"headers": {
17+
"Server": "GitHub.com",
18+
"Date": "Mon, 03 Feb 2020 03:50:14 GMT",
19+
"Content-Type": "application/json; charset=utf-8",
20+
"Status": "200 OK",
21+
"X-RateLimit-Limit": "5000",
22+
"X-RateLimit-Remaining": "4907",
23+
"X-RateLimit-Reset": "1580704799",
24+
"Cache-Control": "private, max-age=60, s-maxage=60",
25+
"Vary": "Accept, Authorization, Cookie, X-GitHub-OTP",
26+
"ETag": "W/\"7a0206b47e995649c88218afeb2266a6\"",
27+
"Last-Modified": "Sun, 02 Feb 2020 04:43:58 GMT",
28+
"X-OAuth-Scopes": "admin:enterprise, admin:gpg_key, admin:org, admin:org_hook, admin:public_key, admin:repo_hook, delete:packages, delete_repo, gist, notifications, read:packages, repo, user, workflow, write:discussion, write:packages",
29+
"X-Accepted-OAuth-Scopes": "",
30+
"X-GitHub-Media-Type": "unknown, github.v3",
31+
"Access-Control-Expose-Headers": "ETag, Link, Location, Retry-After, X-GitHub-OTP, X-RateLimit-Limit, X-RateLimit-Remaining, X-RateLimit-Reset, X-OAuth-Scopes, X-Accepted-OAuth-Scopes, X-Poll-Interval, X-GitHub-Media-Type",
32+
"Access-Control-Allow-Origin": "*",
33+
"Strict-Transport-Security": "max-age=31536000; includeSubdomains; preload",
34+
"X-Frame-Options": "deny",
35+
"X-Content-Type-Options": "nosniff",
36+
"X-XSS-Protection": "1; mode=block",
37+
"Referrer-Policy": "origin-when-cross-origin, strict-origin-when-cross-origin",
38+
"Content-Security-Policy": "default-src 'none'",
39+
"X-GitHub-Request-Id": "CDFE:768D:1021273:26DC788:5E379876"
40+
}
41+
},
42+
"uuid": "6685376c-451b-486d-88cd-502af9a7c5d1",
43+
"persistent": true,
44+
"insertionIndex": 6
45+
}

0 commit comments

Comments
 (0)