diff --git a/src/main/scala/gitbucket/core/api/ApiBranch.scala b/src/main/scala/gitbucket/core/api/ApiBranch.scala index cf6805b..0a27850 100644 --- a/src/main/scala/gitbucket/core/api/ApiBranch.scala +++ b/src/main/scala/gitbucket/core/api/ApiBranch.scala @@ -14,3 +14,10 @@ "self" -> ApiPath(s"/api/v3/repos/${repositoryName.fullName}/branches/${name}"), "html" -> ApiPath(s"/${repositoryName.fullName}/tree/${name}")) } + +case class ApiBranchCommit(sha: String) + +case class ApiBranchForList( + name: String, + commit: ApiBranchCommit +) diff --git a/src/main/scala/gitbucket/core/api/ApiContents.scala b/src/main/scala/gitbucket/core/api/ApiContents.scala new file mode 100644 index 0000000..db70320 --- /dev/null +++ b/src/main/scala/gitbucket/core/api/ApiContents.scala @@ -0,0 +1,11 @@ +package gitbucket.core.api + +import gitbucket.core.util.JGitUtil.FileInfo + +case class ApiContents(`type`: String, name: String) + +object ApiContents{ + def apply(fileInfo: FileInfo): ApiContents = + if(fileInfo.isDirectory) ApiContents("dir", fileInfo.name) + else ApiContents("file", fileInfo.name) +} \ No newline at end of file diff --git a/src/main/scala/gitbucket/core/api/ApiEndPoint.scala b/src/main/scala/gitbucket/core/api/ApiEndPoint.scala new file mode 100644 index 0000000..4c66d84 --- /dev/null +++ b/src/main/scala/gitbucket/core/api/ApiEndPoint.scala @@ -0,0 +1,3 @@ +package gitbucket.core.api + +case class ApiEndPoint(rate_limit_url: ApiPath = ApiPath("/api/v3/rate_limit")) \ No newline at end of file diff --git a/src/main/scala/gitbucket/core/api/ApiRef.scala b/src/main/scala/gitbucket/core/api/ApiRef.scala new file mode 100644 index 0000000..01a9785 --- /dev/null +++ b/src/main/scala/gitbucket/core/api/ApiRef.scala @@ -0,0 +1,5 @@ +package gitbucket.core.api + +case class ApiObject(sha: String) + +case class ApiRef(ref: String, `object`: ApiObject) diff --git a/src/main/scala/gitbucket/core/api/ApiUser.scala b/src/main/scala/gitbucket/core/api/ApiUser.scala index fa69900..7259c12 100644 --- a/src/main/scala/gitbucket/core/api/ApiUser.scala +++ b/src/main/scala/gitbucket/core/api/ApiUser.scala @@ -13,6 +13,7 @@ created_at: Date) { val url = ApiPath(s"/api/v3/users/${login}") val html_url = ApiPath(s"/${login}") + val avatar_url = ApiPath(s"/${login}/_avatar") // val followers_url = ApiPath(s"/api/v3/users/${login}/followers") // val following_url = ApiPath(s"/api/v3/users/${login}/following{/other_user}") // val gists_url = ApiPath(s"/api/v3/users/${login}/gists{/gist_id}") diff --git a/src/main/scala/gitbucket/core/controller/ApiController.scala b/src/main/scala/gitbucket/core/controller/ApiController.scala index c657ee2..959363f 100644 --- a/src/main/scala/gitbucket/core/controller/ApiController.scala +++ b/src/main/scala/gitbucket/core/controller/ApiController.scala @@ -7,7 +7,7 @@ import gitbucket.core.service._ import gitbucket.core.util.ControlUtil._ import gitbucket.core.util.Directory._ -import gitbucket.core.util.JGitUtil.CommitInfo +import gitbucket.core.util.JGitUtil.{CommitInfo, getFileList, getBranches, getDefaultBranch} import gitbucket.core.util._ import gitbucket.core.util.Implicits._ import org.eclipse.jgit.api.Git @@ -54,15 +54,104 @@ with CollaboratorsAuthenticator => /** - * https://developer.github.com/v3/users/#get-a-single-user - */ - get("/api/v3/users/:userName") { - getAccountByUserName(params("userName")).map { account => + * https://developer.github.com/v3/#root-endpoint + */ + get("/api/v3/") { + JsonFormat(ApiEndPoint()) + } + + /** + * https://developer.github.com/v3/orgs/#get-an-organization + */ + get("/api/v3/orgs/:groupName") { + getAccountByUserName(params("groupName")).filter(account => account.isGroupAccount).map { account => JsonFormat(ApiUser(account)) } getOrElse NotFound } /** + * https://developer.github.com/v3/users/#get-a-single-user + */ + get("/api/v3/users/:userName") { + getAccountByUserName(params("userName")).filterNot(account => account.isGroupAccount).map { account => + JsonFormat(ApiUser(account)) + } getOrElse NotFound + } + + /** + * https://developer.github.com/v3/repos/#list-organization-repositories + */ + get("/api/v3/orgs/:orgName/repos") { + JsonFormat(getVisibleRepositories(context.loginAccount, Some(params("orgName"))).map{ r => ApiRepository(r, getAccountByUserName(r.owner).get)}) + } + /** + * https://developer.github.com/v3/repos/#list-user-repositories + */ + get("/api/v3/users/:userName/repos") { + JsonFormat(getVisibleRepositories(context.loginAccount, Some(params("userName"))).map{ r => ApiRepository(r, getAccountByUserName(r.owner).get)}) + } + + /* + * https://developer.github.com/v3/repos/branches/#list-branches + */ + get ("/api/v3/repos/:owner/:repo/branches")(referrersOnly { repository => + JsonFormat(JGitUtil.getBranches( + owner = repository.owner, + name = repository.name, + defaultBranch = repository.repository.defaultBranch, + origin = repository.repository.originUserName.isEmpty + ).map { br => + ApiBranchForList(br.name, ApiBranchCommit(br.commitId)) + }) + }) + + // copy code + private def splitPath(repository: RepositoryService.RepositoryInfo, path: String): (String, String) = { + val id = repository.branchList.collectFirst { + case branch if(path == branch || path.startsWith(branch + "/")) => branch + } orElse repository.tags.collectFirst { + case tag if(path == tag.name || path.startsWith(tag.name + "/")) => tag.name + } getOrElse path.split("/")(0) + + (id, path.substring(id.length).stripPrefix("/")) + } + + /* + * https://developer.github.com/v3/repos/contents/#get-contents + */ + get("/api/v3/repos/:owner/:repo/contents/*")(referrersOnly { repository => + val (id, path) = splitPath(repository, multiParams("splat").head) + val refStr = params("ref") + using(Git.open(getRepositoryDir(params("owner"), params("repo")))){ git => + if (path.isEmpty) { + JsonFormat(getFileList(git, refStr, ".").map{f => ApiContents(f)}) + } else { + JsonFormat(getFileList(git, refStr, path).map{f => ApiContents(f)}) + } + } + }) + + /* + * https://developer.github.com/v3/git/refs/#get-a-reference + */ + get("/api/v3/repos/:owner/:repo/git/*") (referrersOnly { repository => + val revstr = multiParams("splat").head + using(Git.open(getRepositoryDir(params("owner"), params("repo")))) { git => + //JsonFormat( (revstr, git.getRepository().resolve(revstr)) ) + // getRef is deprecated by jgit-4.2. use exactRef() or findRef() + val sha = git.getRepository().getRef(revstr).getObjectId().name() + JsonFormat(ApiRef(revstr, ApiObject(sha))) + } + }) + + /** + * https://developer.github.com/v3/repos/collaborators/#list-collaborators + */ + get("/api/v3/repos/:owner/:repo/collaborators") (referrersOnly { repository => + JsonFormat(getCollaborators(params("owner"), params("repo")).map(u => ApiUser(getAccountByUserName(u).get))) + }) + + /** * https://developer.github.com/v3/users/#get-the-authenticated-user */ get("/api/v3/user") { @@ -72,6 +161,16 @@ } /** + * List user's own repository + * https://developer.github.com/v3/repos/#list-your-repositories + */ + get("/api/v3/user/repos")(usersOnly{ + JsonFormat(getVisibleRepositories(context.loginAccount, Option(context.loginAccount.get.userName)).map{ + r => ApiRepository(r, getAccountByUserName(r.owner).get) + }) + }) + + /** * Create user repository * https://developer.github.com/v3/repos/#create */ diff --git a/src/test/scala/gitbucket/core/api/JsonFormatSpec.scala b/src/test/scala/gitbucket/core/api/JsonFormatSpec.scala index 4d84fe5..6e6376e 100644 --- a/src/test/scala/gitbucket/core/api/JsonFormatSpec.scala +++ b/src/test/scala/gitbucket/core/api/JsonFormatSpec.scala @@ -37,7 +37,8 @@ "site_admin":false, "created_at":"2011-04-14T16:00:49Z", "url":"http://gitbucket.exmple.com/api/v3/users/octocat", - "html_url":"http://gitbucket.exmple.com/octocat" + "html_url":"http://gitbucket.exmple.com/octocat", + "avatar_url":"http://gitbucket.exmple.com/octocat/_avatar" }""" val repository = ApiRepository(