Skip to content

Commit 055397b

Browse files
committed
ADDED: TagApi with endpoints 'create' and 'get'.
1 parent 9fb9515 commit 055397b

File tree

8 files changed

+359
-5
lines changed

8 files changed

+359
-5
lines changed

src/main/java/com/cdancy/bitbucket/rest/BitbucketApi.java

+4-5
Original file line numberDiff line numberDiff line change
@@ -19,13 +19,9 @@
1919

2020
import java.io.Closeable;
2121

22-
import com.cdancy.bitbucket.rest.features.ProjectApi;
23-
import com.cdancy.bitbucket.rest.features.RepositoryApi;
22+
import com.cdancy.bitbucket.rest.features.*;
2423
import org.jclouds.rest.annotations.Delegate;
2524

26-
import com.cdancy.bitbucket.rest.features.PullRequestApi;
27-
import com.cdancy.bitbucket.rest.features.SystemApi;
28-
2925
public interface BitbucketApi extends Closeable {
3026

3127
@Delegate
@@ -39,4 +35,7 @@ public interface BitbucketApi extends Closeable {
3935

4036
@Delegate
4137
SystemApi systemApi();
38+
39+
@Delegate
40+
TagApi tagApi();
4241
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,61 @@
1+
/*
2+
* Licensed to the Apache Software Foundation (ASF) under one or more
3+
* contributor license agreements. See the NOTICE file distributed with
4+
* this work for additional information regarding copyright ownership.
5+
* The ASF licenses this file to You under the Apache License, Version 2.0
6+
* (the "License"); you may not use this file except in compliance with
7+
* the License. You may obtain a copy of the License at
8+
*
9+
* http://www.apache.org/licenses/LICENSE-2.0
10+
*
11+
* Unless required by applicable law or agreed to in writing, software
12+
* distributed under the License is distributed on an "AS IS" BASIS,
13+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14+
* See the License for the specific language governing permissions and
15+
* limitations under the License.
16+
*/
17+
18+
package com.cdancy.bitbucket.rest.domain.tags;
19+
20+
import com.cdancy.bitbucket.rest.error.Error;
21+
import com.google.auto.value.AutoValue;
22+
import com.google.common.collect.ImmutableList;
23+
import org.jclouds.javax.annotation.Nullable;
24+
import org.jclouds.json.SerializedNames;
25+
26+
import java.util.List;
27+
28+
@AutoValue
29+
public abstract class Tag {
30+
31+
@Nullable
32+
public abstract String id();
33+
34+
@Nullable
35+
public abstract String displayId();
36+
37+
@Nullable
38+
public abstract String type();
39+
40+
@Nullable
41+
public abstract String latestCommit();
42+
43+
@Nullable
44+
public abstract String latestChangeset();
45+
46+
@Nullable
47+
public abstract String hash();
48+
49+
@Nullable
50+
public abstract List<Error> errors();
51+
52+
Tag() {
53+
}
54+
55+
@SerializedNames({ "id", "displayId", "type", "latestCommit", "latestChangeset", "hash", "errors" })
56+
public static Tag create(String id, String displayId, String type,
57+
String latestCommit, String latestChangeset, String hash, List<Error> errors) {
58+
return new AutoValue_Tag(id, displayId, type, latestCommit, latestChangeset, hash,
59+
errors != null ? ImmutableList.copyOf(errors) : ImmutableList.<Error> of());
60+
}
61+
}

src/main/java/com/cdancy/bitbucket/rest/fallbacks/BitbucketFallbacks.java

+14
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,7 @@
2525
import com.cdancy.bitbucket.rest.domain.project.Project;
2626
import com.cdancy.bitbucket.rest.domain.pullrequest.MergeStatus;
2727
import com.cdancy.bitbucket.rest.domain.repository.Repository;
28+
import com.cdancy.bitbucket.rest.domain.tags.Tag;
2829
import org.jclouds.Fallback;
2930

3031
import com.cdancy.bitbucket.rest.domain.pullrequest.PullRequest;
@@ -48,6 +49,15 @@ public Object createOrPropagate(Throwable t) throws Exception {
4849
}
4950
}
5051

52+
public static final class TagOnError implements Fallback<Object> {
53+
public Object createOrPropagate(Throwable t) throws Exception {
54+
if (checkNotNull(t, "throwable") != null) {
55+
return createTagFromErrors(getErrors(t.getMessage()));
56+
}
57+
throw propagate(t);
58+
}
59+
}
60+
5161
public static final class RepositoryOnError implements Fallback<Object> {
5262
public Object createOrPropagate(Throwable t) throws Exception {
5363
if (checkNotNull(t, "throwable") != null) {
@@ -105,6 +115,10 @@ public static List<Error> getErrors(String output) {
105115
return errors;
106116
}
107117

118+
public static Tag createTagFromErrors(List<Error> errors) {
119+
return Tag.create(null, null, null, null, null, null, errors);
120+
}
121+
108122
public static Repository createRepositoryFromErrors(List<Error> errors) {
109123
return Repository.create(null, -1, null, null, null, null, false, null, false, null, errors);
110124
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,52 @@
1+
/*
2+
* Licensed to the Apache Software Foundation (ASF) under one or more
3+
* contributor license agreements. See the NOTICE file distributed with
4+
* this work for additional information regarding copyright ownership.
5+
* The ASF licenses this file to You under the Apache License, Version 2.0
6+
* (the "License"); you may not use this file except in compliance with
7+
* the License. You may obtain a copy of the License at
8+
*
9+
* http://www.apache.org/licenses/LICENSE-2.0
10+
*
11+
* Unless required by applicable law or agreed to in writing, software
12+
* distributed under the License is distributed on an "AS IS" BASIS,
13+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14+
* See the License for the specific language governing permissions and
15+
* limitations under the License.
16+
*/
17+
18+
package com.cdancy.bitbucket.rest.features;
19+
20+
import com.cdancy.bitbucket.rest.domain.tags.Tag;
21+
import com.cdancy.bitbucket.rest.fallbacks.BitbucketFallbacks;
22+
import com.cdancy.bitbucket.rest.filters.BitbucketAuthentication;
23+
import com.cdancy.bitbucket.rest.options.CreateTag;
24+
import org.jclouds.Fallbacks;
25+
import org.jclouds.rest.annotations.BinderParam;
26+
import org.jclouds.rest.annotations.Fallback;
27+
import org.jclouds.rest.annotations.RequestFilters;
28+
import org.jclouds.rest.binders.BindToJsonPayload;
29+
30+
import javax.inject.Named;
31+
import javax.ws.rs.*;
32+
import javax.ws.rs.core.MediaType;
33+
34+
@Produces(MediaType.APPLICATION_JSON)
35+
@RequestFilters(BitbucketAuthentication.class)
36+
@Path("/rest/api/{jclouds.api-version}/projects")
37+
public interface TagApi {
38+
39+
@Named("tag:create")
40+
@Consumes(MediaType.APPLICATION_JSON)
41+
@Path("/{project}/repos/{repo}/tags")
42+
@Fallback(BitbucketFallbacks.TagOnError.class)
43+
@POST
44+
Tag create(@PathParam("project") String project, @PathParam("repo") String repo, @BinderParam(BindToJsonPayload.class) CreateTag createTag);
45+
46+
@Named("tag:get")
47+
@Consumes(MediaType.APPLICATION_JSON)
48+
@Path("/{project}/repos/{repo}/tags/{tag}")
49+
@Fallback(Fallbacks.NullOnNotFoundOr404.class)
50+
@GET
51+
Tag get(@PathParam("project") String project, @PathParam("repo") String repo, @PathParam("tag") String tag);
52+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,42 @@
1+
/*
2+
* Licensed to the Apache Software Foundation (ASF) under one or more
3+
* contributor license agreements. See the NOTICE file distributed with
4+
* this work for additional information regarding copyright ownership.
5+
* The ASF licenses this file to You under the Apache License, Version 2.0
6+
* (the "License"); you may not use this file except in compliance with
7+
* the License. You may obtain a copy of the License at
8+
*
9+
* http://www.apache.org/licenses/LICENSE-2.0
10+
*
11+
* Unless required by applicable law or agreed to in writing, software
12+
* distributed under the License is distributed on an "AS IS" BASIS,
13+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14+
* See the License for the specific language governing permissions and
15+
* limitations under the License.
16+
*/
17+
18+
package com.cdancy.bitbucket.rest.options;
19+
20+
import com.google.auto.value.AutoValue;
21+
import org.jclouds.javax.annotation.Nullable;
22+
import org.jclouds.json.SerializedNames;
23+
24+
@AutoValue
25+
public abstract class CreateTag {
26+
27+
public abstract String name();
28+
29+
public abstract String startPoint();
30+
31+
// defaults to value of name if null
32+
@Nullable
33+
public abstract String message();
34+
35+
CreateTag() {
36+
}
37+
38+
@SerializedNames({ "name", "startPoint", "message" })
39+
public static CreateTag create(String name, String startPoint, String message) {
40+
return new AutoValue_CreateTag(name, startPoint, message != null ? message : name);
41+
}
42+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,70 @@
1+
/*
2+
* Licensed to the Apache Software Foundation (ASF) under one or more
3+
* contributor license agreements. See the NOTICE file distributed with
4+
* this work for additional information regarding copyright ownership.
5+
* The ASF licenses this file to You under the Apache License, Version 2.0
6+
* (the "License"); you may not use this file except in compliance with
7+
* the License. You may obtain a copy of the License at
8+
*
9+
* http://www.apache.org/licenses/LICENSE-2.0
10+
*
11+
* Unless required by applicable law or agreed to in writing, software
12+
* distributed under the License is distributed on an "AS IS" BASIS,
13+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14+
* See the License for the specific language governing permissions and
15+
* limitations under the License.
16+
*/
17+
package com.cdancy.bitbucket.rest.features;
18+
19+
import com.cdancy.bitbucket.rest.BaseBitbucketApiLiveTest;
20+
21+
import com.cdancy.bitbucket.rest.domain.tags.Tag;
22+
import com.cdancy.bitbucket.rest.options.CreateTag;
23+
import org.testng.annotations.Test;
24+
25+
import static org.testng.Assert.assertNull;
26+
import static org.testng.Assert.assertNotNull;
27+
import static org.testng.Assert.assertTrue;
28+
29+
@Test(groups = "live", testName = "TagApiLiveTest", singleThreaded = true)
30+
public class TagApiLiveTest extends BaseBitbucketApiLiveTest {
31+
32+
/*
33+
String projectKey = randomStringLettersOnly();
34+
String repoKey = randomStringLettersOnly();
35+
String tagName = randomStringLettersOnly();
36+
String commitHash = "";
37+
*/
38+
39+
String projectKey = "TEST";
40+
String repoKey = "dev";
41+
String tagName = randomStringLettersOnly();
42+
String commitHash = "d90ca08fa076e2e4c076592fce3832aba80a494f";
43+
44+
@Test
45+
public void testCreateTag() {
46+
CreateTag createTag = CreateTag.create(tagName, commitHash, null);
47+
Tag tag = api().create(projectKey, repoKey, createTag);
48+
assertNotNull(tag);
49+
assertTrue(tag.errors().size() == 0);
50+
assertTrue(tag.id().endsWith(tagName));
51+
assertTrue(tag.latestCommit().equalsIgnoreCase(commitHash));
52+
}
53+
54+
@Test (dependsOnMethods = "testCreateTag")
55+
public void testGetTag() {
56+
Tag tag = api().get(projectKey, repoKey, tagName);
57+
assertNotNull(tag);
58+
assertTrue(tag.errors().size() == 0);
59+
assertTrue(tag.id().endsWith(tagName));
60+
assertTrue(tag.latestCommit().equalsIgnoreCase(commitHash));
61+
}
62+
63+
@Test
64+
public void testGetTagNonExistent() {
65+
Tag tag = api().get(projectKey, repoKey, tagName + "9999");
66+
assertNull(tag);
67+
}
68+
69+
private TagApi api() { return api.tagApi(); }
70+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,108 @@
1+
/*
2+
* Licensed to the Apache Software Foundation (ASF) under one or more
3+
* contributor license agreements. See the NOTICE file distributed with
4+
* this work for additional information regarding copyright ownership.
5+
* The ASF licenses this file to You under the Apache License, Version 2.0
6+
* (the "License"); you may not use this file except in compliance with
7+
* the License. You may obtain a copy of the License at
8+
*
9+
* http://www.apache.org/licenses/LICENSE-2.0
10+
*
11+
* Unless required by applicable law or agreed to in writing, software
12+
* distributed under the License is distributed on an "AS IS" BASIS,
13+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14+
* See the License for the specific language governing permissions and
15+
* limitations under the License.
16+
*/
17+
package com.cdancy.bitbucket.rest.features;
18+
19+
import com.cdancy.bitbucket.rest.BitbucketApi;
20+
import com.cdancy.bitbucket.rest.BitbucketApiMetadata;
21+
import com.cdancy.bitbucket.rest.domain.repository.Repository;
22+
import com.cdancy.bitbucket.rest.domain.tags.Tag;
23+
import com.cdancy.bitbucket.rest.internal.BaseBitbucketMockTest;
24+
import com.cdancy.bitbucket.rest.options.CreateRepository;
25+
import com.cdancy.bitbucket.rest.options.CreateTag;
26+
import com.squareup.okhttp.mockwebserver.MockResponse;
27+
import com.squareup.okhttp.mockwebserver.MockWebServer;
28+
import org.testng.annotations.Test;
29+
30+
import static org.testng.Assert.assertNull;
31+
import static org.testng.Assert.assertNotNull;
32+
import static org.testng.Assert.assertTrue;
33+
34+
/**
35+
* Mock tests for the {@link TagApi} class.
36+
*/
37+
@Test(groups = "unit", testName = "TagApiMockTest")
38+
public class TagApiMockTest extends BaseBitbucketMockTest {
39+
40+
public void testCreateTag() throws Exception {
41+
MockWebServer server = mockEtcdJavaWebServer();
42+
43+
server.enqueue(new MockResponse().setBody(payloadFromResource("/tag.json")).setResponseCode(200));
44+
BitbucketApi baseApi = api(server.getUrl("/"));
45+
TagApi api = baseApi.tagApi();
46+
try {
47+
String projectKey = "PRJ";
48+
String repoKey = "myrepo";
49+
String tagName = "release-2.0.0";
50+
String commitHash = "8d351a10fb428c0c1239530256e21cf24f136e73";
51+
52+
CreateTag createTag = CreateTag.create(tagName, commitHash, null);
53+
Tag tag = api.create(projectKey, repoKey, createTag);
54+
assertNotNull(tag);
55+
assertTrue(tag.errors().size() == 0);
56+
assertTrue(tag.id().endsWith(tagName));
57+
assertTrue(tag.latestCommit().equalsIgnoreCase(commitHash));
58+
assertSent(server, "POST", "/rest/api/" + BitbucketApiMetadata.API_VERSION + "/projects/" + projectKey + "/repos/" + repoKey + "/tags");
59+
} finally {
60+
baseApi.close();
61+
server.shutdown();
62+
}
63+
}
64+
65+
public void testGetTag() throws Exception {
66+
MockWebServer server = mockEtcdJavaWebServer();
67+
68+
server.enqueue(new MockResponse().setBody(payloadFromResource("/tag.json")).setResponseCode(200));
69+
BitbucketApi baseApi = api(server.getUrl("/"));
70+
TagApi api = baseApi.tagApi();
71+
try {
72+
String projectKey = "PRJ";
73+
String repoKey = "myrepo";
74+
String tagName = "release-2.0.0";
75+
String commitHash = "8d351a10fb428c0c1239530256e21cf24f136e73";
76+
77+
Tag tag = api.get(projectKey, repoKey, tagName);
78+
assertNotNull(tag);
79+
assertTrue(tag.errors().size() == 0);
80+
assertTrue(tag.id().endsWith(tagName));
81+
assertTrue(tag.latestCommit().equalsIgnoreCase(commitHash));
82+
assertSent(server, "GET", "/rest/api/" + BitbucketApiMetadata.API_VERSION + "/projects/" + projectKey + "/repos/" + repoKey + "/tags/" + tagName);
83+
} finally {
84+
baseApi.close();
85+
server.shutdown();
86+
}
87+
}
88+
89+
public void testGetTagNonExistent() throws Exception {
90+
MockWebServer server = mockEtcdJavaWebServer();
91+
92+
server.enqueue(new MockResponse().setResponseCode(404));
93+
BitbucketApi baseApi = api(server.getUrl("/"));
94+
TagApi api = baseApi.tagApi();
95+
try {
96+
String projectKey = "PRJ";
97+
String repoKey = "myrepo";
98+
String tagName = "non-existent-tag";
99+
100+
Tag tag = api.get(projectKey, repoKey, tagName);
101+
assertNull(tag);
102+
assertSent(server, "GET", "/rest/api/" + BitbucketApiMetadata.API_VERSION + "/projects/" + projectKey + "/repos/" + repoKey + "/tags/" + tagName);
103+
} finally {
104+
baseApi.close();
105+
server.shutdown();
106+
}
107+
}
108+
}

0 commit comments

Comments
 (0)