Skip to content

Commit 43175a4

Browse files
authored
Exclude archived repositories (#752)
Bitbucket server 8.0 introduced the ability to archive repositories. An archived repository makes it read-only as well as other restrictions. https://confluence.atlassian.com/bitbucketserver/archive-a-repository-1128304317.html This change filters out archived repositories from the returned repositories list. Fixes #703
1 parent 5a2e0c1 commit 43175a4

File tree

7 files changed

+240
-0
lines changed

7 files changed

+240
-0
lines changed

src/main/java/com/cloudbees/jenkins/plugins/bitbucket/api/BitbucketRepository.java

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -69,6 +69,13 @@ public interface BitbucketRepository {
6969
*/
7070
boolean isPrivate();
7171

72+
/**
73+
* Is the repository marked as archived. Bitbucket 8.0 introduced the ability to "Archive" a repository which
74+
* makes the repository read-only and distinguishable from "Active" repositories.
75+
* @return true if the repository is marked as archived, false otherwise
76+
*/
77+
boolean isArchived();
78+
7279
/**
7380
* Gets the links for this repository.
7481
* @return the links for this repository.

src/main/java/com/cloudbees/jenkins/plugins/bitbucket/client/repository/BitbucketCloudRepository.java

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -123,6 +123,11 @@ public boolean isPrivate() {
123123
return priv;
124124
}
125125

126+
@Override
127+
public boolean isArchived() {
128+
return false;
129+
}
130+
126131
@JsonProperty("is_private")
127132
public void setPrivate(Boolean priv) {
128133
this.priv = priv;

src/main/java/com/cloudbees/jenkins/plugins/bitbucket/server/client/BitbucketServerAPIClient.java

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -853,6 +853,7 @@ public List<BitbucketServerRepository> getRepositories(@CheckForNull UserRoleInR
853853
} catch (FileNotFoundException e) {
854854
return new ArrayList<>();
855855
}
856+
repositories.removeIf(BitbucketServerRepository::isArchived);
856857
repositories.sort(Comparator.comparing(BitbucketServerRepository::getRepositoryName));
857858

858859
return repositories;

src/main/java/com/cloudbees/jenkins/plugins/bitbucket/server/client/repository/BitbucketServerRepository.java

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -51,6 +51,8 @@ public class BitbucketServerRepository implements BitbucketRepository {
5151
// JSON mapping added in setter because the field can not be called "public"
5252
private Boolean public_;
5353

54+
private Boolean archived;
55+
5456
@JsonProperty
5557
@JsonDeserialize(keyAs = String.class, contentUsing = BitbucketHref.Deserializer.class)
5658
private Map<String, List<BitbucketHref>> links;
@@ -101,6 +103,16 @@ public boolean isPrivate() {
101103
return !public_;
102104
}
103105

106+
@Override
107+
public boolean isArchived() {
108+
return archived != null && archived;
109+
}
110+
111+
@JsonProperty("archived")
112+
public void setArchived(Boolean archived) {
113+
this.archived = archived;
114+
}
115+
104116
@JsonProperty("public")
105117
public void setPublic(Boolean public_) {
106118
this.public_ = public_;

src/test/java/com/cloudbees/jenkins/plugins/bitbucket/server/client/BitbucketServerAPIClientTest.java

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,14 @@
11
package com.cloudbees.jenkins.plugins.bitbucket.server.client;
22

33
import com.cloudbees.jenkins.plugins.bitbucket.api.BitbucketApi;
4+
import com.cloudbees.jenkins.plugins.bitbucket.api.BitbucketRepository;
45
import com.cloudbees.jenkins.plugins.bitbucket.client.BitbucketIntegrationClientFactory;
56
import com.cloudbees.jenkins.plugins.bitbucket.client.BitbucketIntegrationClientFactory.BitbucketServerIntegrationClient;
67
import com.damnhandy.uri.template.UriTemplate;
78
import com.damnhandy.uri.template.impl.Operator;
9+
import java.util.List;
810
import java.util.logging.Level;
11+
import java.util.stream.Collectors;
912
import org.junit.Assert;
1013
import org.junit.Rule;
1114
import org.junit.Test;
@@ -18,6 +21,8 @@
1821
import static org.hamcrest.Matchers.containsString;
1922
import static org.hamcrest.Matchers.equalTo;
2023
import static org.hamcrest.Matchers.hasItem;
24+
import static org.hamcrest.Matchers.is;
25+
import static org.hamcrest.Matchers.not;
2126

2227
public class BitbucketServerAPIClientTest {
2328

@@ -60,4 +65,21 @@ public void retryWhenRateLimited() throws Exception {
6065
assertThat(logger.getMessages(), hasItem(containsString("Bitbucket server API rate limit reached")));
6166
}
6267

68+
@Test
69+
public void filterArchivedRepositories() throws Exception {
70+
BitbucketApi client = BitbucketIntegrationClientFactory.getClient("localhost", "foo", "test-repos");;
71+
List<? extends BitbucketRepository> repos = client.getRepositories();
72+
List<String> names = repos.stream().map(BitbucketRepository::getRepositoryName).collect(Collectors.toList());
73+
assertThat(names, not(hasItem("bar-archived")));
74+
assertThat(names, is(List.of("bar-active")));
75+
}
76+
77+
@Test
78+
public void sortRepositoriesByName() throws Exception {
79+
BitbucketApi client = BitbucketIntegrationClientFactory.getClient("localhost", "amuniz", "test-repos");;
80+
List<? extends BitbucketRepository> repos = client.getRepositories();
81+
List<String> names = repos.stream().map(BitbucketRepository::getRepositoryName).collect(Collectors.toList());
82+
assertThat(names, is(List.of("another-repo", "dogs-repo", "test-repos")));
83+
}
84+
6385
}
Lines changed: 113 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,113 @@
1+
{
2+
"size": 1,
3+
"limit": 200,
4+
"isLastPage": true,
5+
"values": [
6+
{
7+
"slug": "test-repos",
8+
"id": 1,
9+
"name": "test-repos",
10+
"scmId": "git",
11+
"state": "AVAILABLE",
12+
"statusMessage": "Available",
13+
"forkable": false,
14+
"project": {
15+
"key": "AMUNIZ",
16+
"id": 1,
17+
"name": "prj",
18+
"description": "This is a test repo",
19+
"public": true,
20+
"type": "NORMAL",
21+
"links": {
22+
"self": [{
23+
"href": "http://localhost:7990/projects/AMUNIZ"
24+
}]
25+
}
26+
},
27+
"public": false,
28+
"links": {
29+
"clone": [{
30+
"href": "ssh://git@localhost:7999/amuniz/test-repos.git",
31+
"name": "ssh"
32+
}, {
33+
"href": "http://localhost:7990/scm/amuniz/test-repos.git",
34+
"name": "http"
35+
}],
36+
"self": [{
37+
"href": "http://localhost:7990/projects/AMUNIZ/repos/test-repos/browse"
38+
}]
39+
}
40+
},
41+
{
42+
"slug": "another-repo",
43+
"id": 2,
44+
"name": "another-repo",
45+
"scmId": "git",
46+
"state": "AVAILABLE",
47+
"statusMessage": "Available",
48+
"forkable": false,
49+
"project": {
50+
"key": "AMUNIZ",
51+
"id": 1,
52+
"name": "prj",
53+
"description": "This is a test repo",
54+
"public": true,
55+
"type": "NORMAL",
56+
"links": {
57+
"self": [{
58+
"href": "http://localhost:7990/projects/AMUNIZ"
59+
}]
60+
}
61+
},
62+
"public": false,
63+
"links": {
64+
"clone": [{
65+
"href": "ssh://git@localhost:7999/amuniz/another-repo.git",
66+
"name": "ssh"
67+
}, {
68+
"href": "http://localhost:7990/scm/amuniz/another-repo.git",
69+
"name": "http"
70+
}],
71+
"self": [{
72+
"href": "http://localhost:7990/projects/AMUNIZ/repos/another-repo/browse"
73+
}]
74+
}
75+
},
76+
{
77+
"slug": "dogs-repo",
78+
"id": 3,
79+
"name": "dogs-repo",
80+
"scmId": "git",
81+
"state": "AVAILABLE",
82+
"statusMessage": "Available",
83+
"forkable": false,
84+
"project": {
85+
"key": "AMUNIZ",
86+
"id": 1,
87+
"name": "prj",
88+
"description": "This is a test repo",
89+
"public": true,
90+
"type": "NORMAL",
91+
"links": {
92+
"self": [{
93+
"href": "http://localhost:7990/projects/AMUNIZ"
94+
}]
95+
}
96+
},
97+
"public": false,
98+
"links": {
99+
"clone": [{
100+
"href": "ssh://git@localhost:7999/amuniz/dogs-repo.git",
101+
"name": "ssh"
102+
}, {
103+
"href": "http://localhost:7990/scm/amuniz/dogs-repo.git",
104+
"name": "http"
105+
}],
106+
"self": [{
107+
"href": "http://localhost:7990/projects/AMUNIZ/repos/dogs-repo/browse"
108+
}]
109+
}
110+
}
111+
],
112+
"start": 0
113+
}
Lines changed: 80 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,80 @@
1+
{
2+
"size": 1,
3+
"limit": 200,
4+
"isLastPage": true,
5+
"values": [
6+
{
7+
"slug": "bar-active",
8+
"id": 1,
9+
"name": "bar-active",
10+
"scmId": "git",
11+
"state": "AVAILABLE",
12+
"statusMessage": "Available",
13+
"forkable": false,
14+
"project": {
15+
"key": "FOO",
16+
"id": 1,
17+
"name": "prj",
18+
"description": "This is a test repo",
19+
"public": true,
20+
"type": "NORMAL",
21+
"links": {
22+
"self": [{
23+
"href": "http://localhost:7990/projects/FOO"
24+
}]
25+
}
26+
},
27+
"public": false,
28+
"archived": false,
29+
"links": {
30+
"clone": [{
31+
"href": "ssh://git@localhost:7999/foo/bar-active.git",
32+
"name": "ssh"
33+
}, {
34+
"href": "http://localhost:7990/scm/foo/bar-active.git",
35+
"name": "http"
36+
}],
37+
"self": [{
38+
"href": "http://localhost:7990/projects/FOO/repos/bar-active/browse"
39+
}]
40+
}
41+
},
42+
{
43+
"slug": "bar-archived",
44+
"id": 1,
45+
"name": "test-repos",
46+
"scmId": "git",
47+
"state": "AVAILABLE",
48+
"statusMessage": "Available",
49+
"forkable": false,
50+
"project": {
51+
"key": "FOO",
52+
"id": 1,
53+
"name": "prj",
54+
"description": "This is a test repo",
55+
"public": true,
56+
"type": "NORMAL",
57+
"links": {
58+
"self": [{
59+
"href": "http://localhost:7990/projects/FOO"
60+
}]
61+
}
62+
},
63+
"public": false,
64+
"archived": true,
65+
"links": {
66+
"clone": [{
67+
"href": "ssh://git@localhost:7999/foo/bar-archived.git",
68+
"name": "ssh"
69+
}, {
70+
"href": "http://localhost:7990/scm/foo/bar-archived.git",
71+
"name": "http"
72+
}],
73+
"self": [{
74+
"href": "http://localhost:7990/projects/FOO/repos/bar-archived/browse"
75+
}]
76+
}
77+
}
78+
],
79+
"start": 0
80+
}

0 commit comments

Comments
 (0)