Skip to content

Commit 7cd5f3f

Browse files
committed
Move Api2.0 endpoints to new package
1 parent 95376d0 commit 7cd5f3f

File tree

10 files changed

+316
-78
lines changed

10 files changed

+316
-78
lines changed

src/main/scala/com/codacy/client/bitbucket/v1/service/PullRequestServices.scala

Lines changed: 0 additions & 68 deletions
Original file line numberDiff line numberDiff line change
@@ -7,68 +7,6 @@ import play.api.libs.json._
77

88
class PullRequestServices(client: BitbucketClient) {
99

10-
/*
11-
* Gets the list of a repository pull requests
12-
*
13-
* States: OPEN | MERGED | DECLINED
14-
*
15-
*/
16-
def getPullRequests(owner: String, repository: String, states: Seq[String] = Seq("OPEN")): RequestResponse[Seq[PullRequest]] = {
17-
val url = s"https://bitbucket.org/api/2.0/repositories/$owner/$repository/pullrequests?pagelen=50&state=${states.mkString("&state=")}"
18-
19-
client.executePaginated(Request(url, classOf[Seq[PullRequest]]))
20-
}
21-
22-
/*
23-
* Gets the list of commits of a pull request
24-
*
25-
*/
26-
def getPullRequestCommits(owner: String, repository: String, prId: Long): RequestResponse[Seq[SimpleCommit]] = {
27-
val url = s"https://bitbucket.org/api/2.0/repositories/$owner/$repository/pullrequests/$prId/commits?pagelen=100"
28-
29-
client.executePaginated(Request(url, classOf[Seq[SimpleCommit]]))
30-
}
31-
32-
def create(owner: String, repository: String, title: String, sourceBranch: String, destinationBranch: String): RequestResponse[JsObject] = {
33-
val url = s"https://bitbucket.org/api/2.0/repositories/$owner/$repository/pullrequests"
34-
35-
val payload = Json.obj(
36-
"title" -> title,
37-
"source" -> Json.obj(
38-
"branch" -> Json.obj(
39-
"name" -> sourceBranch
40-
)
41-
),
42-
"destination" -> Json.obj(
43-
"branch" -> Json.obj(
44-
"name" -> destinationBranch
45-
)
46-
)
47-
)
48-
49-
client.postJson(Request(url, classOf[JsObject]), payload)
50-
}
51-
52-
def postApprove(owner: String, repository: String, prId: Long): RequestResponse[JsObject] = {
53-
val url = s"https://bitbucket.org/api/2.0/repositories/$owner/$repository/pullrequests/$prId/approve"
54-
client.postJson(Request(url, classOf[JsObject]), JsNull)
55-
}
56-
57-
def deleteApprove(owner: String, repository: String, prId: Long): RequestResponse[Boolean] = {
58-
val url = s"https://bitbucket.org/api/2.0/repositories/$owner/$repository/pullrequests/$prId/approve"
59-
client.delete(url)
60-
}
61-
62-
def merge(owner: String, repository: String, prId: Long): RequestResponse[JsObject] = {
63-
val url = s"https://bitbucket.org/api/2.0/repositories/$owner/$repository/pullrequests/$prId/merge"
64-
client.postJson(Request(url, classOf[JsObject]), JsNull)
65-
}
66-
67-
def decline(owner: String, repository: String, prId: Long): RequestResponse[JsObject] = {
68-
val url = s"https://bitbucket.org/api/2.0/repositories/$owner/$repository/pullrequests/$prId/decline"
69-
client.postJson(Request(url, classOf[JsObject]), JsNull)
70-
}
71-
7210
private[this] def postNewComment(author: String, repo: String, prId: Int, values: JsObject): RequestResponse[PullRequestComment] = {
7311
val url = s"https://bitbucket.org/api/1.0/repositories/$author/$repo/pullrequests/$prId/comments"
7412
client.postJson(Request(url, classOf[PullRequestComment]), values)
@@ -100,10 +38,4 @@ class PullRequestServices(client: BitbucketClient) {
10038
client.execute(Request(url, classOf[Seq[SimplePullRequestComment]]))
10139
}
10240

103-
def getPullRequestsReviewers(owner: String, repository: String, prId: Long): RequestResponse[PullRequestReviewers] = {
104-
val url = s"https://bitbucket.org/api/2.0/repositories/$owner/$repository/pullrequests/$prId"
105-
106-
client.execute(Request(url, classOf[PullRequestReviewers]))
107-
}
108-
10941
}

src/main/scala/com/codacy/client/bitbucket/v1/service/RepositoryServices.scala

Lines changed: 0 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -14,14 +14,6 @@ class RepositoryServices(client: BitbucketClient) {
1414
client.execute(Request(s"https://bitbucket.org/api/1.0/user/repositories", classOf[Seq[SimpleRepository]]))
1515
}
1616

17-
/*
18-
* Gets the list of the user's repositories. Private repositories only appear on this list
19-
* if the caller is authenticated and is authorized to view the repository.
20-
*/
21-
def getRepositories(username: String): RequestResponse[Seq[Repository]] = {
22-
client.executePaginated(Request(s"https://bitbucket.org/api/2.0/repositories/$username", classOf[Seq[Repository]]))
23-
}
24-
2517
/*
2618
* Creates a ssh key
2719
*/
Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
package com.codacy.client.bitbucket.v2
2+
3+
import com.codacy.client.util.JsonEnumeration
4+
import play.api.libs.json.Json
5+
6+
object CommitStatus extends JsonEnumeration {
7+
val InProgress = Value("INPROGRESS")
8+
val Successful = Value("SUCCESSFUL")
9+
val Failed = Value("FAILED")
10+
}
11+
12+
case class BuildStatus(state: CommitStatus.Value, key: String, name: String, url: String, description: String)
13+
14+
object BuildStatus {
15+
implicit val fmt = Json.format[BuildStatus]
16+
}
Lines changed: 74 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,74 @@
1+
package com.codacy.client.bitbucket.v2
2+
3+
import java.time.LocalDateTime
4+
5+
import play.api.libs.functional.syntax._
6+
import play.api.libs.json._
7+
8+
case class PullRequest(id: Long, title: String, description: String,
9+
authorUsername: Option[String], authorAvatar: Option[String],
10+
state: String, created_on: LocalDateTime, updated_on: LocalDateTime,
11+
sourceRepository: String, sourceBranch: String, sourceCommit: String,
12+
destRepository: String, destBranch: String, destCommit: Option[String],
13+
apiUrls: Seq[ApiUrl], authorUUID: Option[String] = None) {
14+
val url = s"https://bitbucket.org/$destRepository/pull-request/$id"
15+
}
16+
17+
object ApiUrlType extends Enumeration {
18+
val Commits = Value("commits")
19+
val Decline = Value("decline")
20+
val Self = Value("self")
21+
val Comments = Value("comments")
22+
val Patch = Value("patch")
23+
val Merge = Value("merge")
24+
val Html = Value("html")
25+
val Activity = Value("activity")
26+
val Diff = Value("diff")
27+
val Approve = Value("approve")
28+
29+
def find(urlType: String): Option[Value] = {
30+
values.find(_.toString == urlType)
31+
}
32+
}
33+
34+
case class ApiUrl(urlType: ApiUrlType.Value, link: String)
35+
36+
object PullRequest {
37+
val dateFormat = "yyyy-MM-dd'T'HH:mm:ss.SSSSSSXXX"
38+
implicit val dateTimeReads: Reads[LocalDateTime] = Reads.localDateTimeReads(dateFormat)
39+
40+
implicit def optionStringReader: Reads[Option[String]] = Reads { (json: JsValue) =>
41+
json match {
42+
case JsString(value) => JsSuccess(Some(value))
43+
case _ => JsSuccess(None)
44+
}
45+
}
46+
47+
implicit val reader: Reads[PullRequest] = (
48+
(__ \ "id").read[Long] and
49+
(__ \ "title").read[String] and
50+
(__ \ "description").read[String] and
51+
(__ \ "author" \ "username").readNullable[String] and
52+
(__ \ "author" \ "links" \ "avatar" \ "href").readNullable[String].orElse((__ \ "author" \ "links").readNullable[String]) and
53+
(__ \ "state").read[String] and
54+
(__ \ "created_on").read[LocalDateTime] and
55+
(__ \ "updated_on").read[LocalDateTime] and
56+
(__ \ "source" \ "repository" \ "full_name").read[String] and
57+
(__ \ "source" \ "branch" \ "name").read[String] and
58+
(__ \ "source" \ "commit" \ "hash").read[String] and
59+
(__ \ "destination" \ "repository" \ "full_name").read[String] and
60+
(__ \ "destination" \ "branch" \ "name").read[String] and
61+
(__ \ "destination" \ "commit" \ "hash").readNullable[String] and
62+
// TODO: (__ \ "destination" \ "commit" \ "hash").read[Option[String]] and
63+
(__ \ "links").read[Map[String, Map[String, String]]].map(parseLinks) and
64+
(__ \ "author" \ "uuid").readNullable[String]
65+
) (PullRequest.apply _)
66+
67+
private def parseLinks(links: Map[String, Map[String, String]]): Seq[ApiUrl] = {
68+
(for {
69+
(linkName, linkMap) <- links
70+
urlType <- ApiUrlType.find(linkName)
71+
linkUrl <- linkMap.get("href")
72+
} yield ApiUrl(urlType, linkUrl)).toSeq
73+
}
74+
}
Lines changed: 69 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,69 @@
1+
package com.codacy.client.bitbucket.v2
2+
3+
import java.time.LocalDateTime
4+
5+
import play.api.libs.functional.syntax._
6+
import play.api.libs.json._
7+
8+
case class Repository(name: String, full_name: String, description: String, scm: String,
9+
created_on: LocalDateTime, updated_on: LocalDateTime, owner: String, size: Long,
10+
has_issues: Boolean, is_private: Boolean, language: String,
11+
url: Seq[RepositoryUrl])
12+
13+
object Repository {
14+
val dateFormat = "yyyy-MM-dd'T'HH:mm:ss.SSSSSSXXX"
15+
val dateFormatWithoutMillis = "yyyy-MM-dd'T'HH:mm:ssXXX"
16+
17+
implicit val dateTimeReads: Reads[LocalDateTime] =
18+
Reads.localDateTimeReads(dateFormat)
19+
.orElse(Reads.localDateTimeReads(dateFormatWithoutMillis))
20+
21+
implicit val reader: Reads[Repository] = {
22+
((__ \ "name").read[String] and
23+
(__ \ "full_name").read[String] and
24+
(__ \ "description").read[String] and
25+
(__ \ "scm").read[String] and
26+
(__ \ "created_on").read[LocalDateTime] and
27+
(__ \ "updated_on").read[LocalDateTime] and
28+
(__ \ "owner" \ "username").read[String] and
29+
(__ \ "size").read[Long] and
30+
(__ \ "has_issues").read[Boolean] and
31+
(__ \ "is_private").read[Boolean] and
32+
(__ \ "language").read[String] and
33+
(__ \ "links").read[Map[String, JsValue]].map(parseLinks)
34+
) (Repository.apply _)
35+
}
36+
37+
private def parseLinks(links: Map[String, JsValue]): Seq[RepositoryUrl] = {
38+
links.flatMap {
39+
case (linkName, linkMap) =>
40+
41+
val simpleLinks = for {
42+
ref <- linkMap.asOpt[Map[String, String]]
43+
urlType <- RepositoryUrlType.find(linkName)
44+
linkUrl <- ref.get("href")
45+
} yield RepositoryUrl(urlType, linkUrl)
46+
47+
val complexLinks = for {
48+
refs <- linkMap.asOpt[Seq[Map[String, String]]].toSeq
49+
ref <- refs
50+
linkName <- ref.get("name")
51+
urlType <- RepositoryUrlType.find(linkName)
52+
linkUrl <- ref.get("href")
53+
} yield RepositoryUrl(urlType, linkUrl)
54+
55+
simpleLinks ++ complexLinks
56+
}.toSeq
57+
}
58+
}
59+
60+
object RepositoryUrlType extends Enumeration {
61+
val Https = Value("https")
62+
val Ssh = Value("ssh")
63+
64+
def find(urlType: String): Option[Value] = {
65+
values.find(_.toString == urlType)
66+
}
67+
}
68+
69+
case class RepositoryUrl(urlType: RepositoryUrlType.Value, link: String)

src/main/scala/com/codacy/client/bitbucket/v1/service/BuildStatusServices.scala renamed to src/main/scala/com/codacy/client/bitbucket/v2/service/BuildStatusServices.scala

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
1-
package com.codacy.client.bitbucket.v1.service
1+
package com.codacy.client.bitbucket.v2.service
22

3-
import com.codacy.client.bitbucket.v1.BuildStatus
3+
import com.codacy.client.bitbucket.v2.BuildStatus
44
import com.codacy.client.client.{BitbucketClient, Request, RequestResponse}
55
import play.api.libs.json.Json
66

Lines changed: 46 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,46 @@
1+
package com.codacy.client.bitbucket.v2.service
2+
3+
import com.codacy.client.bitbucket.v2
4+
import com.codacy.client.client.{BitbucketClient, Request, RequestResponse}
5+
import play.api.libs.json.Json
6+
7+
class HookServices(client: BitbucketClient) {
8+
9+
def list(author: String, repo: String): RequestResponse[Seq[v2.Webhook]] = {
10+
val servicesUrl = getServicesUrl(author, repo)
11+
client.executePaginated(Request(servicesUrl, classOf[Seq[v2.Webhook]]))
12+
}
13+
14+
def create(author: String, repo: String, description: String, hookUrl: String, events:Set[String]): RequestResponse[v2.Webhook] = {
15+
val servicesUrl = getServicesUrl(author, repo)
16+
val payload = Json.obj(
17+
"active" -> true,
18+
"description" -> description,
19+
"url" -> hookUrl,
20+
"events" -> events
21+
)
22+
client.postJson(Request(servicesUrl, classOf[v2.Webhook]), payload)
23+
}
24+
25+
def update(author: String, repo: String, uuid: String,
26+
active: Boolean, description: String, hookUrl: String, events:Set[String]): RequestResponse[v2.Webhook] = {
27+
val servicesUrl = getServicesUrl(author, repo)
28+
val payload = Json.obj(
29+
"active" -> active,
30+
"description" -> description,
31+
"url" -> hookUrl,
32+
"events" -> events
33+
)
34+
client.putJson(Request(s"$servicesUrl/$uuid", classOf[v2.Webhook]), payload)
35+
}
36+
37+
def delete(author: String, repo: String, uuid: String): RequestResponse[Boolean] = {
38+
val servicesUrl = getServicesUrl(author, repo)
39+
client.delete(s"$servicesUrl/$uuid")
40+
}
41+
42+
private[this] lazy val BASE_URL: String = "https://api.bitbucket.org/2.0/repositories"
43+
44+
private[this] def getServicesUrl(owner: String, repo: String) = s"$BASE_URL/$owner/$repo/hooks"
45+
46+
}
Lines changed: 78 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,78 @@
1+
package com.codacy.client.bitbucket.v2.service
2+
3+
import com.codacy.client.bitbucket.v2
4+
import com.codacy.client.bitbucket.v2.PullRequest
5+
import com.codacy.client.client.{BitbucketClient, Request, RequestResponse}
6+
import play.api.libs.json._
7+
8+
class PullRequestServices(client: BitbucketClient) {
9+
10+
/*
11+
* Gets the list of a repository pull requests
12+
*
13+
* States: OPEN | MERGED | DECLINED
14+
*
15+
*/
16+
def getPullRequests(owner: String, repository: String, states: Seq[String] = Seq("OPEN")): RequestResponse[Seq[PullRequest]] = {
17+
val url = s"https://bitbucket.org/api/2.0/repositories/$owner/$repository/pullrequests?pagelen=50&state=${states.mkString("&state=")}"
18+
19+
client.executePaginated(Request(url, classOf[Seq[PullRequest]]))
20+
}
21+
22+
/*
23+
* Gets the list of commits of a pull request
24+
*
25+
*/
26+
def getPullRequestCommits(owner: String, repository: String, prId: Long): RequestResponse[Seq[v2.SimpleCommit]] = {
27+
val url = s"https://bitbucket.org/api/2.0/repositories/$owner/$repository/pullrequests/$prId/commits?pagelen=100"
28+
29+
client.executePaginated(Request(url, classOf[Seq[v2.SimpleCommit]]))
30+
}
31+
32+
def create(owner: String, repository: String, title: String, sourceBranch: String, destinationBranch: String): RequestResponse[JsObject] = {
33+
val url = s"https://bitbucket.org/api/2.0/repositories/$owner/$repository/pullrequests"
34+
35+
val payload = Json.obj(
36+
"title" -> title,
37+
"source" -> Json.obj(
38+
"branch" -> Json.obj(
39+
"name" -> sourceBranch
40+
)
41+
),
42+
"destination" -> Json.obj(
43+
"branch" -> Json.obj(
44+
"name" -> destinationBranch
45+
)
46+
)
47+
)
48+
49+
client.postJson(Request(url, classOf[JsObject]), payload)
50+
}
51+
52+
def postApprove(owner: String, repository: String, prId: Long): RequestResponse[JsObject] = {
53+
val url = s"https://bitbucket.org/api/2.0/repositories/$owner/$repository/pullrequests/$prId/approve"
54+
client.postJson(Request(url, classOf[JsObject]), JsNull)
55+
}
56+
57+
def deleteApprove(owner: String, repository: String, prId: Long): RequestResponse[Boolean] = {
58+
val url = s"https://bitbucket.org/api/2.0/repositories/$owner/$repository/pullrequests/$prId/approve"
59+
client.delete(url)
60+
}
61+
62+
def merge(owner: String, repository: String, prId: Long): RequestResponse[JsObject] = {
63+
val url = s"https://bitbucket.org/api/2.0/repositories/$owner/$repository/pullrequests/$prId/merge"
64+
client.postJson(Request(url, classOf[JsObject]), JsNull)
65+
}
66+
67+
def decline(owner: String, repository: String, prId: Long): RequestResponse[JsObject] = {
68+
val url = s"https://bitbucket.org/api/2.0/repositories/$owner/$repository/pullrequests/$prId/decline"
69+
client.postJson(Request(url, classOf[JsObject]), JsNull)
70+
}
71+
72+
def getPullRequestsReviewers(owner: String, repository: String, prId: Long): RequestResponse[v2.PullRequestReviewers] = {
73+
val url = s"https://bitbucket.org/api/2.0/repositories/$owner/$repository/pullrequests/$prId"
74+
75+
client.execute(Request(url, classOf[v2.PullRequestReviewers]))
76+
}
77+
78+
}

0 commit comments

Comments
 (0)