diff --git a/src/main/resources/update/2_9.sql b/src/main/resources/update/2_9.sql index 1ac303b..3ddc48a 100644 --- a/src/main/resources/update/2_9.sql +++ b/src/main/resources/update/2_9.sql @@ -1,42 +1,42 @@ -DROP TABLE IF EXISTS ACCESS_TOKEN; - -CREATE TABLE ACCESS_TOKEN ( - ACCESS_TOKEN_ID INT NOT NULL AUTO_INCREMENT, - TOKEN_HASH VARCHAR(40) NOT NULL, - USER_NAME VARCHAR(100) NOT NULL, - NOTE TEXT NOT NULL -); - -ALTER TABLE ACCESS_TOKEN ADD CONSTRAINT IDX_ACCESS_TOKEN_PK PRIMARY KEY (ACCESS_TOKEN_ID); -ALTER TABLE ACCESS_TOKEN ADD CONSTRAINT IDX_ACCESS_TOKEN_FK0 FOREIGN KEY (USER_NAME) REFERENCES ACCOUNT (USER_NAME) - ON DELETE CASCADE ON UPDATE CASCADE; -ALTER TABLE ACCESS_TOKEN ADD CONSTRAINT IDX_ACCESS_TOKEN_TOKEN_HASH UNIQUE(TOKEN_HASH); - - -DROP TABLE IF EXISTS COMMIT_STATUS; -CREATE TABLE COMMIT_STATUS( - COMMIT_STATUS_ID INT AUTO_INCREMENT, - USER_NAME VARCHAR(100) NOT NULL, - REPOSITORY_NAME VARCHAR(100) NOT NULL, - COMMIT_ID VARCHAR(40) NOT NULL, - CONTEXT VARCHAR(255) NOT NULL, -- context is too long (maximum is 255 characters) - STATE VARCHAR(10) NOT NULL, -- pending, success, error, or failure - TARGET_URL VARCHAR(200), - DESCRIPTION TEXT, - CREATOR VARCHAR(100) NOT NULL, - REGISTERED_DATE TIMESTAMP NOT NULL, -- CREATED_AT - UPDATED_DATE TIMESTAMP NOT NULL -- UPDATED_AT -); -ALTER TABLE COMMIT_STATUS ADD CONSTRAINT IDX_COMMIT_STATUS_PK PRIMARY KEY (COMMIT_STATUS_ID); -ALTER TABLE COMMIT_STATUS ADD CONSTRAINT IDX_COMMIT_STATUS_1 - UNIQUE (USER_NAME, REPOSITORY_NAME, COMMIT_ID, CONTEXT); -ALTER TABLE COMMIT_STATUS ADD CONSTRAINT IDX_COMMIT_STATUS_FK1 - FOREIGN KEY (USER_NAME, REPOSITORY_NAME) - REFERENCES REPOSITORY (USER_NAME, REPOSITORY_NAME) - ON DELETE CASCADE ON UPDATE CASCADE; -ALTER TABLE COMMIT_STATUS ADD CONSTRAINT IDX_COMMIT_STATUS_FK2 - FOREIGN KEY (USER_NAME) REFERENCES ACCOUNT (USER_NAME) - ON DELETE CASCADE ON UPDATE CASCADE; -ALTER TABLE COMMIT_STATUS ADD CONSTRAINT IDX_COMMIT_STATUS_FK3 - FOREIGN KEY (CREATOR) REFERENCES ACCOUNT (USER_NAME) - ON DELETE CASCADE ON UPDATE CASCADE; +DROP TABLE IF EXISTS ACCESS_TOKEN; + +CREATE TABLE ACCESS_TOKEN ( + ACCESS_TOKEN_ID INT NOT NULL AUTO_INCREMENT, + TOKEN_HASH VARCHAR(40) NOT NULL, + USER_NAME VARCHAR(100) NOT NULL, + NOTE TEXT NOT NULL +); + +ALTER TABLE ACCESS_TOKEN ADD CONSTRAINT IDX_ACCESS_TOKEN_PK PRIMARY KEY (ACCESS_TOKEN_ID); +ALTER TABLE ACCESS_TOKEN ADD CONSTRAINT IDX_ACCESS_TOKEN_FK0 FOREIGN KEY (USER_NAME) REFERENCES ACCOUNT (USER_NAME) + ON DELETE CASCADE ON UPDATE CASCADE; +ALTER TABLE ACCESS_TOKEN ADD CONSTRAINT IDX_ACCESS_TOKEN_TOKEN_HASH UNIQUE(TOKEN_HASH); + + +DROP TABLE IF EXISTS COMMIT_STATUS; +CREATE TABLE COMMIT_STATUS( + COMMIT_STATUS_ID INT AUTO_INCREMENT, + USER_NAME VARCHAR(100) NOT NULL, + REPOSITORY_NAME VARCHAR(100) NOT NULL, + COMMIT_ID VARCHAR(40) NOT NULL, + CONTEXT VARCHAR(255) NOT NULL, -- context is too long (maximum is 255 characters) + STATE VARCHAR(10) NOT NULL, -- pending, success, error, or failure + TARGET_URL VARCHAR(200), + DESCRIPTION TEXT, + CREATOR VARCHAR(100) NOT NULL, + REGISTERED_DATE TIMESTAMP NOT NULL, -- CREATED_AT + UPDATED_DATE TIMESTAMP NOT NULL -- UPDATED_AT +); +ALTER TABLE COMMIT_STATUS ADD CONSTRAINT IDX_COMMIT_STATUS_PK PRIMARY KEY (COMMIT_STATUS_ID); +ALTER TABLE COMMIT_STATUS ADD CONSTRAINT IDX_COMMIT_STATUS_1 + UNIQUE (USER_NAME, REPOSITORY_NAME, COMMIT_ID, CONTEXT); +ALTER TABLE COMMIT_STATUS ADD CONSTRAINT IDX_COMMIT_STATUS_FK1 + FOREIGN KEY (USER_NAME, REPOSITORY_NAME) + REFERENCES REPOSITORY (USER_NAME, REPOSITORY_NAME) + ON DELETE CASCADE ON UPDATE CASCADE; +ALTER TABLE COMMIT_STATUS ADD CONSTRAINT IDX_COMMIT_STATUS_FK2 + FOREIGN KEY (USER_NAME) REFERENCES ACCOUNT (USER_NAME) + ON DELETE CASCADE ON UPDATE CASCADE; +ALTER TABLE COMMIT_STATUS ADD CONSTRAINT IDX_COMMIT_STATUS_FK3 + FOREIGN KEY (CREATOR) REFERENCES ACCOUNT (USER_NAME) + ON DELETE CASCADE ON UPDATE CASCADE; diff --git a/src/main/scala/api/ApiCombinedCommitStatus.scala b/src/main/scala/api/ApiCombinedCommitStatus.scala index 29d8fa7..19f2ead 100644 --- a/src/main/scala/api/ApiCombinedCommitStatus.scala +++ b/src/main/scala/api/ApiCombinedCommitStatus.scala @@ -1,26 +1,26 @@ -package api - -import model.Account -import model.CommitStatus -import model.CommitState - -/** - * https://developer.github.com/v3/repos/statuses/#get-the-combined-status-for-a-specific-ref - */ -case class ApiCombinedCommitStatus( - state: String, - sha: String, - total_count: Int, - statuses: Iterable[ApiCommitStatus], - repository: ApiRepository){ - // val commit_url = ApiPath(s"/api/v3/repos/${repository.full_name}/${sha}") - val url = ApiPath(s"/api/v3/repos/${repository.full_name}/commits/${sha}/status") -} -object ApiCombinedCommitStatus { - def apply(sha:String, statuses: Iterable[(CommitStatus, Account)], repository:ApiRepository): ApiCombinedCommitStatus = ApiCombinedCommitStatus( - state = CommitState.combine(statuses.map(_._1.state).toSet).name, - sha = sha, - total_count= statuses.size, - statuses = statuses.map{ case (s, a)=> ApiCommitStatus(s, ApiUser(a)) }, - repository = repository) -} +package api + +import model.Account +import model.CommitStatus +import model.CommitState + +/** + * https://developer.github.com/v3/repos/statuses/#get-the-combined-status-for-a-specific-ref + */ +case class ApiCombinedCommitStatus( + state: String, + sha: String, + total_count: Int, + statuses: Iterable[ApiCommitStatus], + repository: ApiRepository){ + // val commit_url = ApiPath(s"/api/v3/repos/${repository.full_name}/${sha}") + val url = ApiPath(s"/api/v3/repos/${repository.full_name}/commits/${sha}/status") +} +object ApiCombinedCommitStatus { + def apply(sha:String, statuses: Iterable[(CommitStatus, Account)], repository:ApiRepository): ApiCombinedCommitStatus = ApiCombinedCommitStatus( + state = CommitState.combine(statuses.map(_._1.state).toSet).name, + sha = sha, + total_count= statuses.size, + statuses = statuses.map{ case (s, a)=> ApiCommitStatus(s, ApiUser(a)) }, + repository = repository) +} diff --git a/src/main/scala/api/ApiComment.scala b/src/main/scala/api/ApiComment.scala index 1733fb3..34197f0 100644 --- a/src/main/scala/api/ApiComment.scala +++ b/src/main/scala/api/ApiComment.scala @@ -1,24 +1,24 @@ -package api - -import java.util.Date -import model.IssueComment - -/** - * https://developer.github.com/v3/issues/comments/ - */ -case class ApiComment( - id: Int, - user: ApiUser, - body: String, - created_at: Date, - updated_at: Date) - -object ApiComment{ - def apply(comment: IssueComment, user: ApiUser): ApiComment = - ApiComment( - id = comment.commentId, - user = user, - body = comment.content, - created_at = comment.registeredDate, - updated_at = comment.updatedDate) -} +package api + +import java.util.Date +import model.IssueComment + +/** + * https://developer.github.com/v3/issues/comments/ + */ +case class ApiComment( + id: Int, + user: ApiUser, + body: String, + created_at: Date, + updated_at: Date) + +object ApiComment{ + def apply(comment: IssueComment, user: ApiUser): ApiComment = + ApiComment( + id = comment.commentId, + user = user, + body = comment.content, + created_at = comment.registeredDate, + updated_at = comment.updatedDate) +} diff --git a/src/main/scala/api/ApiCommit.scala b/src/main/scala/api/ApiCommit.scala index f4ef17a..57ee02d 100644 --- a/src/main/scala/api/ApiCommit.scala +++ b/src/main/scala/api/ApiCommit.scala @@ -1,41 +1,41 @@ -package api - -import java.util.Date -import org.eclipse.jgit.diff.DiffEntry -import util.JGitUtil -import util.JGitUtil.CommitInfo -import org.eclipse.jgit.api.Git -import util.RepositoryName - -/** - * https://developer.github.com/v3/repos/commits/ - */ -case class ApiCommit( - id: String, - message: String, - timestamp: Date, - added: List[String], - removed: List[String], - modified: List[String], - author: ApiPersonIdent, - committer: ApiPersonIdent)(repositoryName:RepositoryName){ - val url = ApiPath(s"/api/v3/${repositoryName.fullName}/commits/${id}") - val html_url = ApiPath(s"/${repositoryName.fullName}/commit/${id}") -} - -object ApiCommit{ - def apply(git: Git, repositoryName: RepositoryName, commit: CommitInfo): ApiCommit = { - val diffs = JGitUtil.getDiffs(git, commit.id, false) - ApiCommit( - id = commit.id, - message = commit.fullMessage, - timestamp = commit.commitTime, - added = diffs._1.collect { case x if(x.changeType == DiffEntry.ChangeType.ADD) => x.newPath }, - removed = diffs._1.collect { case x if(x.changeType == DiffEntry.ChangeType.DELETE) => x.oldPath }, - modified = diffs._1.collect { case x if(x.changeType != DiffEntry.ChangeType.ADD && - x.changeType != DiffEntry.ChangeType.DELETE) => x.newPath }, - author = ApiPersonIdent.author(commit), - committer = ApiPersonIdent.committer(commit) - )(repositoryName) - } -} +package api + +import java.util.Date +import org.eclipse.jgit.diff.DiffEntry +import util.JGitUtil +import util.JGitUtil.CommitInfo +import org.eclipse.jgit.api.Git +import util.RepositoryName + +/** + * https://developer.github.com/v3/repos/commits/ + */ +case class ApiCommit( + id: String, + message: String, + timestamp: Date, + added: List[String], + removed: List[String], + modified: List[String], + author: ApiPersonIdent, + committer: ApiPersonIdent)(repositoryName:RepositoryName){ + val url = ApiPath(s"/api/v3/${repositoryName.fullName}/commits/${id}") + val html_url = ApiPath(s"/${repositoryName.fullName}/commit/${id}") +} + +object ApiCommit{ + def apply(git: Git, repositoryName: RepositoryName, commit: CommitInfo): ApiCommit = { + val diffs = JGitUtil.getDiffs(git, commit.id, false) + ApiCommit( + id = commit.id, + message = commit.fullMessage, + timestamp = commit.commitTime, + added = diffs._1.collect { case x if(x.changeType == DiffEntry.ChangeType.ADD) => x.newPath }, + removed = diffs._1.collect { case x if(x.changeType == DiffEntry.ChangeType.DELETE) => x.oldPath }, + modified = diffs._1.collect { case x if(x.changeType != DiffEntry.ChangeType.ADD && + x.changeType != DiffEntry.ChangeType.DELETE) => x.newPath }, + author = ApiPersonIdent.author(commit), + committer = ApiPersonIdent.committer(commit) + )(repositoryName) + } +} diff --git a/src/main/scala/api/ApiCommitListItem.scala b/src/main/scala/api/ApiCommitListItem.scala index c345661..4a80d8c 100644 --- a/src/main/scala/api/ApiCommitListItem.scala +++ b/src/main/scala/api/ApiCommitListItem.scala @@ -1,41 +1,41 @@ -package api - -import util.JGitUtil.CommitInfo -import ApiCommitListItem._ -import util.RepositoryName - -/** - * https://developer.github.com/v3/repos/commits/ - */ -case class ApiCommitListItem( - sha: String, - commit: Commit, - author: Option[ApiUser], - committer: Option[ApiUser], - parents: Seq[Parent])(repositoryName: RepositoryName) { - val url = ApiPath(s"/api/v3/repos/${repositoryName.fullName}/commits/${sha}") -} - -object ApiCommitListItem { - def apply(commit: CommitInfo, repositoryName: RepositoryName): ApiCommitListItem = ApiCommitListItem( - sha = commit.id, - commit = Commit( - message = commit.fullMessage, - author = ApiPersonIdent.author(commit), - committer = ApiPersonIdent.committer(commit) - )(commit.id, repositoryName), - author = None, - committer = None, - parents = commit.parents.map(Parent(_)(repositoryName)))(repositoryName) - - case class Parent(sha: String)(repositoryName: RepositoryName){ - val url = ApiPath(s"/api/v3/repos/${repositoryName.fullName}/commits/${sha}") - } - - case class Commit( - message: String, - author: ApiPersonIdent, - committer: ApiPersonIdent)(sha:String, repositoryName: RepositoryName) { - val url = ApiPath(s"/api/v3/repos/${repositoryName.fullName}/git/commits/${sha}") - } -} +package api + +import util.JGitUtil.CommitInfo +import ApiCommitListItem._ +import util.RepositoryName + +/** + * https://developer.github.com/v3/repos/commits/ + */ +case class ApiCommitListItem( + sha: String, + commit: Commit, + author: Option[ApiUser], + committer: Option[ApiUser], + parents: Seq[Parent])(repositoryName: RepositoryName) { + val url = ApiPath(s"/api/v3/repos/${repositoryName.fullName}/commits/${sha}") +} + +object ApiCommitListItem { + def apply(commit: CommitInfo, repositoryName: RepositoryName): ApiCommitListItem = ApiCommitListItem( + sha = commit.id, + commit = Commit( + message = commit.fullMessage, + author = ApiPersonIdent.author(commit), + committer = ApiPersonIdent.committer(commit) + )(commit.id, repositoryName), + author = None, + committer = None, + parents = commit.parents.map(Parent(_)(repositoryName)))(repositoryName) + + case class Parent(sha: String)(repositoryName: RepositoryName){ + val url = ApiPath(s"/api/v3/repos/${repositoryName.fullName}/commits/${sha}") + } + + case class Commit( + message: String, + author: ApiPersonIdent, + committer: ApiPersonIdent)(sha:String, repositoryName: RepositoryName) { + val url = ApiPath(s"/api/v3/repos/${repositoryName.fullName}/git/commits/${sha}") + } +} diff --git a/src/main/scala/api/ApiCommitStatus.scala b/src/main/scala/api/ApiCommitStatus.scala index e6e2ea1..011be26 100644 --- a/src/main/scala/api/ApiCommitStatus.scala +++ b/src/main/scala/api/ApiCommitStatus.scala @@ -1,35 +1,35 @@ -package api - -import java.util.Date -import model.CommitStatus -import util.RepositoryName - -/** - * https://developer.github.com/v3/repos/statuses/#create-a-status - * https://developer.github.com/v3/repos/statuses/#list-statuses-for-a-specific-ref - */ -case class ApiCommitStatus( - created_at: Date, - updated_at: Date, - state: String, - target_url: Option[String], - description: Option[String], - id: Int, - context: String, - creator: ApiUser -)(sha: String,repositoryName: RepositoryName) { - val url = ApiPath(s"/api/v3/repos/${repositoryName.fullName}/commits/${sha}/statuses") -} - -object ApiCommitStatus { - def apply(status: CommitStatus, creator:ApiUser): ApiCommitStatus = ApiCommitStatus( - created_at = status.registeredDate, - updated_at = status.updatedDate, - state = status.state.name, - target_url = status.targetUrl, - description= status.description, - id = status.commitStatusId, - context = status.context, - creator = creator - )(status.commitId, RepositoryName(status)) -} +package api + +import java.util.Date +import model.CommitStatus +import util.RepositoryName + +/** + * https://developer.github.com/v3/repos/statuses/#create-a-status + * https://developer.github.com/v3/repos/statuses/#list-statuses-for-a-specific-ref + */ +case class ApiCommitStatus( + created_at: Date, + updated_at: Date, + state: String, + target_url: Option[String], + description: Option[String], + id: Int, + context: String, + creator: ApiUser +)(sha: String,repositoryName: RepositoryName) { + val url = ApiPath(s"/api/v3/repos/${repositoryName.fullName}/commits/${sha}/statuses") +} + +object ApiCommitStatus { + def apply(status: CommitStatus, creator:ApiUser): ApiCommitStatus = ApiCommitStatus( + created_at = status.registeredDate, + updated_at = status.updatedDate, + state = status.state.name, + target_url = status.targetUrl, + description= status.description, + id = status.commitStatusId, + context = status.context, + creator = creator + )(status.commitId, RepositoryName(status)) +} diff --git a/src/main/scala/api/ApiError.scala b/src/main/scala/api/ApiError.scala index d0470dc..8acdba2 100644 --- a/src/main/scala/api/ApiError.scala +++ b/src/main/scala/api/ApiError.scala @@ -1,5 +1,5 @@ -package api - -case class ApiError( - message: String, - documentation_url: Option[String] = None) +package api + +case class ApiError( + message: String, + documentation_url: Option[String] = None) diff --git a/src/main/scala/api/ApiIssue.scala b/src/main/scala/api/ApiIssue.scala index 6c31d6a..1bbb55a 100644 --- a/src/main/scala/api/ApiIssue.scala +++ b/src/main/scala/api/ApiIssue.scala @@ -1,29 +1,29 @@ -package api - -import java.util.Date -import model.Issue - -/** - * https://developer.github.com/v3/issues/ - */ -case class ApiIssue( - number: Int, - title: String, - user: ApiUser, - // labels, - state: String, - created_at: Date, - updated_at: Date, - body: String) - -object ApiIssue{ - def apply(issue: Issue, user: ApiUser): ApiIssue = - ApiIssue( - number = issue.issueId, - title = issue.title, - user = user, - state = if(issue.closed){ "closed" }else{ "open" }, - body = issue.content.getOrElse(""), - created_at = issue.registeredDate, - updated_at = issue.updatedDate) -} +package api + +import java.util.Date +import model.Issue + +/** + * https://developer.github.com/v3/issues/ + */ +case class ApiIssue( + number: Int, + title: String, + user: ApiUser, + // labels, + state: String, + created_at: Date, + updated_at: Date, + body: String) + +object ApiIssue{ + def apply(issue: Issue, user: ApiUser): ApiIssue = + ApiIssue( + number = issue.issueId, + title = issue.title, + user = user, + state = if(issue.closed){ "closed" }else{ "open" }, + body = issue.content.getOrElse(""), + created_at = issue.registeredDate, + updated_at = issue.updatedDate) +} diff --git a/src/main/scala/api/ApiPath.scala b/src/main/scala/api/ApiPath.scala index 2572945..1f6701e 100644 --- a/src/main/scala/api/ApiPath.scala +++ b/src/main/scala/api/ApiPath.scala @@ -1,6 +1,6 @@ -package api - -/** - * path for api url. if set path '/repos/aa/bb' then, expand 'http://server:post/repos/aa/bb' when converted to json. - */ -case class ApiPath(path: String) +package api + +/** + * path for api url. if set path '/repos/aa/bb' then, expand 'http://server:post/repos/aa/bb' when converted to json. + */ +case class ApiPath(path: String) diff --git a/src/main/scala/api/ApiPersonIdent.scala b/src/main/scala/api/ApiPersonIdent.scala index c9b3b97..010f539 100644 --- a/src/main/scala/api/ApiPersonIdent.scala +++ b/src/main/scala/api/ApiPersonIdent.scala @@ -1,22 +1,22 @@ -package api - -import java.util.Date -import util.JGitUtil.CommitInfo - -case class ApiPersonIdent( - name: String, - email: String, - date: Date) - -object ApiPersonIdent { - def author(commit: CommitInfo): ApiPersonIdent = - ApiPersonIdent( - name = commit.authorName, - email = commit.authorEmailAddress, - date = commit.authorTime) - def committer(commit: CommitInfo): ApiPersonIdent = - ApiPersonIdent( - name = commit.committerName, - email = commit.committerEmailAddress, - date = commit.commitTime) -} +package api + +import java.util.Date +import util.JGitUtil.CommitInfo + +case class ApiPersonIdent( + name: String, + email: String, + date: Date) + +object ApiPersonIdent { + def author(commit: CommitInfo): ApiPersonIdent = + ApiPersonIdent( + name = commit.authorName, + email = commit.authorEmailAddress, + date = commit.authorTime) + def committer(commit: CommitInfo): ApiPersonIdent = + ApiPersonIdent( + name = commit.committerName, + email = commit.committerEmailAddress, + date = commit.commitTime) +} diff --git a/src/main/scala/api/ApiPullRequest.scala b/src/main/scala/api/ApiPullRequest.scala index 975f562..7ce6f6d 100644 --- a/src/main/scala/api/ApiPullRequest.scala +++ b/src/main/scala/api/ApiPullRequest.scala @@ -1,58 +1,58 @@ -package api - -import java.util.Date -import model.{Issue, PullRequest} -import ApiPullRequest._ - -/** - * https://developer.github.com/v3/pulls/ - */ -case class ApiPullRequest( - number: Int, - updated_at: Date, - created_at: Date, - head: ApiPullRequest.Commit, - base: ApiPullRequest.Commit, - mergeable: Option[Boolean], - title: String, - body: String, - user: ApiUser) { - val html_url = ApiPath(s"${base.repo.html_url.path}/pull/${number}") - //val diff_url = ApiPath(s"${base.repo.html_url.path}/pull/${number}.diff") - //val patch_url = ApiPath(s"${base.repo.html_url.path}/pull/${number}.patch") - val url = ApiPath(s"${base.repo.url.path}/pulls/${number}") - //val issue_url = ApiPath(s"${base.repo.url.path}/issues/${number}") - val commits_url = ApiPath(s"${base.repo.url.path}/pulls/${number}/commits") - val review_comments_url = ApiPath(s"${base.repo.url.path}/pulls/${number}/comments") - val review_comment_url = ApiPath(s"${base.repo.url.path}/pulls/comments/{number}") - val comments_url = ApiPath(s"${base.repo.url.path}/issues/${number}/comments") - val statuses_url = ApiPath(s"${base.repo.url.path}/statuses/${head.sha}") -} - -object ApiPullRequest{ - def apply(issue: Issue, pullRequest: PullRequest, headRepo: ApiRepository, baseRepo: ApiRepository, user: ApiUser): ApiPullRequest = ApiPullRequest( - number = issue.issueId, - updated_at = issue.updatedDate, - created_at = issue.registeredDate, - head = Commit( - sha = pullRequest.commitIdTo, - ref = pullRequest.requestBranch, - repo = headRepo)(issue.userName), - base = Commit( - sha = pullRequest.commitIdFrom, - ref = pullRequest.branch, - repo = baseRepo)(issue.userName), - mergeable = None, // TODO: need check mergeable. - title = issue.title, - body = issue.content.getOrElse(""), - user = user - ) - - case class Commit( - sha: String, - ref: String, - repo: ApiRepository)(baseOwner:String){ - val label = if( baseOwner == repo.owner.login ){ ref }else{ s"${repo.owner.login}:${ref}" } - val user = repo.owner - } -} +package api + +import java.util.Date +import model.{Issue, PullRequest} +import ApiPullRequest._ + +/** + * https://developer.github.com/v3/pulls/ + */ +case class ApiPullRequest( + number: Int, + updated_at: Date, + created_at: Date, + head: ApiPullRequest.Commit, + base: ApiPullRequest.Commit, + mergeable: Option[Boolean], + title: String, + body: String, + user: ApiUser) { + val html_url = ApiPath(s"${base.repo.html_url.path}/pull/${number}") + //val diff_url = ApiPath(s"${base.repo.html_url.path}/pull/${number}.diff") + //val patch_url = ApiPath(s"${base.repo.html_url.path}/pull/${number}.patch") + val url = ApiPath(s"${base.repo.url.path}/pulls/${number}") + //val issue_url = ApiPath(s"${base.repo.url.path}/issues/${number}") + val commits_url = ApiPath(s"${base.repo.url.path}/pulls/${number}/commits") + val review_comments_url = ApiPath(s"${base.repo.url.path}/pulls/${number}/comments") + val review_comment_url = ApiPath(s"${base.repo.url.path}/pulls/comments/{number}") + val comments_url = ApiPath(s"${base.repo.url.path}/issues/${number}/comments") + val statuses_url = ApiPath(s"${base.repo.url.path}/statuses/${head.sha}") +} + +object ApiPullRequest{ + def apply(issue: Issue, pullRequest: PullRequest, headRepo: ApiRepository, baseRepo: ApiRepository, user: ApiUser): ApiPullRequest = ApiPullRequest( + number = issue.issueId, + updated_at = issue.updatedDate, + created_at = issue.registeredDate, + head = Commit( + sha = pullRequest.commitIdTo, + ref = pullRequest.requestBranch, + repo = headRepo)(issue.userName), + base = Commit( + sha = pullRequest.commitIdFrom, + ref = pullRequest.branch, + repo = baseRepo)(issue.userName), + mergeable = None, // TODO: need check mergeable. + title = issue.title, + body = issue.content.getOrElse(""), + user = user + ) + + case class Commit( + sha: String, + ref: String, + repo: ApiRepository)(baseOwner:String){ + val label = if( baseOwner == repo.owner.login ){ ref }else{ s"${repo.owner.login}:${ref}" } + val user = repo.owner + } +} diff --git a/src/main/scala/api/ApiRepository.scala b/src/main/scala/api/ApiRepository.scala index 05949b8..1962e47 100644 --- a/src/main/scala/api/ApiRepository.scala +++ b/src/main/scala/api/ApiRepository.scala @@ -1,48 +1,48 @@ -package api - -import util.JGitUtil.CommitInfo -import service.RepositoryService.RepositoryInfo -import model.{Account, Repository} - -// https://developer.github.com/v3/repos/ -case class ApiRepository( - name: String, - full_name: String, - description: String, - watchers: Int, - forks: Int, - `private`: Boolean, - default_branch: String, - owner: ApiUser) { - val forks_count = forks - val watchers_coun = watchers - val url = ApiPath(s"/api/v3/repos/${full_name}") - val http_url = ApiPath(s"/git/${full_name}.git") - val clone_url = ApiPath(s"/git/${full_name}.git") - val html_url = ApiPath(s"/${full_name}") -} - -object ApiRepository{ - def apply( - repository: Repository, - owner: ApiUser, - forkedCount: Int =0, - watchers: Int = 0): ApiRepository = - ApiRepository( - name = repository.repositoryName, - full_name = s"${repository.userName}/${repository.repositoryName}", - description = repository.description.getOrElse(""), - watchers = 0, - forks = forkedCount, - `private` = repository.isPrivate, - default_branch = repository.defaultBranch, - owner = owner - ) - - def apply(repositoryInfo: RepositoryInfo, owner: ApiUser): ApiRepository = - ApiRepository(repositoryInfo.repository, owner, forkedCount=repositoryInfo.forkedCount) - - def apply(repositoryInfo: RepositoryInfo, owner: Account): ApiRepository = - this(repositoryInfo.repository, ApiUser(owner)) - -} +package api + +import util.JGitUtil.CommitInfo +import service.RepositoryService.RepositoryInfo +import model.{Account, Repository} + +// https://developer.github.com/v3/repos/ +case class ApiRepository( + name: String, + full_name: String, + description: String, + watchers: Int, + forks: Int, + `private`: Boolean, + default_branch: String, + owner: ApiUser) { + val forks_count = forks + val watchers_coun = watchers + val url = ApiPath(s"/api/v3/repos/${full_name}") + val http_url = ApiPath(s"/git/${full_name}.git") + val clone_url = ApiPath(s"/git/${full_name}.git") + val html_url = ApiPath(s"/${full_name}") +} + +object ApiRepository{ + def apply( + repository: Repository, + owner: ApiUser, + forkedCount: Int =0, + watchers: Int = 0): ApiRepository = + ApiRepository( + name = repository.repositoryName, + full_name = s"${repository.userName}/${repository.repositoryName}", + description = repository.description.getOrElse(""), + watchers = 0, + forks = forkedCount, + `private` = repository.isPrivate, + default_branch = repository.defaultBranch, + owner = owner + ) + + def apply(repositoryInfo: RepositoryInfo, owner: ApiUser): ApiRepository = + ApiRepository(repositoryInfo.repository, owner, forkedCount=repositoryInfo.forkedCount) + + def apply(repositoryInfo: RepositoryInfo, owner: Account): ApiRepository = + this(repositoryInfo.repository, ApiUser(owner)) + +} diff --git a/src/main/scala/api/ApiUser.scala b/src/main/scala/api/ApiUser.scala index 5cbc326..f180a9d 100644 --- a/src/main/scala/api/ApiUser.scala +++ b/src/main/scala/api/ApiUser.scala @@ -1,33 +1,33 @@ -package api - -import java.util.Date -import model.Account - -case class ApiUser( - login: String, - email: String, - `type`: String, - site_admin: Boolean, - created_at: Date) { - val url = ApiPath(s"/api/v3/users/${login}") - val html_url = ApiPath(s"/${login}") - // 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}") - // val starred_url = ApiPath(s"/api/v3/users/${login}/starred{/owner}{/repo}") - // val subscriptions_url = ApiPath(s"/api/v3/users/${login}/subscriptions") - // val organizations_url = ApiPath(s"/api/v3/users/${login}/orgs") - // val repos_url = ApiPath(s"/api/v3/users/${login}/repos") - // val events_url = ApiPath(s"/api/v3/users/${login}/events{/privacy}") - // val received_events_url = ApiPath(s"/api/v3/users/${login}/received_events") -} - -object ApiUser{ - def apply(user: Account): ApiUser = ApiUser( - login = user.fullName, - email = user.mailAddress, - `type` = if(user.isGroupAccount){ "Organization" }else{ "User" }, - site_admin = user.isAdmin, - created_at = user.registeredDate - ) -} +package api + +import java.util.Date +import model.Account + +case class ApiUser( + login: String, + email: String, + `type`: String, + site_admin: Boolean, + created_at: Date) { + val url = ApiPath(s"/api/v3/users/${login}") + val html_url = ApiPath(s"/${login}") + // 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}") + // val starred_url = ApiPath(s"/api/v3/users/${login}/starred{/owner}{/repo}") + // val subscriptions_url = ApiPath(s"/api/v3/users/${login}/subscriptions") + // val organizations_url = ApiPath(s"/api/v3/users/${login}/orgs") + // val repos_url = ApiPath(s"/api/v3/users/${login}/repos") + // val events_url = ApiPath(s"/api/v3/users/${login}/events{/privacy}") + // val received_events_url = ApiPath(s"/api/v3/users/${login}/received_events") +} + +object ApiUser{ + def apply(user: Account): ApiUser = ApiUser( + login = user.fullName, + email = user.mailAddress, + `type` = if(user.isGroupAccount){ "Organization" }else{ "User" }, + site_admin = user.isAdmin, + created_at = user.registeredDate + ) +} diff --git a/src/main/scala/api/CreateAComment.scala b/src/main/scala/api/CreateAComment.scala index 733758d..138f705 100644 --- a/src/main/scala/api/CreateAComment.scala +++ b/src/main/scala/api/CreateAComment.scala @@ -1,7 +1,7 @@ -package api - -/** - * https://developer.github.com/v3/issues/comments/#create-a-comment - * api form - */ -case class CreateAComment(body: String) +package api + +/** + * https://developer.github.com/v3/issues/comments/#create-a-comment + * api form + */ +case class CreateAComment(body: String) diff --git a/src/main/scala/api/CreateAStatus.scala b/src/main/scala/api/CreateAStatus.scala index 5237cac..51b82a2 100644 --- a/src/main/scala/api/CreateAStatus.scala +++ b/src/main/scala/api/CreateAStatus.scala @@ -1,26 +1,26 @@ -package api - -import model.CommitState - -/** - * https://developer.github.com/v3/repos/statuses/#create-a-status - * api form - */ -case class CreateAStatus( - /* state is Required. The state of the status. Can be one of pending, success, error, or failure. */ - state: String, - /* context is a string label to differentiate this status from the status of other systems. Default: "default" */ - context: Option[String], - /* The target URL to associate with this status. This URL will be linked from the GitHub UI to allow users to easily see the ‘source’ of the Status. */ - target_url: Option[String], - /* description is a short description of the status.*/ - description: Option[String] -) { - def isValid: Boolean = { - CommitState.valueOf(state).isDefined && - // only http - target_url.filterNot(f => "\\Ahttps?://".r.findPrefixOf(f).isDefined && f.length<255).isEmpty && - context.filterNot(f => f.length<255).isEmpty && - description.filterNot(f => f.length<1000).isEmpty - } -} +package api + +import model.CommitState + +/** + * https://developer.github.com/v3/repos/statuses/#create-a-status + * api form + */ +case class CreateAStatus( + /* state is Required. The state of the status. Can be one of pending, success, error, or failure. */ + state: String, + /* context is a string label to differentiate this status from the status of other systems. Default: "default" */ + context: Option[String], + /* The target URL to associate with this status. This URL will be linked from the GitHub UI to allow users to easily see the ‘source’ of the Status. */ + target_url: Option[String], + /* description is a short description of the status.*/ + description: Option[String] +) { + def isValid: Boolean = { + CommitState.valueOf(state).isDefined && + // only http + target_url.filterNot(f => "\\Ahttps?://".r.findPrefixOf(f).isDefined && f.length<255).isEmpty && + context.filterNot(f => f.length<255).isEmpty && + description.filterNot(f => f.length<1000).isEmpty + } +} diff --git a/src/main/scala/api/JsonFormat.scala b/src/main/scala/api/JsonFormat.scala index f743534..385a24c 100644 --- a/src/main/scala/api/JsonFormat.scala +++ b/src/main/scala/api/JsonFormat.scala @@ -1,37 +1,37 @@ -package api -import org.json4s._ -import org.json4s.jackson.Serialization -import scala.util.Try -import org.joda.time.format._ -import org.joda.time.DateTime -import org.joda.time.DateTimeZone -import java.util.Date -object JsonFormat { - case class Context(baseUrl:String) - val parserISO = DateTimeFormat.forPattern("yyyy-MM-dd'T'HH:mm:ss'Z'") - val jsonFormats = Serialization.formats(NoTypeHints) + new CustomSerializer[Date](format => - ( - { case JString(s) => Try(parserISO.parseDateTime(s)).toOption.map(_.toDate) - .getOrElse(throw new MappingException("Can't convert " + s + " to Date")) }, - { case x: Date => JString(parserISO.print(new DateTime(x).withZone(DateTimeZone.UTC))) } - ) - ) + FieldSerializer[ApiUser]() + FieldSerializer[ApiPullRequest]() + FieldSerializer[ApiRepository]() + - FieldSerializer[ApiCommitListItem.Parent]() + FieldSerializer[ApiCommitListItem]() + FieldSerializer[ApiCommitListItem.Commit]() + - FieldSerializer[ApiCommitStatus]() + FieldSerializer[ApiCommit]() + FieldSerializer[ApiCombinedCommitStatus]() + - FieldSerializer[ApiPullRequest.Commit]() - def apiPathSerializer(c: Context) = new CustomSerializer[ApiPath](format => - ( - { - case JString(s) if s.startsWith(c.baseUrl) => ApiPath(s.substring(c.baseUrl.length)) - case JString(s) => throw new MappingException("Can't convert " + s + " to ApiPath") - }, - { - case ApiPath(path) => JString(c.baseUrl+path) - } - ) - ) - /** - * convert object to json string - */ - def apply(obj: AnyRef)(implicit c: Context): String = Serialization.write(obj)(jsonFormats + apiPathSerializer(c)) -} +package api +import org.json4s._ +import org.json4s.jackson.Serialization +import scala.util.Try +import org.joda.time.format._ +import org.joda.time.DateTime +import org.joda.time.DateTimeZone +import java.util.Date +object JsonFormat { + case class Context(baseUrl:String) + val parserISO = DateTimeFormat.forPattern("yyyy-MM-dd'T'HH:mm:ss'Z'") + val jsonFormats = Serialization.formats(NoTypeHints) + new CustomSerializer[Date](format => + ( + { case JString(s) => Try(parserISO.parseDateTime(s)).toOption.map(_.toDate) + .getOrElse(throw new MappingException("Can't convert " + s + " to Date")) }, + { case x: Date => JString(parserISO.print(new DateTime(x).withZone(DateTimeZone.UTC))) } + ) + ) + FieldSerializer[ApiUser]() + FieldSerializer[ApiPullRequest]() + FieldSerializer[ApiRepository]() + + FieldSerializer[ApiCommitListItem.Parent]() + FieldSerializer[ApiCommitListItem]() + FieldSerializer[ApiCommitListItem.Commit]() + + FieldSerializer[ApiCommitStatus]() + FieldSerializer[ApiCommit]() + FieldSerializer[ApiCombinedCommitStatus]() + + FieldSerializer[ApiPullRequest.Commit]() + def apiPathSerializer(c: Context) = new CustomSerializer[ApiPath](format => + ( + { + case JString(s) if s.startsWith(c.baseUrl) => ApiPath(s.substring(c.baseUrl.length)) + case JString(s) => throw new MappingException("Can't convert " + s + " to ApiPath") + }, + { + case ApiPath(path) => JString(c.baseUrl+path) + } + ) + ) + /** + * convert object to json string + */ + def apply(obj: AnyRef)(implicit c: Context): String = Serialization.write(obj)(jsonFormats + apiPathSerializer(c)) +} diff --git a/src/main/scala/model/AccessToken.scala b/src/main/scala/model/AccessToken.scala index acaad56..2695c2f 100644 --- a/src/main/scala/model/AccessToken.scala +++ b/src/main/scala/model/AccessToken.scala @@ -1,20 +1,20 @@ -package model - -trait AccessTokenComponent { self: Profile => - import profile.simple._ - lazy val AccessTokens = TableQuery[AccessTokens] - - class AccessTokens(tag: Tag) extends Table[AccessToken](tag, "ACCESS_TOKEN") { - val accessTokenId = column[Int]("ACCESS_TOKEN_ID", O AutoInc) - val userName = column[String]("USER_NAME") - val tokenHash = column[String]("TOKEN_HASH") - val note = column[String]("NOTE") - def * = (accessTokenId, userName, tokenHash, note) <> (AccessToken.tupled, AccessToken.unapply) - } -} -case class AccessToken( - accessTokenId: Int = 0, - userName: String, - tokenHash: String, - note: String -) +package model + +trait AccessTokenComponent { self: Profile => + import profile.simple._ + lazy val AccessTokens = TableQuery[AccessTokens] + + class AccessTokens(tag: Tag) extends Table[AccessToken](tag, "ACCESS_TOKEN") { + val accessTokenId = column[Int]("ACCESS_TOKEN_ID", O AutoInc) + val userName = column[String]("USER_NAME") + val tokenHash = column[String]("TOKEN_HASH") + val note = column[String]("NOTE") + def * = (accessTokenId, userName, tokenHash, note) <> (AccessToken.tupled, AccessToken.unapply) + } +} +case class AccessToken( + accessTokenId: Int = 0, + userName: String, + tokenHash: String, + note: String +) diff --git a/src/main/scala/model/CommitStatus.scala b/src/main/scala/model/CommitStatus.scala index 2977b26..47a2343 100644 --- a/src/main/scala/model/CommitStatus.scala +++ b/src/main/scala/model/CommitStatus.scala @@ -1,71 +1,71 @@ -package model - -import scala.slick.lifted.MappedTo -import scala.slick.jdbc._ - -trait CommitStatusComponent extends TemplateComponent { self: Profile => - import profile.simple._ - import self._ - - implicit val commitStateColumnType = MappedColumnType.base[CommitState, String](b => b.name , i => CommitState(i)) - - lazy val CommitStatuses = TableQuery[CommitStatuses] - class CommitStatuses(tag: Tag) extends Table[CommitStatus](tag, "COMMIT_STATUS") with CommitTemplate { - val commitStatusId = column[Int]("COMMIT_STATUS_ID", O AutoInc) - val context = column[String]("CONTEXT") - val state = column[CommitState]("STATE") - val targetUrl = column[Option[String]]("TARGET_URL") - val description = column[Option[String]]("DESCRIPTION") - val creator = column[String]("CREATOR") - val registeredDate = column[java.util.Date]("REGISTERED_DATE") - val updatedDate = column[java.util.Date]("UPDATED_DATE") - def * = (commitStatusId, userName, repositoryName, commitId, context, state, targetUrl, description, creator, registeredDate, updatedDate) <> (CommitStatus.tupled, CommitStatus.unapply) - def byPrimaryKey(id: Int) = commitStatusId === id.bind - } -} - -case class CommitStatus( - commitStatusId: Int = 0, - userName: String, - repositoryName: String, - commitId: String, - context: String, - state: CommitState, - targetUrl: Option[String], - description: Option[String], - creator: String, - registeredDate: java.util.Date, - updatedDate: java.util.Date -) -sealed abstract class CommitState(val name: String) -object CommitState { - object ERROR extends CommitState("error") - object FAILURE extends CommitState("failure") - object PENDING extends CommitState("pending") - object SUCCESS extends CommitState("success") - - val values: Vector[CommitState] = Vector(PENDING, SUCCESS, ERROR, FAILURE) - private val map: Map[String, CommitState] = values.map(enum => enum.name -> enum).toMap - def apply(name: String): CommitState = map(name) - def valueOf(name: String): Option[CommitState] = map.get(name) - - /** - * failure if any of the contexts report as error or failure - * pending if there are no statuses or a context is pending - * success if the latest status for all contexts is success - */ - def combine(statuses: Set[CommitState]): CommitState = { - if(statuses.isEmpty){ - PENDING - }else if(statuses.contains(CommitState.ERROR) || statuses.contains(CommitState.FAILURE)){ - FAILURE - }else if(statuses.contains(CommitState.PENDING)){ - PENDING - }else{ - SUCCESS - } - } - - implicit val getResult: GetResult[CommitState] = GetResult(r => CommitState(r.<<)) - implicit val getResultOpt: GetResult[Option[CommitState]] = GetResult(r => r.< + import profile.simple._ + import self._ + + implicit val commitStateColumnType = MappedColumnType.base[CommitState, String](b => b.name , i => CommitState(i)) + + lazy val CommitStatuses = TableQuery[CommitStatuses] + class CommitStatuses(tag: Tag) extends Table[CommitStatus](tag, "COMMIT_STATUS") with CommitTemplate { + val commitStatusId = column[Int]("COMMIT_STATUS_ID", O AutoInc) + val context = column[String]("CONTEXT") + val state = column[CommitState]("STATE") + val targetUrl = column[Option[String]]("TARGET_URL") + val description = column[Option[String]]("DESCRIPTION") + val creator = column[String]("CREATOR") + val registeredDate = column[java.util.Date]("REGISTERED_DATE") + val updatedDate = column[java.util.Date]("UPDATED_DATE") + def * = (commitStatusId, userName, repositoryName, commitId, context, state, targetUrl, description, creator, registeredDate, updatedDate) <> (CommitStatus.tupled, CommitStatus.unapply) + def byPrimaryKey(id: Int) = commitStatusId === id.bind + } +} + +case class CommitStatus( + commitStatusId: Int = 0, + userName: String, + repositoryName: String, + commitId: String, + context: String, + state: CommitState, + targetUrl: Option[String], + description: Option[String], + creator: String, + registeredDate: java.util.Date, + updatedDate: java.util.Date +) +sealed abstract class CommitState(val name: String) +object CommitState { + object ERROR extends CommitState("error") + object FAILURE extends CommitState("failure") + object PENDING extends CommitState("pending") + object SUCCESS extends CommitState("success") + + val values: Vector[CommitState] = Vector(PENDING, SUCCESS, ERROR, FAILURE) + private val map: Map[String, CommitState] = values.map(enum => enum.name -> enum).toMap + def apply(name: String): CommitState = map(name) + def valueOf(name: String): Option[CommitState] = map.get(name) + + /** + * failure if any of the contexts report as error or failure + * pending if there are no statuses or a context is pending + * success if the latest status for all contexts is success + */ + def combine(statuses: Set[CommitState]): CommitState = { + if(statuses.isEmpty){ + PENDING + }else if(statuses.contains(CommitState.ERROR) || statuses.contains(CommitState.FAILURE)){ + FAILURE + }else if(statuses.contains(CommitState.PENDING)){ + PENDING + }else{ + SUCCESS + } + } + + implicit val getResult: GetResult[CommitState] = GetResult(r => CommitState(r.<<)) + implicit val getResultOpt: GetResult[Option[CommitState]] = GetResult(r => r.< (ac.userName === t.userName) && (t.tokenHash === tokenToHash(token).bind) && (ac.removed === false.bind) } - .map{ case (ac, t) => ac } - .firstOption - - def getAccessTokens(userName: String)(implicit s: Session): List[AccessToken] = - AccessTokens.filter(_.userName === userName.bind).sortBy(_.accessTokenId.desc).list - - def deleteAccessToken(userName: String, accessTokenId: Int)(implicit s: Session): Unit = - AccessTokens filter (t => t.userName === userName.bind && t.accessTokenId === accessTokenId) delete - -} - -object AccessTokenService extends AccessTokenService +package service + +import model.Profile._ +import profile.simple._ +import model.{Account, AccessToken} +import util.StringUtil +import scala.util.Random + +trait AccessTokenService { + + def makeAccessTokenString: String = { + val bytes = new Array[Byte](20) + Random.nextBytes(bytes) + bytes.map("%02x".format(_)).mkString + } + + def tokenToHash(token: String): String = StringUtil.sha1(token) + + /** + * @retuen (TokenId, Token) + */ + def generateAccessToken(userName: String, note: String)(implicit s: Session): (Int, String) = { + var token: String = null + var hash: String = null + do{ + token = makeAccessTokenString + hash = tokenToHash(token) + }while(AccessTokens.filter(_.tokenHash === hash.bind).exists.run) + val newToken = AccessToken( + userName = userName, + note = note, + tokenHash = hash) + val tokenId = (AccessTokens returning AccessTokens.map(_.accessTokenId)) += newToken + (tokenId, token) + } + + def getAccountByAccessToken(token: String)(implicit s: Session): Option[Account] = + Accounts + .innerJoin(AccessTokens) + .filter{ case (ac, t) => (ac.userName === t.userName) && (t.tokenHash === tokenToHash(token).bind) && (ac.removed === false.bind) } + .map{ case (ac, t) => ac } + .firstOption + + def getAccessTokens(userName: String)(implicit s: Session): List[AccessToken] = + AccessTokens.filter(_.userName === userName.bind).sortBy(_.accessTokenId.desc).list + + def deleteAccessToken(userName: String, accessTokenId: Int)(implicit s: Session): Unit = + AccessTokens filter (t => t.userName === userName.bind && t.accessTokenId === accessTokenId) delete + +} + +object AccessTokenService extends AccessTokenService diff --git a/src/main/scala/service/CommitStatusService.scala b/src/main/scala/service/CommitStatusService.scala index fc05744..8860f77 100644 --- a/src/main/scala/service/CommitStatusService.scala +++ b/src/main/scala/service/CommitStatusService.scala @@ -1,50 +1,50 @@ -package service - -import model.Profile._ -import profile.simple._ -import model.{CommitState, CommitStatus, Account} -import util.Implicits._ -import util.StringUtil._ -import service.RepositoryService.RepositoryInfo - -trait CommitStatusService { - /** insert or update */ - def createCommitStatus(userName: String, repositoryName: String, sha:String, context:String, state:CommitState, targetUrl:Option[String], description:Option[String], now:java.util.Date, creator:Account)(implicit s: Session): Int = - CommitStatuses.filter(t => t.byCommit(userName, repositoryName, sha) && t.context===context.bind ) - .map(_.commitStatusId).firstOption match { - case Some(id:Int) => { - CommitStatuses.filter(_.byPrimaryKey(id)).map{ - t => (t.state , t.targetUrl , t.updatedDate , t.creator, t.description) - }.update( (state, targetUrl, now, creator.userName, description) ) - id - } - case None => (CommitStatuses returning CommitStatuses.map(_.commitStatusId)) += CommitStatus( - userName = userName, - repositoryName = repositoryName, - commitId = sha, - context = context, - state = state, - targetUrl = targetUrl, - description = description, - creator = creator.userName, - registeredDate = now, - updatedDate = now) - } - - def getCommitStatus(userName: String, repositoryName: String, id: Int)(implicit s: Session) :Option[CommitStatus] = - CommitStatuses.filter(t => t.byPrimaryKey(id) && t.byRepository(userName, repositoryName)).firstOption - - def getCommitStatus(userName: String, repositoryName: String, sha: String, context: String)(implicit s: Session) :Option[CommitStatus] = - CommitStatuses.filter(t => t.byCommit(userName, repositoryName, sha) && t.context===context.bind ).firstOption - - def getCommitStatues(userName: String, repositoryName: String, sha: String)(implicit s: Session) :List[CommitStatus] = - byCommitStatues(userName, repositoryName, sha).list - - def getCommitStatuesWithCreator(userName: String, repositoryName: String, sha: String)(implicit s: Session) :List[(CommitStatus, Account)] = - byCommitStatues(userName, repositoryName, sha).innerJoin(Accounts) - .filter{ case (t,a) => t.creator === a.userName }.list - - protected def byCommitStatues(userName: String, repositoryName: String, sha: String)(implicit s: Session) = - CommitStatuses.filter(t => t.byCommit(userName, repositoryName, sha) ).sortBy(_.updatedDate desc) - +package service + +import model.Profile._ +import profile.simple._ +import model.{CommitState, CommitStatus, Account} +import util.Implicits._ +import util.StringUtil._ +import service.RepositoryService.RepositoryInfo + +trait CommitStatusService { + /** insert or update */ + def createCommitStatus(userName: String, repositoryName: String, sha:String, context:String, state:CommitState, targetUrl:Option[String], description:Option[String], now:java.util.Date, creator:Account)(implicit s: Session): Int = + CommitStatuses.filter(t => t.byCommit(userName, repositoryName, sha) && t.context===context.bind ) + .map(_.commitStatusId).firstOption match { + case Some(id:Int) => { + CommitStatuses.filter(_.byPrimaryKey(id)).map{ + t => (t.state , t.targetUrl , t.updatedDate , t.creator, t.description) + }.update( (state, targetUrl, now, creator.userName, description) ) + id + } + case None => (CommitStatuses returning CommitStatuses.map(_.commitStatusId)) += CommitStatus( + userName = userName, + repositoryName = repositoryName, + commitId = sha, + context = context, + state = state, + targetUrl = targetUrl, + description = description, + creator = creator.userName, + registeredDate = now, + updatedDate = now) + } + + def getCommitStatus(userName: String, repositoryName: String, id: Int)(implicit s: Session) :Option[CommitStatus] = + CommitStatuses.filter(t => t.byPrimaryKey(id) && t.byRepository(userName, repositoryName)).firstOption + + def getCommitStatus(userName: String, repositoryName: String, sha: String, context: String)(implicit s: Session) :Option[CommitStatus] = + CommitStatuses.filter(t => t.byCommit(userName, repositoryName, sha) && t.context===context.bind ).firstOption + + def getCommitStatues(userName: String, repositoryName: String, sha: String)(implicit s: Session) :List[CommitStatus] = + byCommitStatues(userName, repositoryName, sha).list + + def getCommitStatuesWithCreator(userName: String, repositoryName: String, sha: String)(implicit s: Session) :List[(CommitStatus, Account)] = + byCommitStatues(userName, repositoryName, sha).innerJoin(Accounts) + .filter{ case (t,a) => t.creator === a.userName }.list + + protected def byCommitStatues(userName: String, repositoryName: String, sha: String)(implicit s: Session) = + CommitStatuses.filter(t => t.byCommit(userName, repositoryName, sha) ).sortBy(_.updatedDate desc) + } \ No newline at end of file diff --git a/src/main/scala/service/MergeService.scala b/src/main/scala/service/MergeService.scala index 1b7d81a..b2168ac 100644 --- a/src/main/scala/service/MergeService.scala +++ b/src/main/scala/service/MergeService.scala @@ -1,168 +1,168 @@ -package service -import util.LockUtil -import util.Directory._ -import util.Implicits._ -import util.ControlUtil._ -import org.eclipse.jgit.merge.MergeStrategy -import org.eclipse.jgit.api.Git -import org.eclipse.jgit.transport.RefSpec -import org.eclipse.jgit.errors.NoMergeBaseException -import org.eclipse.jgit.lib.{ObjectId, CommitBuilder, PersonIdent} -import model.Account -import org.eclipse.jgit.revwalk.RevWalk -trait MergeService { - import MergeService._ - /** - * Checks whether conflict will be caused in merging within pull request. - * Returns true if conflict will be caused. - */ - def checkConflict(userName: String, repositoryName: String, branch: String, issueId: Int): Boolean = { - using(Git.open(getRepositoryDir(userName, repositoryName))) { git => - MergeCacheInfo(git, branch, issueId).checkConflict() - } - } - /** - * Checks whether conflict will be caused in merging within pull request. - * only cache check. - * Returns Some(true) if conflict will be caused. - * Returns None if cache has not created yet. - */ - def checkConflictCache(userName: String, repositoryName: String, branch: String, issueId: Int): Option[Boolean] = { - using(Git.open(getRepositoryDir(userName, repositoryName))) { git => - MergeCacheInfo(git, branch, issueId).checkConflictCache() - } - } - /** merge pull request */ - def mergePullRequest(git:Git, branch: String, issueId: Int, message:String, committer:PersonIdent): Unit = { - MergeCacheInfo(git, branch, issueId).merge(message, committer) - } - /** fetch remote branch to my repository refs/pull/{issueId}/head */ - def fetchAsPullRequest(userName: String, repositoryName: String, requestUserName: String, requestRepositoryName: String, requestBranch:String, issueId:Int){ - using(Git.open(getRepositoryDir(userName, repositoryName))){ git => - git.fetch - .setRemote(getRepositoryDir(requestUserName, requestRepositoryName).toURI.toString) - .setRefSpecs(new RefSpec(s"refs/heads/${requestBranch}:refs/pull/${issueId}/head")) - .call - } - } - /** - * Checks whether conflict will be caused in merging. Returns true if conflict will be caused. - */ - def checkConflict(userName: String, repositoryName: String, branch: String, - requestUserName: String, requestRepositoryName: String, requestBranch: String): Boolean = { - using(Git.open(getRepositoryDir(requestUserName, requestRepositoryName))) { git => - val remoteRefName = s"refs/heads/${branch}" - val tmpRefName = s"refs/merge-check/${userName}/${branch}" - val refSpec = new RefSpec(s"${remoteRefName}:${tmpRefName}").setForceUpdate(true) - try { - // fetch objects from origin repository branch - git.fetch - .setRemote(getRepositoryDir(userName, repositoryName).toURI.toString) - .setRefSpecs(refSpec) - .call - // merge conflict check - val merger = MergeStrategy.RECURSIVE.newMerger(git.getRepository, true) - val mergeBaseTip = git.getRepository.resolve(s"refs/heads/${requestBranch}") - val mergeTip = git.getRepository.resolve(tmpRefName) - try { - !merger.merge(mergeBaseTip, mergeTip) - } catch { - case e: NoMergeBaseException => true - } - } finally { - val refUpdate = git.getRepository.updateRef(refSpec.getDestination) - refUpdate.setForceUpdate(true) - refUpdate.delete() - } - } - } -} -object MergeService{ - case class MergeCacheInfo(git:Git, branch:String, issueId:Int){ - val repository = git.getRepository - val mergedBranchName = s"refs/pull/${issueId}/merge" - val conflictedBranchName = s"refs/pull/${issueId}/conflict" - lazy val mergeBaseTip = repository.resolve(s"refs/heads/${branch}") - lazy val mergeTip = repository.resolve(s"refs/pull/${issueId}/head") - def checkConflictCache(): Option[Boolean] = { - Option(repository.resolve(mergedBranchName)).flatMap{ merged => - if(parseCommit( merged ).getParents().toSet == Set( mergeBaseTip, mergeTip )){ - // merged branch exists - Some(false) - }else{ - None - } - }.orElse(Option(repository.resolve(conflictedBranchName)).flatMap{ conflicted => - if(parseCommit( conflicted ).getParents().toSet == Set( mergeBaseTip, mergeTip )){ - // conflict branch exists - Some(true) - }else{ - None - } - }) - } - def checkConflict():Boolean ={ - checkConflictCache.getOrElse(checkConflictForce) - } - def checkConflictForce():Boolean ={ - val merger = MergeStrategy.RECURSIVE.newMerger(repository, true) - val conflicted = try { - !merger.merge(mergeBaseTip, mergeTip) - } catch { - case e: NoMergeBaseException => true - } - val mergeTipCommit = using(new RevWalk( repository ))(_.parseCommit( mergeTip )) - val committer = mergeTipCommit.getCommitterIdent; - def updateBranch(treeId:ObjectId, message:String, branchName:String){ - // creates merge commit - val mergeCommitId = createMergeCommit(treeId, committer, message) - // update refs - val refUpdate = repository.updateRef(branchName) - refUpdate.setNewObjectId(mergeCommitId) - refUpdate.setForceUpdate(true) - refUpdate.setRefLogIdent(committer) - refUpdate.update() - } - if(!conflicted){ - updateBranch(merger.getResultTreeId, s"Merge ${mergeTip.name} into ${mergeBaseTip.name}", mergedBranchName) - git.branchDelete().setForce(true).setBranchNames(conflictedBranchName).call() - }else{ - updateBranch(mergeTipCommit.getTree().getId(), s"can't merge ${mergeTip.name} into ${mergeBaseTip.name}", conflictedBranchName) - git.branchDelete().setForce(true).setBranchNames(mergedBranchName).call() - } - conflicted - } - // update branch from cache - def merge(message:String, committer:PersonIdent) = { - if(checkConflict()){ - throw new RuntimeException("This pull request can't merge automatically.") - } - val mergeResultCommit = parseCommit( Option(repository.resolve(mergedBranchName)).getOrElse(throw new RuntimeException(s"not found branch ${mergedBranchName}")) ) - // creates merge commit - val mergeCommitId = createMergeCommit(mergeResultCommit.getTree().getId(), committer, message) - // update refs - val refUpdate = repository.updateRef(s"refs/heads/${branch}") - refUpdate.setNewObjectId(mergeCommitId) - refUpdate.setForceUpdate(false) - refUpdate.setRefLogIdent(committer) - refUpdate.setRefLogMessage("merged", true) - refUpdate.update() - } - // return treeId - private def createMergeCommit(treeId:ObjectId, committer:PersonIdent, message:String) = { - val mergeCommit = new CommitBuilder() - mergeCommit.setTreeId(treeId) - mergeCommit.setParentIds(Array[ObjectId](mergeBaseTip, mergeTip): _*) - mergeCommit.setAuthor(committer) - mergeCommit.setCommitter(committer) - mergeCommit.setMessage(message) - // insertObject and got mergeCommit Object Id - val inserter = repository.newObjectInserter - val mergeCommitId = inserter.insert(mergeCommit) - inserter.flush() - inserter.release() - mergeCommitId - } - private def parseCommit(id:ObjectId) = using(new RevWalk( repository ))(_.parseCommit(id)) - } +package service +import util.LockUtil +import util.Directory._ +import util.Implicits._ +import util.ControlUtil._ +import org.eclipse.jgit.merge.MergeStrategy +import org.eclipse.jgit.api.Git +import org.eclipse.jgit.transport.RefSpec +import org.eclipse.jgit.errors.NoMergeBaseException +import org.eclipse.jgit.lib.{ObjectId, CommitBuilder, PersonIdent} +import model.Account +import org.eclipse.jgit.revwalk.RevWalk +trait MergeService { + import MergeService._ + /** + * Checks whether conflict will be caused in merging within pull request. + * Returns true if conflict will be caused. + */ + def checkConflict(userName: String, repositoryName: String, branch: String, issueId: Int): Boolean = { + using(Git.open(getRepositoryDir(userName, repositoryName))) { git => + MergeCacheInfo(git, branch, issueId).checkConflict() + } + } + /** + * Checks whether conflict will be caused in merging within pull request. + * only cache check. + * Returns Some(true) if conflict will be caused. + * Returns None if cache has not created yet. + */ + def checkConflictCache(userName: String, repositoryName: String, branch: String, issueId: Int): Option[Boolean] = { + using(Git.open(getRepositoryDir(userName, repositoryName))) { git => + MergeCacheInfo(git, branch, issueId).checkConflictCache() + } + } + /** merge pull request */ + def mergePullRequest(git:Git, branch: String, issueId: Int, message:String, committer:PersonIdent): Unit = { + MergeCacheInfo(git, branch, issueId).merge(message, committer) + } + /** fetch remote branch to my repository refs/pull/{issueId}/head */ + def fetchAsPullRequest(userName: String, repositoryName: String, requestUserName: String, requestRepositoryName: String, requestBranch:String, issueId:Int){ + using(Git.open(getRepositoryDir(userName, repositoryName))){ git => + git.fetch + .setRemote(getRepositoryDir(requestUserName, requestRepositoryName).toURI.toString) + .setRefSpecs(new RefSpec(s"refs/heads/${requestBranch}:refs/pull/${issueId}/head")) + .call + } + } + /** + * Checks whether conflict will be caused in merging. Returns true if conflict will be caused. + */ + def checkConflict(userName: String, repositoryName: String, branch: String, + requestUserName: String, requestRepositoryName: String, requestBranch: String): Boolean = { + using(Git.open(getRepositoryDir(requestUserName, requestRepositoryName))) { git => + val remoteRefName = s"refs/heads/${branch}" + val tmpRefName = s"refs/merge-check/${userName}/${branch}" + val refSpec = new RefSpec(s"${remoteRefName}:${tmpRefName}").setForceUpdate(true) + try { + // fetch objects from origin repository branch + git.fetch + .setRemote(getRepositoryDir(userName, repositoryName).toURI.toString) + .setRefSpecs(refSpec) + .call + // merge conflict check + val merger = MergeStrategy.RECURSIVE.newMerger(git.getRepository, true) + val mergeBaseTip = git.getRepository.resolve(s"refs/heads/${requestBranch}") + val mergeTip = git.getRepository.resolve(tmpRefName) + try { + !merger.merge(mergeBaseTip, mergeTip) + } catch { + case e: NoMergeBaseException => true + } + } finally { + val refUpdate = git.getRepository.updateRef(refSpec.getDestination) + refUpdate.setForceUpdate(true) + refUpdate.delete() + } + } + } +} +object MergeService{ + case class MergeCacheInfo(git:Git, branch:String, issueId:Int){ + val repository = git.getRepository + val mergedBranchName = s"refs/pull/${issueId}/merge" + val conflictedBranchName = s"refs/pull/${issueId}/conflict" + lazy val mergeBaseTip = repository.resolve(s"refs/heads/${branch}") + lazy val mergeTip = repository.resolve(s"refs/pull/${issueId}/head") + def checkConflictCache(): Option[Boolean] = { + Option(repository.resolve(mergedBranchName)).flatMap{ merged => + if(parseCommit( merged ).getParents().toSet == Set( mergeBaseTip, mergeTip )){ + // merged branch exists + Some(false) + }else{ + None + } + }.orElse(Option(repository.resolve(conflictedBranchName)).flatMap{ conflicted => + if(parseCommit( conflicted ).getParents().toSet == Set( mergeBaseTip, mergeTip )){ + // conflict branch exists + Some(true) + }else{ + None + } + }) + } + def checkConflict():Boolean ={ + checkConflictCache.getOrElse(checkConflictForce) + } + def checkConflictForce():Boolean ={ + val merger = MergeStrategy.RECURSIVE.newMerger(repository, true) + val conflicted = try { + !merger.merge(mergeBaseTip, mergeTip) + } catch { + case e: NoMergeBaseException => true + } + val mergeTipCommit = using(new RevWalk( repository ))(_.parseCommit( mergeTip )) + val committer = mergeTipCommit.getCommitterIdent; + def updateBranch(treeId:ObjectId, message:String, branchName:String){ + // creates merge commit + val mergeCommitId = createMergeCommit(treeId, committer, message) + // update refs + val refUpdate = repository.updateRef(branchName) + refUpdate.setNewObjectId(mergeCommitId) + refUpdate.setForceUpdate(true) + refUpdate.setRefLogIdent(committer) + refUpdate.update() + } + if(!conflicted){ + updateBranch(merger.getResultTreeId, s"Merge ${mergeTip.name} into ${mergeBaseTip.name}", mergedBranchName) + git.branchDelete().setForce(true).setBranchNames(conflictedBranchName).call() + }else{ + updateBranch(mergeTipCommit.getTree().getId(), s"can't merge ${mergeTip.name} into ${mergeBaseTip.name}", conflictedBranchName) + git.branchDelete().setForce(true).setBranchNames(mergedBranchName).call() + } + conflicted + } + // update branch from cache + def merge(message:String, committer:PersonIdent) = { + if(checkConflict()){ + throw new RuntimeException("This pull request can't merge automatically.") + } + val mergeResultCommit = parseCommit( Option(repository.resolve(mergedBranchName)).getOrElse(throw new RuntimeException(s"not found branch ${mergedBranchName}")) ) + // creates merge commit + val mergeCommitId = createMergeCommit(mergeResultCommit.getTree().getId(), committer, message) + // update refs + val refUpdate = repository.updateRef(s"refs/heads/${branch}") + refUpdate.setNewObjectId(mergeCommitId) + refUpdate.setForceUpdate(false) + refUpdate.setRefLogIdent(committer) + refUpdate.setRefLogMessage("merged", true) + refUpdate.update() + } + // return treeId + private def createMergeCommit(treeId:ObjectId, committer:PersonIdent, message:String) = { + val mergeCommit = new CommitBuilder() + mergeCommit.setTreeId(treeId) + mergeCommit.setParentIds(Array[ObjectId](mergeBaseTip, mergeTip): _*) + mergeCommit.setAuthor(committer) + mergeCommit.setCommitter(committer) + mergeCommit.setMessage(message) + // insertObject and got mergeCommit Object Id + val inserter = repository.newObjectInserter + val mergeCommitId = inserter.insert(mergeCommit) + inserter.flush() + inserter.release() + mergeCommitId + } + private def parseCommit(id:ObjectId) = using(new RevWalk( repository ))(_.parseCommit(id)) + } } \ No newline at end of file diff --git a/src/main/scala/servlet/AccessTokenAuthenticationFilter.scala b/src/main/scala/servlet/AccessTokenAuthenticationFilter.scala index 0dc3949..56e50c2 100644 --- a/src/main/scala/servlet/AccessTokenAuthenticationFilter.scala +++ b/src/main/scala/servlet/AccessTokenAuthenticationFilter.scala @@ -1,41 +1,41 @@ -package servlet - -import javax.servlet._ -import javax.servlet.http.{HttpServletRequest, HttpServletResponse} - -import service.AccessTokenService -import util.Keys -import org.scalatra.servlet.ServletApiImplicits._ -import model.Account -import org.scalatra._ - -class AccessTokenAuthenticationFilter extends Filter with AccessTokenService { - private val tokenHeaderPrefix = "token " - - override def init(filterConfig: FilterConfig): Unit = {} - - override def destroy(): Unit = {} - - override def doFilter(req: ServletRequest, res: ServletResponse, chain: FilterChain): Unit = { - implicit val request = req.asInstanceOf[HttpServletRequest] - implicit val session = req.getAttribute(Keys.Request.DBSession).asInstanceOf[slick.jdbc.JdbcBackend#Session] - val response = res.asInstanceOf[HttpServletResponse] - Option(request.getHeader("Authorization")).map{ - case auth if auth.startsWith("token ") => AccessTokenService.getAccountByAccessToken(auth.substring(6).trim).toRight(Unit) - // TODO Basic Authentication Support - case _ => Left(Unit) - }.orElse{ - Option(request.getSession.getAttribute(Keys.Session.LoginAccount).asInstanceOf[Account]).map(Right(_)) - } match { - case Some(Right(account)) => request.setAttribute(Keys.Session.LoginAccount, account); chain.doFilter(req, res) - case None => chain.doFilter(req, res) - case Some(Left(_)) => { - response.setStatus(HttpServletResponse.SC_UNAUTHORIZED) - response.setContentType("Content-Type: application/json; charset=utf-8") - val w = response.getWriter() - w.print("""{ "message": "Bad credentials" }""") - w.close() - } - } - } -} +package servlet + +import javax.servlet._ +import javax.servlet.http.{HttpServletRequest, HttpServletResponse} + +import service.AccessTokenService +import util.Keys +import org.scalatra.servlet.ServletApiImplicits._ +import model.Account +import org.scalatra._ + +class AccessTokenAuthenticationFilter extends Filter with AccessTokenService { + private val tokenHeaderPrefix = "token " + + override def init(filterConfig: FilterConfig): Unit = {} + + override def destroy(): Unit = {} + + override def doFilter(req: ServletRequest, res: ServletResponse, chain: FilterChain): Unit = { + implicit val request = req.asInstanceOf[HttpServletRequest] + implicit val session = req.getAttribute(Keys.Request.DBSession).asInstanceOf[slick.jdbc.JdbcBackend#Session] + val response = res.asInstanceOf[HttpServletResponse] + Option(request.getHeader("Authorization")).map{ + case auth if auth.startsWith("token ") => AccessTokenService.getAccountByAccessToken(auth.substring(6).trim).toRight(Unit) + // TODO Basic Authentication Support + case _ => Left(Unit) + }.orElse{ + Option(request.getSession.getAttribute(Keys.Session.LoginAccount).asInstanceOf[Account]).map(Right(_)) + } match { + case Some(Right(account)) => request.setAttribute(Keys.Session.LoginAccount, account); chain.doFilter(req, res) + case None => chain.doFilter(req, res) + case Some(Left(_)) => { + response.setStatus(HttpServletResponse.SC_UNAUTHORIZED) + response.setContentType("Content-Type: application/json; charset=utf-8") + val w = response.getWriter() + w.print("""{ "message": "Bad credentials" }""") + w.close() + } + } + } +} diff --git a/src/main/scala/util/RepoitoryName.scala b/src/main/scala/util/RepoitoryName.scala index 1642d9b..0e6edbf 100644 --- a/src/main/scala/util/RepoitoryName.scala +++ b/src/main/scala/util/RepoitoryName.scala @@ -1,18 +1,18 @@ -package util - -case class RepositoryName(owner:String, name:String){ - val fullName = s"${owner}/${name}" -} - -object RepositoryName{ - def apply(fullName: String): RepositoryName = { - fullName.split("/").toList match { - case owner :: name :: Nil => RepositoryName(owner, name) - case _ => throw new IllegalArgumentException(s"${fullName} is not repositoryName (only 'owner/name')") - } - } - def apply(repository: model.Repository): RepositoryName = RepositoryName(repository.userName, repository.repositoryName) - def apply(repository: util.JGitUtil.RepositoryInfo): RepositoryName = RepositoryName(repository.owner, repository.name) - def apply(repository: service.RepositoryService.RepositoryInfo): RepositoryName = RepositoryName(repository.owner, repository.name) - def apply(repository: model.CommitStatus): RepositoryName = RepositoryName(repository.userName, repository.repositoryName) -} +package util + +case class RepositoryName(owner:String, name:String){ + val fullName = s"${owner}/${name}" +} + +object RepositoryName{ + def apply(fullName: String): RepositoryName = { + fullName.split("/").toList match { + case owner :: name :: Nil => RepositoryName(owner, name) + case _ => throw new IllegalArgumentException(s"${fullName} is not repositoryName (only 'owner/name')") + } + } + def apply(repository: model.Repository): RepositoryName = RepositoryName(repository.userName, repository.repositoryName) + def apply(repository: util.JGitUtil.RepositoryInfo): RepositoryName = RepositoryName(repository.owner, repository.name) + def apply(repository: service.RepositoryService.RepositoryInfo): RepositoryName = RepositoryName(repository.owner, repository.name) + def apply(repository: model.CommitStatus): RepositoryName = RepositoryName(repository.userName, repository.repositoryName) +} diff --git a/src/main/twirl/account/application.scala.html b/src/main/twirl/account/application.scala.html index d2c3800..e6a5d06 100644 --- a/src/main/twirl/account/application.scala.html +++ b/src/main/twirl/account/application.scala.html @@ -1,55 +1,55 @@ -@(account: model.Account, personalTokens: List[model.AccessToken], gneratedToken:Option[(model.AccessToken, String)])(implicit context: app.Context) -@import context._ -@import view.helpers._ -@html.main("Applications"){ -
-
-
- @menu("application", settings.ssh) -
-
-
-
Personal access tokens
-
- @if(personalTokens.isEmpty && gneratedToken.isEmpty){ - No tokens. - }else{ - Tokens you have generated that can be used to access the GitBucket API.
- } - @gneratedToken.map{ case (token, tokenString) => -
- Make sure to copy your new personal access token now. You won't be able to see it again! -
- @helper.html.copy("generated-token-copy", tokenString){ - - } - Delete -
- } - @personalTokens.zipWithIndex.map { case (token, i) => - @if(i != 0){ -
- } - @token.note - Delete - } -
-
-
-
-
Generate new token
-
-
- -
- -

What's this token for?

-
- -
-
-
-
-
-
-} +@(account: model.Account, personalTokens: List[model.AccessToken], gneratedToken:Option[(model.AccessToken, String)])(implicit context: app.Context) +@import context._ +@import view.helpers._ +@html.main("Applications"){ +
+
+
+ @menu("application", settings.ssh) +
+
+
+
Personal access tokens
+
+ @if(personalTokens.isEmpty && gneratedToken.isEmpty){ + No tokens. + }else{ + Tokens you have generated that can be used to access the GitBucket API.
+ } + @gneratedToken.map{ case (token, tokenString) => +
+ Make sure to copy your new personal access token now. You won't be able to see it again! +
+ @helper.html.copy("generated-token-copy", tokenString){ + + } + Delete +
+ } + @personalTokens.zipWithIndex.map { case (token, i) => + @if(i != 0){ +
+ } + @token.note + Delete + } +
+
+
+
+
Generate new token
+
+
+ +
+ +

What's this token for?

+
+ +
+
+
+
+
+
+} diff --git a/src/test/scala/api/JsonFormatSpec.scala b/src/test/scala/api/JsonFormatSpec.scala index a000a52..0f145a6 100644 --- a/src/test/scala/api/JsonFormatSpec.scala +++ b/src/test/scala/api/JsonFormatSpec.scala @@ -1,275 +1,275 @@ -package api -import org.specs2.mutable.Specification -import java.util.{Date, Calendar, TimeZone} -import util.RepositoryName -import org.json4s.jackson.JsonMethods.{pretty, parse} -import org.json4s._ -import org.specs2.matcher._ -class JsonFormatSpec extends Specification { - val date1 = { - val d = Calendar.getInstance(TimeZone.getTimeZone("UTC")) - d.set(2011,3,14,16,0,49) - d.getTime - } - val sha1 = "6dcb09b5b57875f334f61aebed695e2e4193db5e" - val repo1Name = RepositoryName("octocat/Hello-World") - implicit val context = JsonFormat.Context("http://gitbucket.exmple.com") - - val apiUser = ApiUser( - login= "octocat", - email= "octocat@example.com", - `type`= "User", - site_admin= false, - created_at= date1) - val apiUserJson = """{ - "login":"octocat", - "email":"octocat@example.com", - "type":"User", - "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" - }""" - - val repository = ApiRepository( - name = repo1Name.name, - full_name = repo1Name.fullName, - description = "This your first repo!", - watchers = 0, - forks = 0, - `private` = false, - default_branch = "master", - owner = apiUser) - val repositoryJson = s"""{ - "name" : "Hello-World", - "full_name" : "octocat/Hello-World", - "description" : "This your first repo!", - "watchers" : 0, - "forks" : 0, - "private" : false, - "default_branch" : "master", - "owner" : $apiUserJson, - "forks_count" : 0, - "watchers_coun" : 0, - "url" : "${context.baseUrl}/api/v3/repos/octocat/Hello-World", - "http_url" : "${context.baseUrl}/git/octocat/Hello-World.git", - "clone_url" : "${context.baseUrl}/git/octocat/Hello-World.git", - "html_url" : "${context.baseUrl}/octocat/Hello-World" - }""" - - val apiCommitStatus = ApiCommitStatus( - created_at = date1, - updated_at = date1, - state = "success", - target_url = Some("https://ci.example.com/1000/output"), - description = Some("Build has completed successfully"), - id = 1, - context = "Default", - creator = apiUser - )(sha1, repo1Name) - val apiCommitStatusJson = s"""{ - "created_at":"2011-04-14T16:00:49Z", - "updated_at":"2011-04-14T16:00:49Z", - "state":"success", - "target_url":"https://ci.example.com/1000/output", - "description":"Build has completed successfully", - "id":1, - "context":"Default", - "creator":$apiUserJson, - "url": "http://gitbucket.exmple.com/api/v3/repos/octocat/Hello-World/commits/6dcb09b5b57875f334f61aebed695e2e4193db5e/statuses" - }""" - - val apiComment = ApiComment( - id =1, - user = apiUser, - body= "Me too", - created_at= date1, - updated_at= date1) - val apiCommentJson = s"""{ - "id": 1, - "body": "Me too", - "user": $apiUserJson, - "created_at": "2011-04-14T16:00:49Z", - "updated_at": "2011-04-14T16:00:49Z" - }""" - - val apiPersonIdent = ApiPersonIdent("Monalisa Octocat","support@example.com",date1) - val apiPersonIdentJson = """ { - "name": "Monalisa Octocat", - "email": "support@example.com", - "date": "2011-04-14T16:00:49Z" - }""" - - val apiCommitListItem = ApiCommitListItem( - sha = sha1, - commit = ApiCommitListItem.Commit( - message = "Fix all the bugs", - author = apiPersonIdent, - committer = apiPersonIdent - )(sha1, repo1Name), - author = Some(apiUser), - committer= Some(apiUser), - parents= Seq(ApiCommitListItem.Parent("6dcb09b5b57875f334f61aebed695e2e4193db5e")(repo1Name)))(repo1Name) - val apiCommitListItemJson = s"""{ - "url": "${context.baseUrl}/api/v3/repos/octocat/Hello-World/commits/6dcb09b5b57875f334f61aebed695e2e4193db5e", - "sha": "6dcb09b5b57875f334f61aebed695e2e4193db5e", - "commit": { - "url": "${context.baseUrl}/api/v3/repos/octocat/Hello-World/git/commits/6dcb09b5b57875f334f61aebed695e2e4193db5e", - "author": $apiPersonIdentJson, - "committer": $apiPersonIdentJson, - "message": "Fix all the bugs" - }, - "author": $apiUserJson, - "committer": $apiUserJson, - "parents": [ - { - "url": "${context.baseUrl}/api/v3/repos/octocat/Hello-World/commits/6dcb09b5b57875f334f61aebed695e2e4193db5e", - "sha": "6dcb09b5b57875f334f61aebed695e2e4193db5e" - } - ] - }""" - - val apiCombinedCommitStatus = ApiCombinedCommitStatus( - state = "success", - sha = sha1, - total_count = 2, - statuses = List(apiCommitStatus), - repository = repository) - val apiCombinedCommitStatusJson = s"""{ - "state": "success", - "sha": "$sha1", - "total_count": 2, - "statuses": [ $apiCommitStatusJson ], - "repository": $repositoryJson, - "url": "${context.baseUrl}/api/v3/repos/octocat/Hello-World/commits/$sha1/status" - }""" - - val apiIssue = ApiIssue( - number = 1347, - title = "Found a bug", - user = apiUser, - state = "open", - body = "I'm having a problem with this.", - created_at = date1, - updated_at = date1) - val apiIssueJson = s"""{ - "number": 1347, - "state": "open", - "title": "Found a bug", - "body": "I'm having a problem with this.", - "user": $apiUserJson, - "created_at": "2011-04-14T16:00:49Z", - "updated_at": "2011-04-14T16:00:49Z" - }""" - - val apiPullRequest = ApiPullRequest( - number = 1347, - updated_at = date1, - created_at = date1, - head = ApiPullRequest.Commit( - sha = sha1, - ref = "new-topic", - repo = repository)("octocat"), - base = ApiPullRequest.Commit( - sha = sha1, - ref = "master", - repo = repository)("octocat"), - mergeable = None, - title = "new-feature", - body = "Please pull these awesome changes", - user = apiUser - ) - val apiPullRequestJson = s"""{ - "url": "${context.baseUrl}/api/v3/repos/octocat/Hello-World/pulls/1347", - "html_url": "${context.baseUrl}/octocat/Hello-World/pull/1347", - // "diff_url": "${context.baseUrl}/octocat/Hello-World/pull/1347.diff", - // "patch_url": "${context.baseUrl}/octocat/Hello-World/pull/1347.patch", - // "issue_url": "${context.baseUrl}/api/v3/repos/octocat/Hello-World/issues/1347", - "commits_url": "${context.baseUrl}/api/v3/repos/octocat/Hello-World/pulls/1347/commits", - "review_comments_url": "${context.baseUrl}/api/v3/repos/octocat/Hello-World/pulls/1347/comments", - "review_comment_url": "${context.baseUrl}/api/v3/repos/octocat/Hello-World/pulls/comments/{number}", - "comments_url": "${context.baseUrl}/api/v3/repos/octocat/Hello-World/issues/1347/comments", - "statuses_url": "${context.baseUrl}/api/v3/repos/octocat/Hello-World/statuses/6dcb09b5b57875f334f61aebed695e2e4193db5e", - "number": 1347, - // "state": "open", - "title": "new-feature", - "body": "Please pull these awesome changes", - "created_at": "2011-04-14T16:00:49Z", - "updated_at": "2011-04-14T16:00:49Z", - // "closed_at": "2011-04-14T16:00:49Z", - // "merged_at": "2011-04-14T16:00:49Z", - "head": { - "label": "new-topic", - "ref": "new-topic", - "sha": "6dcb09b5b57875f334f61aebed695e2e4193db5e", - "user": $apiUserJson, - "repo": $repositoryJson - }, - "base": { - "label": "master", - "ref": "master", - "sha": "6dcb09b5b57875f334f61aebed695e2e4193db5e", - "user": $apiUserJson, - "repo": $repositoryJson - }, - "user": $apiUserJson - // "merge_commit_sha": "e5bd3914e2e596debea16f433f57875b5b90bcd6", - // "merged": false, - // "mergeable": true, - // "merged_by": $$apiUserJson, - // "comments": 10, - // "commits": 3, - // "additions": 100, - // "deletions": 3, - // "changed_files": 5 - }""" - def beFormatted(json2Arg:String) = new Matcher[String] { - def apply[S <: String](e: Expectable[S]) = { - import java.util.regex.Pattern - val json2 = Pattern.compile("""^\s*//.*$""", Pattern.MULTILINE).matcher(json2Arg).replaceAll("") - val js2 = try{ - parse(json2) - }catch{ - case e:com.fasterxml.jackson.core.JsonParseException => { - val p = java.lang.Math.max(e.getLocation.getCharOffset()-10,0).toInt - val message = json2.substring(p,java.lang.Math.min(p+100,json2.length)) - throw new com.fasterxml.jackson.core.JsonParseException(message + e.getMessage , e.getLocation) - } - } - val js1 = parse(e.value) - result(js1 == js2, - "expected", - { - val diff = js2 diff js1 - s"${pretty(js1)} is not ${pretty(js2)} \n\n ${pretty(Extraction.decompose(diff)(org.json4s.DefaultFormats))}" - }, - e) - } - } - "JsonFormat" should { - "apiUser" in { - JsonFormat(apiUser) must beFormatted(apiUserJson) - } - "repository" in { - JsonFormat(repository) must beFormatted(repositoryJson) - } - "apiComment" in { - JsonFormat(apiComment) must beFormatted(apiCommentJson) - } - "apiCommitListItem" in { - JsonFormat(apiCommitListItem) must beFormatted(apiCommitListItemJson) - } - "apiCommitStatus" in { - JsonFormat(apiCommitStatus) must beFormatted(apiCommitStatusJson) - } - "apiCombinedCommitStatus" in { - JsonFormat(apiCombinedCommitStatus) must beFormatted(apiCombinedCommitStatusJson) - } - "apiIssue" in { - JsonFormat(apiIssue) must beFormatted(apiIssueJson) - } - "apiPullRequest" in { - JsonFormat(apiPullRequest) must beFormatted(apiPullRequestJson) - } - } -} +package api +import org.specs2.mutable.Specification +import java.util.{Date, Calendar, TimeZone} +import util.RepositoryName +import org.json4s.jackson.JsonMethods.{pretty, parse} +import org.json4s._ +import org.specs2.matcher._ +class JsonFormatSpec extends Specification { + val date1 = { + val d = Calendar.getInstance(TimeZone.getTimeZone("UTC")) + d.set(2011,3,14,16,0,49) + d.getTime + } + val sha1 = "6dcb09b5b57875f334f61aebed695e2e4193db5e" + val repo1Name = RepositoryName("octocat/Hello-World") + implicit val context = JsonFormat.Context("http://gitbucket.exmple.com") + + val apiUser = ApiUser( + login= "octocat", + email= "octocat@example.com", + `type`= "User", + site_admin= false, + created_at= date1) + val apiUserJson = """{ + "login":"octocat", + "email":"octocat@example.com", + "type":"User", + "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" + }""" + + val repository = ApiRepository( + name = repo1Name.name, + full_name = repo1Name.fullName, + description = "This your first repo!", + watchers = 0, + forks = 0, + `private` = false, + default_branch = "master", + owner = apiUser) + val repositoryJson = s"""{ + "name" : "Hello-World", + "full_name" : "octocat/Hello-World", + "description" : "This your first repo!", + "watchers" : 0, + "forks" : 0, + "private" : false, + "default_branch" : "master", + "owner" : $apiUserJson, + "forks_count" : 0, + "watchers_coun" : 0, + "url" : "${context.baseUrl}/api/v3/repos/octocat/Hello-World", + "http_url" : "${context.baseUrl}/git/octocat/Hello-World.git", + "clone_url" : "${context.baseUrl}/git/octocat/Hello-World.git", + "html_url" : "${context.baseUrl}/octocat/Hello-World" + }""" + + val apiCommitStatus = ApiCommitStatus( + created_at = date1, + updated_at = date1, + state = "success", + target_url = Some("https://ci.example.com/1000/output"), + description = Some("Build has completed successfully"), + id = 1, + context = "Default", + creator = apiUser + )(sha1, repo1Name) + val apiCommitStatusJson = s"""{ + "created_at":"2011-04-14T16:00:49Z", + "updated_at":"2011-04-14T16:00:49Z", + "state":"success", + "target_url":"https://ci.example.com/1000/output", + "description":"Build has completed successfully", + "id":1, + "context":"Default", + "creator":$apiUserJson, + "url": "http://gitbucket.exmple.com/api/v3/repos/octocat/Hello-World/commits/6dcb09b5b57875f334f61aebed695e2e4193db5e/statuses" + }""" + + val apiComment = ApiComment( + id =1, + user = apiUser, + body= "Me too", + created_at= date1, + updated_at= date1) + val apiCommentJson = s"""{ + "id": 1, + "body": "Me too", + "user": $apiUserJson, + "created_at": "2011-04-14T16:00:49Z", + "updated_at": "2011-04-14T16:00:49Z" + }""" + + val apiPersonIdent = ApiPersonIdent("Monalisa Octocat","support@example.com",date1) + val apiPersonIdentJson = """ { + "name": "Monalisa Octocat", + "email": "support@example.com", + "date": "2011-04-14T16:00:49Z" + }""" + + val apiCommitListItem = ApiCommitListItem( + sha = sha1, + commit = ApiCommitListItem.Commit( + message = "Fix all the bugs", + author = apiPersonIdent, + committer = apiPersonIdent + )(sha1, repo1Name), + author = Some(apiUser), + committer= Some(apiUser), + parents= Seq(ApiCommitListItem.Parent("6dcb09b5b57875f334f61aebed695e2e4193db5e")(repo1Name)))(repo1Name) + val apiCommitListItemJson = s"""{ + "url": "${context.baseUrl}/api/v3/repos/octocat/Hello-World/commits/6dcb09b5b57875f334f61aebed695e2e4193db5e", + "sha": "6dcb09b5b57875f334f61aebed695e2e4193db5e", + "commit": { + "url": "${context.baseUrl}/api/v3/repos/octocat/Hello-World/git/commits/6dcb09b5b57875f334f61aebed695e2e4193db5e", + "author": $apiPersonIdentJson, + "committer": $apiPersonIdentJson, + "message": "Fix all the bugs" + }, + "author": $apiUserJson, + "committer": $apiUserJson, + "parents": [ + { + "url": "${context.baseUrl}/api/v3/repos/octocat/Hello-World/commits/6dcb09b5b57875f334f61aebed695e2e4193db5e", + "sha": "6dcb09b5b57875f334f61aebed695e2e4193db5e" + } + ] + }""" + + val apiCombinedCommitStatus = ApiCombinedCommitStatus( + state = "success", + sha = sha1, + total_count = 2, + statuses = List(apiCommitStatus), + repository = repository) + val apiCombinedCommitStatusJson = s"""{ + "state": "success", + "sha": "$sha1", + "total_count": 2, + "statuses": [ $apiCommitStatusJson ], + "repository": $repositoryJson, + "url": "${context.baseUrl}/api/v3/repos/octocat/Hello-World/commits/$sha1/status" + }""" + + val apiIssue = ApiIssue( + number = 1347, + title = "Found a bug", + user = apiUser, + state = "open", + body = "I'm having a problem with this.", + created_at = date1, + updated_at = date1) + val apiIssueJson = s"""{ + "number": 1347, + "state": "open", + "title": "Found a bug", + "body": "I'm having a problem with this.", + "user": $apiUserJson, + "created_at": "2011-04-14T16:00:49Z", + "updated_at": "2011-04-14T16:00:49Z" + }""" + + val apiPullRequest = ApiPullRequest( + number = 1347, + updated_at = date1, + created_at = date1, + head = ApiPullRequest.Commit( + sha = sha1, + ref = "new-topic", + repo = repository)("octocat"), + base = ApiPullRequest.Commit( + sha = sha1, + ref = "master", + repo = repository)("octocat"), + mergeable = None, + title = "new-feature", + body = "Please pull these awesome changes", + user = apiUser + ) + val apiPullRequestJson = s"""{ + "url": "${context.baseUrl}/api/v3/repos/octocat/Hello-World/pulls/1347", + "html_url": "${context.baseUrl}/octocat/Hello-World/pull/1347", + // "diff_url": "${context.baseUrl}/octocat/Hello-World/pull/1347.diff", + // "patch_url": "${context.baseUrl}/octocat/Hello-World/pull/1347.patch", + // "issue_url": "${context.baseUrl}/api/v3/repos/octocat/Hello-World/issues/1347", + "commits_url": "${context.baseUrl}/api/v3/repos/octocat/Hello-World/pulls/1347/commits", + "review_comments_url": "${context.baseUrl}/api/v3/repos/octocat/Hello-World/pulls/1347/comments", + "review_comment_url": "${context.baseUrl}/api/v3/repos/octocat/Hello-World/pulls/comments/{number}", + "comments_url": "${context.baseUrl}/api/v3/repos/octocat/Hello-World/issues/1347/comments", + "statuses_url": "${context.baseUrl}/api/v3/repos/octocat/Hello-World/statuses/6dcb09b5b57875f334f61aebed695e2e4193db5e", + "number": 1347, + // "state": "open", + "title": "new-feature", + "body": "Please pull these awesome changes", + "created_at": "2011-04-14T16:00:49Z", + "updated_at": "2011-04-14T16:00:49Z", + // "closed_at": "2011-04-14T16:00:49Z", + // "merged_at": "2011-04-14T16:00:49Z", + "head": { + "label": "new-topic", + "ref": "new-topic", + "sha": "6dcb09b5b57875f334f61aebed695e2e4193db5e", + "user": $apiUserJson, + "repo": $repositoryJson + }, + "base": { + "label": "master", + "ref": "master", + "sha": "6dcb09b5b57875f334f61aebed695e2e4193db5e", + "user": $apiUserJson, + "repo": $repositoryJson + }, + "user": $apiUserJson + // "merge_commit_sha": "e5bd3914e2e596debea16f433f57875b5b90bcd6", + // "merged": false, + // "mergeable": true, + // "merged_by": $$apiUserJson, + // "comments": 10, + // "commits": 3, + // "additions": 100, + // "deletions": 3, + // "changed_files": 5 + }""" + def beFormatted(json2Arg:String) = new Matcher[String] { + def apply[S <: String](e: Expectable[S]) = { + import java.util.regex.Pattern + val json2 = Pattern.compile("""^\s*//.*$""", Pattern.MULTILINE).matcher(json2Arg).replaceAll("") + val js2 = try{ + parse(json2) + }catch{ + case e:com.fasterxml.jackson.core.JsonParseException => { + val p = java.lang.Math.max(e.getLocation.getCharOffset()-10,0).toInt + val message = json2.substring(p,java.lang.Math.min(p+100,json2.length)) + throw new com.fasterxml.jackson.core.JsonParseException(message + e.getMessage , e.getLocation) + } + } + val js1 = parse(e.value) + result(js1 == js2, + "expected", + { + val diff = js2 diff js1 + s"${pretty(js1)} is not ${pretty(js2)} \n\n ${pretty(Extraction.decompose(diff)(org.json4s.DefaultFormats))}" + }, + e) + } + } + "JsonFormat" should { + "apiUser" in { + JsonFormat(apiUser) must beFormatted(apiUserJson) + } + "repository" in { + JsonFormat(repository) must beFormatted(repositoryJson) + } + "apiComment" in { + JsonFormat(apiComment) must beFormatted(apiCommentJson) + } + "apiCommitListItem" in { + JsonFormat(apiCommitListItem) must beFormatted(apiCommitListItemJson) + } + "apiCommitStatus" in { + JsonFormat(apiCommitStatus) must beFormatted(apiCommitStatusJson) + } + "apiCombinedCommitStatus" in { + JsonFormat(apiCombinedCommitStatus) must beFormatted(apiCombinedCommitStatusJson) + } + "apiIssue" in { + JsonFormat(apiIssue) must beFormatted(apiIssueJson) + } + "apiPullRequest" in { + JsonFormat(apiPullRequest) must beFormatted(apiPullRequestJson) + } + } +} diff --git a/src/test/scala/model/CommitStateSpec.scala b/src/test/scala/model/CommitStateSpec.scala index a744d83..231322f 100644 --- a/src/test/scala/model/CommitStateSpec.scala +++ b/src/test/scala/model/CommitStateSpec.scala @@ -1,25 +1,25 @@ -package model - -import org.specs2.mutable.Specification - -import CommitState._ - -class CommitStateSpec extends Specification { - "CommitState" should { - "combine empty must eq PENDING" in { - combine(Set()) must_== PENDING - } - "combine includes ERROR must eq FAILURE" in { - combine(Set(ERROR, SUCCESS, PENDING)) must_== FAILURE - } - "combine includes FAILURE must eq peinding" in { - combine(Set(FAILURE, SUCCESS, PENDING)) must_== FAILURE - } - "combine includes PENDING must eq peinding" in { - combine(Set(PENDING, SUCCESS)) must_== PENDING - } - "combine only SUCCESS must eq SUCCESS" in { - combine(Set(SUCCESS)) must_== SUCCESS - } - } -} +package model + +import org.specs2.mutable.Specification + +import CommitState._ + +class CommitStateSpec extends Specification { + "CommitState" should { + "combine empty must eq PENDING" in { + combine(Set()) must_== PENDING + } + "combine includes ERROR must eq FAILURE" in { + combine(Set(ERROR, SUCCESS, PENDING)) must_== FAILURE + } + "combine includes FAILURE must eq peinding" in { + combine(Set(FAILURE, SUCCESS, PENDING)) must_== FAILURE + } + "combine includes PENDING must eq peinding" in { + combine(Set(PENDING, SUCCESS)) must_== PENDING + } + "combine only SUCCESS must eq SUCCESS" in { + combine(Set(SUCCESS)) must_== SUCCESS + } + } +} diff --git a/src/test/scala/service/AccessTokenServiceSpec.scala b/src/test/scala/service/AccessTokenServiceSpec.scala index dccb287..7729158 100644 --- a/src/test/scala/service/AccessTokenServiceSpec.scala +++ b/src/test/scala/service/AccessTokenServiceSpec.scala @@ -1,88 +1,88 @@ -package service - -import org.specs2.mutable.Specification -import java.util.Date -import model._ - -class AccessTokenServiceSpec extends Specification with ServiceSpecBase { - - "AccessTokenService" should { - "generateAccessToken" in { withTestDB { implicit session => - AccessTokenService.generateAccessToken("root", "note") must be like{ - case (id, token) if id != 0 => ok - } - }} - - "getAccessTokens" in { withTestDB { implicit session => - val (id, token) = AccessTokenService.generateAccessToken("root", "note") - val tokenHash = AccessTokenService.tokenToHash(token) - - AccessTokenService.getAccessTokens("root") must be like{ - case List(model.AccessToken(`id`, "root", `tokenHash`, "note")) => ok - } - }} - - "getAccessTokens(root) get root's tokens" in { withTestDB { implicit session => - val (id, token) = AccessTokenService.generateAccessToken("root", "note") - val tokenHash = AccessTokenService.tokenToHash(token) - val user2 = generateNewAccount("user2") - AccessTokenService.generateAccessToken("user2", "note2") - - AccessTokenService.getAccessTokens("root") must be like{ - case List(model.AccessToken(`id`, "root", `tokenHash`, "note")) => ok - } - }} - - "deleteAccessToken" in { withTestDB { implicit session => - val (id, token) = AccessTokenService.generateAccessToken("root", "note") - val user2 = generateNewAccount("user2") - AccessTokenService.generateAccessToken("user2", "note2") - - AccessTokenService.deleteAccessToken("root", id) - - AccessTokenService.getAccessTokens("root") must beEmpty - }} - - "getAccountByAccessToken" in { withTestDB { implicit session => - val (id, token) = AccessTokenService.generateAccessToken("root", "note") - AccessTokenService.getAccountByAccessToken(token) must beSome.like { - case user => user.userName must_== "root" - } - }} - - "getAccountByAccessToken don't get removed account" in { withTestDB { implicit session => - val user2 = generateNewAccount("user2") - val (id, token) = AccessTokenService.generateAccessToken("user2", "note") - AccountService.updateAccount(user2.copy(isRemoved=true)) - - AccessTokenService.getAccountByAccessToken(token) must beEmpty - }} - - "generateAccessToken create uniq token" in { withTestDB { implicit session => - val tokenIt = List("token1","token1","token1","token2").iterator - val service = new AccessTokenService{ - override def makeAccessTokenString:String = tokenIt.next - } - - service.generateAccessToken("root", "note1") must like{ - case (_, "token1") => ok - } - service.generateAccessToken("root", "note2") must like{ - case (_, "token2") => ok - } - }} - - "when update Account.userName then AccessToken.userName changed" in { withTestDB { implicit session => - val user2 = generateNewAccount("user2") - val (id, token) = AccessTokenService.generateAccessToken("user2", "note") - import model.Profile._ - import profile.simple._ - Accounts.filter(_.userName === "user2".bind).map(_.userName).update("user3") - - AccessTokenService.getAccountByAccessToken(token) must beSome.like { - case user => user.userName must_== "user3" - } - }} - } -} - +package service + +import org.specs2.mutable.Specification +import java.util.Date +import model._ + +class AccessTokenServiceSpec extends Specification with ServiceSpecBase { + + "AccessTokenService" should { + "generateAccessToken" in { withTestDB { implicit session => + AccessTokenService.generateAccessToken("root", "note") must be like{ + case (id, token) if id != 0 => ok + } + }} + + "getAccessTokens" in { withTestDB { implicit session => + val (id, token) = AccessTokenService.generateAccessToken("root", "note") + val tokenHash = AccessTokenService.tokenToHash(token) + + AccessTokenService.getAccessTokens("root") must be like{ + case List(model.AccessToken(`id`, "root", `tokenHash`, "note")) => ok + } + }} + + "getAccessTokens(root) get root's tokens" in { withTestDB { implicit session => + val (id, token) = AccessTokenService.generateAccessToken("root", "note") + val tokenHash = AccessTokenService.tokenToHash(token) + val user2 = generateNewAccount("user2") + AccessTokenService.generateAccessToken("user2", "note2") + + AccessTokenService.getAccessTokens("root") must be like{ + case List(model.AccessToken(`id`, "root", `tokenHash`, "note")) => ok + } + }} + + "deleteAccessToken" in { withTestDB { implicit session => + val (id, token) = AccessTokenService.generateAccessToken("root", "note") + val user2 = generateNewAccount("user2") + AccessTokenService.generateAccessToken("user2", "note2") + + AccessTokenService.deleteAccessToken("root", id) + + AccessTokenService.getAccessTokens("root") must beEmpty + }} + + "getAccountByAccessToken" in { withTestDB { implicit session => + val (id, token) = AccessTokenService.generateAccessToken("root", "note") + AccessTokenService.getAccountByAccessToken(token) must beSome.like { + case user => user.userName must_== "root" + } + }} + + "getAccountByAccessToken don't get removed account" in { withTestDB { implicit session => + val user2 = generateNewAccount("user2") + val (id, token) = AccessTokenService.generateAccessToken("user2", "note") + AccountService.updateAccount(user2.copy(isRemoved=true)) + + AccessTokenService.getAccountByAccessToken(token) must beEmpty + }} + + "generateAccessToken create uniq token" in { withTestDB { implicit session => + val tokenIt = List("token1","token1","token1","token2").iterator + val service = new AccessTokenService{ + override def makeAccessTokenString:String = tokenIt.next + } + + service.generateAccessToken("root", "note1") must like{ + case (_, "token1") => ok + } + service.generateAccessToken("root", "note2") must like{ + case (_, "token2") => ok + } + }} + + "when update Account.userName then AccessToken.userName changed" in { withTestDB { implicit session => + val user2 = generateNewAccount("user2") + val (id, token) = AccessTokenService.generateAccessToken("user2", "note") + import model.Profile._ + import profile.simple._ + Accounts.filter(_.userName === "user2".bind).map(_.userName).update("user3") + + AccessTokenService.getAccountByAccessToken(token) must beSome.like { + case user => user.userName must_== "user3" + } + }} + } +} + diff --git a/src/test/scala/service/CommitStateServiceSpec.scala b/src/test/scala/service/CommitStateServiceSpec.scala index a868e13..4983fc5 100644 --- a/src/test/scala/service/CommitStateServiceSpec.scala +++ b/src/test/scala/service/CommitStateServiceSpec.scala @@ -1,73 +1,73 @@ -package service -import org.specs2.mutable.Specification -import java.util.Date -import model._ -import model.Profile._ -import profile.simple._ -class CommitStatusServiceSpec extends Specification with ServiceSpecBase with CommitStatusService - with RepositoryService with AccountService{ - val now = new java.util.Date() - val fixture1 = CommitStatus( - userName = "root", - repositoryName = "repo", - commitId = "0e97b8f59f7cdd709418bb59de53f741fd1c1bd7", - context = "jenkins/test", - creator = "tester", - state = CommitState.PENDING, - targetUrl = Some("http://example.com/target"), - description = Some("description"), - updatedDate = now, - registeredDate = now) - def findById(id: Int)(implicit s:Session) = CommitStatuses.filter(_.byPrimaryKey(id)).firstOption - def generateFixture1(tester:Account)(implicit s:Session) = createCommitStatus( - userName = fixture1.userName, - repositoryName = fixture1.repositoryName, - sha = fixture1.commitId, - context = fixture1.context, - state = fixture1.state, - targetUrl = fixture1.targetUrl, - description = fixture1.description, - creator = tester, - now = fixture1.registeredDate) - "CommitStatusService" should { - "createCommitState can insert and update" in { withTestDB { implicit session => - val tester = generateNewAccount(fixture1.creator) - createRepository(fixture1.repositoryName,fixture1.userName,None,false) - val id = generateFixture1(tester:Account) - getCommitStatus(fixture1.userName, fixture1.repositoryName, id) must_== - Some(fixture1.copy(commitStatusId=id)) - // other one can update - val tester2 = generateNewAccount("tester2") - val time2 = new java.util.Date(); - val id2 = createCommitStatus( - userName = fixture1.userName, - repositoryName = fixture1.repositoryName, - sha = fixture1.commitId, - context = fixture1.context, - state = CommitState.SUCCESS, - targetUrl = Some("http://example.com/target2"), - description = Some("description2"), - creator = tester2, - now = time2) - getCommitStatus(fixture1.userName, fixture1.repositoryName, id2) must_== Some(fixture1.copy( - commitStatusId = id, - creator = "tester2", - state = CommitState.SUCCESS, - targetUrl = Some("http://example.com/target2"), - description = Some("description2"), - updatedDate = time2)) - }} - "getCommitStatus can find by commitId and context" in { withTestDB { implicit session => - val tester = generateNewAccount(fixture1.creator) - createRepository(fixture1.repositoryName,fixture1.userName,None,false) - val id = generateFixture1(tester:Account) - getCommitStatus(fixture1.userName, fixture1.repositoryName, fixture1.commitId, fixture1.context) must_== Some(fixture1.copy(commitStatusId=id)) - }} - "getCommitStatus can find by commitStatusId" in { withTestDB { implicit session => - val tester = generateNewAccount(fixture1.creator) - createRepository(fixture1.repositoryName,fixture1.userName,None,false) - val id = generateFixture1(tester:Account) - getCommitStatus(fixture1.userName, fixture1.repositoryName, id) must_== Some(fixture1.copy(commitStatusId=id)) - }} - } +package service +import org.specs2.mutable.Specification +import java.util.Date +import model._ +import model.Profile._ +import profile.simple._ +class CommitStatusServiceSpec extends Specification with ServiceSpecBase with CommitStatusService + with RepositoryService with AccountService{ + val now = new java.util.Date() + val fixture1 = CommitStatus( + userName = "root", + repositoryName = "repo", + commitId = "0e97b8f59f7cdd709418bb59de53f741fd1c1bd7", + context = "jenkins/test", + creator = "tester", + state = CommitState.PENDING, + targetUrl = Some("http://example.com/target"), + description = Some("description"), + updatedDate = now, + registeredDate = now) + def findById(id: Int)(implicit s:Session) = CommitStatuses.filter(_.byPrimaryKey(id)).firstOption + def generateFixture1(tester:Account)(implicit s:Session) = createCommitStatus( + userName = fixture1.userName, + repositoryName = fixture1.repositoryName, + sha = fixture1.commitId, + context = fixture1.context, + state = fixture1.state, + targetUrl = fixture1.targetUrl, + description = fixture1.description, + creator = tester, + now = fixture1.registeredDate) + "CommitStatusService" should { + "createCommitState can insert and update" in { withTestDB { implicit session => + val tester = generateNewAccount(fixture1.creator) + createRepository(fixture1.repositoryName,fixture1.userName,None,false) + val id = generateFixture1(tester:Account) + getCommitStatus(fixture1.userName, fixture1.repositoryName, id) must_== + Some(fixture1.copy(commitStatusId=id)) + // other one can update + val tester2 = generateNewAccount("tester2") + val time2 = new java.util.Date(); + val id2 = createCommitStatus( + userName = fixture1.userName, + repositoryName = fixture1.repositoryName, + sha = fixture1.commitId, + context = fixture1.context, + state = CommitState.SUCCESS, + targetUrl = Some("http://example.com/target2"), + description = Some("description2"), + creator = tester2, + now = time2) + getCommitStatus(fixture1.userName, fixture1.repositoryName, id2) must_== Some(fixture1.copy( + commitStatusId = id, + creator = "tester2", + state = CommitState.SUCCESS, + targetUrl = Some("http://example.com/target2"), + description = Some("description2"), + updatedDate = time2)) + }} + "getCommitStatus can find by commitId and context" in { withTestDB { implicit session => + val tester = generateNewAccount(fixture1.creator) + createRepository(fixture1.repositoryName,fixture1.userName,None,false) + val id = generateFixture1(tester:Account) + getCommitStatus(fixture1.userName, fixture1.repositoryName, fixture1.commitId, fixture1.context) must_== Some(fixture1.copy(commitStatusId=id)) + }} + "getCommitStatus can find by commitStatusId" in { withTestDB { implicit session => + val tester = generateNewAccount(fixture1.creator) + createRepository(fixture1.repositoryName,fixture1.userName,None,false) + val id = generateFixture1(tester:Account) + getCommitStatus(fixture1.userName, fixture1.repositoryName, id) must_== Some(fixture1.copy(commitStatusId=id)) + }} + } } \ No newline at end of file diff --git a/src/test/scala/service/IssuesServiceSpec.scala b/src/test/scala/service/IssuesServiceSpec.scala index 0fada59..8105f06 100644 --- a/src/test/scala/service/IssuesServiceSpec.scala +++ b/src/test/scala/service/IssuesServiceSpec.scala @@ -1,47 +1,47 @@ -package service - -import org.specs2.mutable.Specification -import java.util.Date -import model._ -import service.IssuesService._ - -class IssuesServiceSpec extends Specification with ServiceSpecBase { - "IssuesService" should { - "getCommitStatues" in { withTestDB { implicit session => - val user1 = generateNewUserWithDBRepository("user1","repo1") - - def getCommitStatues = dummyService.getCommitStatues(List(("user1","repo1",1),("user1","repo1",2))) - - getCommitStatues must_== Map.empty - - val now = new java.util.Date() - val issueId = generateNewIssue("user1","repo1") - issueId must_== 1 - - getCommitStatues must_== Map.empty - - val cs = dummyService.createCommitStatus("user1","repo1","shasha", "default", CommitState.SUCCESS, Some("http://exmple.com/ci"), Some("exampleService"), now, user1) - - getCommitStatues must_== Map.empty - - val (is2, pr2) = generateNewPullRequest("user1/repo1/master","user1/repo1/feature1") - pr2.issueId must_== 2 - - // if there are no statuses, state is none - getCommitStatues must_== Map.empty - - // if there is a status, state is that - val cs2 = dummyService.createCommitStatus("user1","repo1","feature1", "default", CommitState.SUCCESS, Some("http://exmple.com/ci"), Some("exampleService"), now, user1) - getCommitStatues must_== Map(("user1","repo1",2) -> CommitStatusInfo(1,1,Some("default"),Some(CommitState.SUCCESS),Some("http://exmple.com/ci"),Some("exampleService"))) - - // if there are two statuses, state is none - val cs3 = dummyService.createCommitStatus("user1","repo1","feature1", "pend", CommitState.PENDING, Some("http://exmple.com/ci"), Some("exampleService"), now, user1) - getCommitStatues must_== Map(("user1","repo1",2) -> CommitStatusInfo(2,1,None,None,None,None)) - - // get only statuses in query issues - val (is3, pr3) = generateNewPullRequest("user1/repo1/master","user1/repo1/feature3") - val cs4 = dummyService.createCommitStatus("user1","repo1","feature3", "none", CommitState.PENDING, None, None, now, user1) - getCommitStatues must_== Map(("user1","repo1",2) -> CommitStatusInfo(2,1,None,None,None,None)) - } } - } +package service + +import org.specs2.mutable.Specification +import java.util.Date +import model._ +import service.IssuesService._ + +class IssuesServiceSpec extends Specification with ServiceSpecBase { + "IssuesService" should { + "getCommitStatues" in { withTestDB { implicit session => + val user1 = generateNewUserWithDBRepository("user1","repo1") + + def getCommitStatues = dummyService.getCommitStatues(List(("user1","repo1",1),("user1","repo1",2))) + + getCommitStatues must_== Map.empty + + val now = new java.util.Date() + val issueId = generateNewIssue("user1","repo1") + issueId must_== 1 + + getCommitStatues must_== Map.empty + + val cs = dummyService.createCommitStatus("user1","repo1","shasha", "default", CommitState.SUCCESS, Some("http://exmple.com/ci"), Some("exampleService"), now, user1) + + getCommitStatues must_== Map.empty + + val (is2, pr2) = generateNewPullRequest("user1/repo1/master","user1/repo1/feature1") + pr2.issueId must_== 2 + + // if there are no statuses, state is none + getCommitStatues must_== Map.empty + + // if there is a status, state is that + val cs2 = dummyService.createCommitStatus("user1","repo1","feature1", "default", CommitState.SUCCESS, Some("http://exmple.com/ci"), Some("exampleService"), now, user1) + getCommitStatues must_== Map(("user1","repo1",2) -> CommitStatusInfo(1,1,Some("default"),Some(CommitState.SUCCESS),Some("http://exmple.com/ci"),Some("exampleService"))) + + // if there are two statuses, state is none + val cs3 = dummyService.createCommitStatus("user1","repo1","feature1", "pend", CommitState.PENDING, Some("http://exmple.com/ci"), Some("exampleService"), now, user1) + getCommitStatues must_== Map(("user1","repo1",2) -> CommitStatusInfo(2,1,None,None,None,None)) + + // get only statuses in query issues + val (is3, pr3) = generateNewPullRequest("user1/repo1/master","user1/repo1/feature3") + val cs4 = dummyService.createCommitStatus("user1","repo1","feature3", "none", CommitState.PENDING, None, None, now, user1) + getCommitStatues must_== Map(("user1","repo1",2) -> CommitStatusInfo(2,1,None,None,None,None)) + } } + } } \ No newline at end of file diff --git a/src/test/scala/service/MergeServiceSpec.scala b/src/test/scala/service/MergeServiceSpec.scala index 44e30f4..9f09304 100644 --- a/src/test/scala/service/MergeServiceSpec.scala +++ b/src/test/scala/service/MergeServiceSpec.scala @@ -1,155 +1,155 @@ -package service -import org.specs2.mutable.Specification -import java.util.Date -import model._ -import util.JGitUtil -import util.Directory._ -import java.nio.file._ -import util.Implicits._ -import util.ControlUtil._ -import org.eclipse.jgit.api.Git -import org.eclipse.jgit.dircache.DirCache -import org.eclipse.jgit.lib._ -import org.eclipse.jgit.treewalk._ -import org.eclipse.jgit.revwalk._ -import org.apache.commons.io.FileUtils - -class MergeServiceSpec extends Specification { - sequential - val service = new MergeService{} - val branch = "master" - val issueId = 10 - def initRepository(owner:String, name:String) = { - val repo1Dir = getRepositoryDir(owner, name) - RepositoryCache.clear() - FileUtils.deleteQuietly(repo1Dir) - Files.createDirectories(repo1Dir.toPath()) - JGitUtil.initRepository(repo1Dir) - using(Git.open(repo1Dir)){ git => - createFile(git, s"refs/heads/master", "test.txt", "hoge" ) - git.branchCreate().setStartPoint(s"refs/heads/master").setName(s"refs/pull/${issueId}/head").call() - } - repo1Dir - } - def createFile(git:Git, branch:String, name:String, content:String){ - val builder = DirCache.newInCore.builder() - val inserter = git.getRepository.newObjectInserter() - val headId = git.getRepository.resolve(branch + "^{commit}") - builder.add(JGitUtil.createDirCacheEntry(name, FileMode.REGULAR_FILE, - inserter.insert(Constants.OBJ_BLOB, content.getBytes("UTF-8")))) - builder.finish() - JGitUtil.createNewCommit(git, inserter, headId, builder.getDirCache.writeTree(inserter), - branch, "dummy", "dummy@example.com", "Initial commit") - } - def getFile(git:Git, branch:String, path:String) = { - val revCommit = JGitUtil.getRevCommitFromId(git, git.getRepository.resolve(branch)) - val objectId = using(new TreeWalk(git.getRepository)){ walk => - walk.addTree(revCommit.getTree) - walk.setRecursive(true) - @scala.annotation.tailrec - def _getPathObjectId: ObjectId = walk.next match { - case true if(walk.getPathString == path) => walk.getObjectId(0) - case true => _getPathObjectId - case false => throw new Exception(s"not found ${branch} / ${path}") - } - _getPathObjectId - } - JGitUtil.getContentInfo(git, path, objectId) - } - def createConfrict(git:Git) = { - createFile(git, s"refs/heads/${branch}", "test.txt", "hoge2" ) - createFile(git, s"refs/pull/${issueId}/head", "test.txt", "hoge4" ) - } - "checkConflict, checkConflictCache" should { - "checkConflict false if not conflicted, and create cache" in { - val repo1Dir = initRepository("user1","repo1") - service.checkConflictCache("user1", "repo1", branch, issueId) mustEqual None - val conflicted = service.checkConflict("user1", "repo1", branch, issueId) - service.checkConflictCache("user1", "repo1", branch, issueId) mustEqual Some(false) - conflicted mustEqual false - } - "checkConflict true if not conflicted, and create cache" in { - val repo1Dir = initRepository("user1","repo1") - using(Git.open(repo1Dir)){ git => - createConfrict(git) - } - service.checkConflictCache("user1", "repo1", branch, issueId) mustEqual None - val conflicted = service.checkConflict("user1", "repo1", branch, issueId) - conflicted mustEqual true - service.checkConflictCache("user1", "repo1", branch, issueId) mustEqual Some(true) - } - } - "checkConflictCache" should { - "merged cache invalid if origin branch moved" in { - val repo1Dir = initRepository("user1","repo1") - service.checkConflict("user1", "repo1", branch, issueId) mustEqual false - service.checkConflictCache("user1", "repo1", branch, issueId) mustEqual Some(false) - using(Git.open(repo1Dir)){ git => - createFile(git, s"refs/heads/${branch}", "test.txt", "hoge2" ) - } - service.checkConflictCache("user1", "repo1", branch, issueId) mustEqual None - } - "merged cache invalid if request branch moved" in { - val repo1Dir = initRepository("user1","repo1") - service.checkConflict("user1", "repo1", branch, issueId) mustEqual false - service.checkConflictCache("user1", "repo1", branch, issueId) mustEqual Some(false) - using(Git.open(repo1Dir)){ git => - createFile(git, s"refs/pull/${issueId}/head", "test.txt", "hoge4" ) - } - service.checkConflictCache("user1", "repo1", branch, issueId) mustEqual None - } - "merged cache invalid if origin branch moved" in { - val repo1Dir = initRepository("user1","repo1") - service.checkConflict("user1", "repo1", branch, issueId) mustEqual false - service.checkConflictCache("user1", "repo1", branch, issueId) mustEqual Some(false) - using(Git.open(repo1Dir)){ git => - createFile(git, s"refs/heads/${branch}", "test.txt", "hoge2" ) - } - service.checkConflictCache("user1", "repo1", branch, issueId) mustEqual None - } - "conflicted cache invalid if request branch moved" in { - val repo1Dir = initRepository("user1","repo1") - using(Git.open(repo1Dir)){ git => - createConfrict(git) - } - service.checkConflict("user1", "repo1", branch, issueId) mustEqual true - service.checkConflictCache("user1", "repo1", branch, issueId) mustEqual Some(true) - using(Git.open(repo1Dir)){ git => - createFile(git, s"refs/pull/${issueId}/head", "test.txt", "hoge4" ) - } - service.checkConflictCache("user1", "repo1", branch, issueId) mustEqual None - } - "conflicted cache invalid if origin branch moved" in { - val repo1Dir = initRepository("user1","repo1") - using(Git.open(repo1Dir)){ git => - createConfrict(git) - } - service.checkConflict("user1", "repo1", branch, issueId) mustEqual true - service.checkConflictCache("user1", "repo1", branch, issueId) mustEqual Some(true) - using(Git.open(repo1Dir)){ git => - createFile(git, s"refs/heads/${branch}", "test.txt", "hoge4" ) - } - service.checkConflictCache("user1", "repo1", branch, issueId) mustEqual None - } - } - "mergePullRequest" should { - "can merge" in { - val repo1Dir = initRepository("user1","repo1") - using(Git.open(repo1Dir)){ git => - createFile(git, s"refs/pull/${issueId}/head", "test.txt", "hoge2" ) - val committer = new PersonIdent("dummy2", "dummy2@example.com") - getFile(git, branch, "test.txt").content.get mustEqual "hoge" - val requestBranchId = git.getRepository.resolve(s"refs/pull/${issueId}/head") - val masterId = git.getRepository.resolve(branch) - service.mergePullRequest(git, branch, issueId, "merged", committer) - val lastCommitId = git.getRepository.resolve(branch); - val commit = using(new RevWalk(git.getRepository))(_.parseCommit(lastCommitId)) - commit.getCommitterIdent() mustEqual committer - commit.getAuthorIdent() mustEqual committer - commit.getFullMessage() mustEqual "merged" - commit.getParents.toSet mustEqual Set( requestBranchId, masterId ) - getFile(git, branch, "test.txt").content.get mustEqual "hoge2" - } - } - } +package service +import org.specs2.mutable.Specification +import java.util.Date +import model._ +import util.JGitUtil +import util.Directory._ +import java.nio.file._ +import util.Implicits._ +import util.ControlUtil._ +import org.eclipse.jgit.api.Git +import org.eclipse.jgit.dircache.DirCache +import org.eclipse.jgit.lib._ +import org.eclipse.jgit.treewalk._ +import org.eclipse.jgit.revwalk._ +import org.apache.commons.io.FileUtils + +class MergeServiceSpec extends Specification { + sequential + val service = new MergeService{} + val branch = "master" + val issueId = 10 + def initRepository(owner:String, name:String) = { + val repo1Dir = getRepositoryDir(owner, name) + RepositoryCache.clear() + FileUtils.deleteQuietly(repo1Dir) + Files.createDirectories(repo1Dir.toPath()) + JGitUtil.initRepository(repo1Dir) + using(Git.open(repo1Dir)){ git => + createFile(git, s"refs/heads/master", "test.txt", "hoge" ) + git.branchCreate().setStartPoint(s"refs/heads/master").setName(s"refs/pull/${issueId}/head").call() + } + repo1Dir + } + def createFile(git:Git, branch:String, name:String, content:String){ + val builder = DirCache.newInCore.builder() + val inserter = git.getRepository.newObjectInserter() + val headId = git.getRepository.resolve(branch + "^{commit}") + builder.add(JGitUtil.createDirCacheEntry(name, FileMode.REGULAR_FILE, + inserter.insert(Constants.OBJ_BLOB, content.getBytes("UTF-8")))) + builder.finish() + JGitUtil.createNewCommit(git, inserter, headId, builder.getDirCache.writeTree(inserter), + branch, "dummy", "dummy@example.com", "Initial commit") + } + def getFile(git:Git, branch:String, path:String) = { + val revCommit = JGitUtil.getRevCommitFromId(git, git.getRepository.resolve(branch)) + val objectId = using(new TreeWalk(git.getRepository)){ walk => + walk.addTree(revCommit.getTree) + walk.setRecursive(true) + @scala.annotation.tailrec + def _getPathObjectId: ObjectId = walk.next match { + case true if(walk.getPathString == path) => walk.getObjectId(0) + case true => _getPathObjectId + case false => throw new Exception(s"not found ${branch} / ${path}") + } + _getPathObjectId + } + JGitUtil.getContentInfo(git, path, objectId) + } + def createConfrict(git:Git) = { + createFile(git, s"refs/heads/${branch}", "test.txt", "hoge2" ) + createFile(git, s"refs/pull/${issueId}/head", "test.txt", "hoge4" ) + } + "checkConflict, checkConflictCache" should { + "checkConflict false if not conflicted, and create cache" in { + val repo1Dir = initRepository("user1","repo1") + service.checkConflictCache("user1", "repo1", branch, issueId) mustEqual None + val conflicted = service.checkConflict("user1", "repo1", branch, issueId) + service.checkConflictCache("user1", "repo1", branch, issueId) mustEqual Some(false) + conflicted mustEqual false + } + "checkConflict true if not conflicted, and create cache" in { + val repo1Dir = initRepository("user1","repo1") + using(Git.open(repo1Dir)){ git => + createConfrict(git) + } + service.checkConflictCache("user1", "repo1", branch, issueId) mustEqual None + val conflicted = service.checkConflict("user1", "repo1", branch, issueId) + conflicted mustEqual true + service.checkConflictCache("user1", "repo1", branch, issueId) mustEqual Some(true) + } + } + "checkConflictCache" should { + "merged cache invalid if origin branch moved" in { + val repo1Dir = initRepository("user1","repo1") + service.checkConflict("user1", "repo1", branch, issueId) mustEqual false + service.checkConflictCache("user1", "repo1", branch, issueId) mustEqual Some(false) + using(Git.open(repo1Dir)){ git => + createFile(git, s"refs/heads/${branch}", "test.txt", "hoge2" ) + } + service.checkConflictCache("user1", "repo1", branch, issueId) mustEqual None + } + "merged cache invalid if request branch moved" in { + val repo1Dir = initRepository("user1","repo1") + service.checkConflict("user1", "repo1", branch, issueId) mustEqual false + service.checkConflictCache("user1", "repo1", branch, issueId) mustEqual Some(false) + using(Git.open(repo1Dir)){ git => + createFile(git, s"refs/pull/${issueId}/head", "test.txt", "hoge4" ) + } + service.checkConflictCache("user1", "repo1", branch, issueId) mustEqual None + } + "merged cache invalid if origin branch moved" in { + val repo1Dir = initRepository("user1","repo1") + service.checkConflict("user1", "repo1", branch, issueId) mustEqual false + service.checkConflictCache("user1", "repo1", branch, issueId) mustEqual Some(false) + using(Git.open(repo1Dir)){ git => + createFile(git, s"refs/heads/${branch}", "test.txt", "hoge2" ) + } + service.checkConflictCache("user1", "repo1", branch, issueId) mustEqual None + } + "conflicted cache invalid if request branch moved" in { + val repo1Dir = initRepository("user1","repo1") + using(Git.open(repo1Dir)){ git => + createConfrict(git) + } + service.checkConflict("user1", "repo1", branch, issueId) mustEqual true + service.checkConflictCache("user1", "repo1", branch, issueId) mustEqual Some(true) + using(Git.open(repo1Dir)){ git => + createFile(git, s"refs/pull/${issueId}/head", "test.txt", "hoge4" ) + } + service.checkConflictCache("user1", "repo1", branch, issueId) mustEqual None + } + "conflicted cache invalid if origin branch moved" in { + val repo1Dir = initRepository("user1","repo1") + using(Git.open(repo1Dir)){ git => + createConfrict(git) + } + service.checkConflict("user1", "repo1", branch, issueId) mustEqual true + service.checkConflictCache("user1", "repo1", branch, issueId) mustEqual Some(true) + using(Git.open(repo1Dir)){ git => + createFile(git, s"refs/heads/${branch}", "test.txt", "hoge4" ) + } + service.checkConflictCache("user1", "repo1", branch, issueId) mustEqual None + } + } + "mergePullRequest" should { + "can merge" in { + val repo1Dir = initRepository("user1","repo1") + using(Git.open(repo1Dir)){ git => + createFile(git, s"refs/pull/${issueId}/head", "test.txt", "hoge2" ) + val committer = new PersonIdent("dummy2", "dummy2@example.com") + getFile(git, branch, "test.txt").content.get mustEqual "hoge" + val requestBranchId = git.getRepository.resolve(s"refs/pull/${issueId}/head") + val masterId = git.getRepository.resolve(branch) + service.mergePullRequest(git, branch, issueId, "merged", committer) + val lastCommitId = git.getRepository.resolve(branch); + val commit = using(new RevWalk(git.getRepository))(_.parseCommit(lastCommitId)) + commit.getCommitterIdent() mustEqual committer + commit.getAuthorIdent() mustEqual committer + commit.getFullMessage() mustEqual "merged" + commit.getParents.toSet mustEqual Set( requestBranchId, masterId ) + getFile(git, branch, "test.txt").content.get mustEqual "hoge2" + } + } + } } \ No newline at end of file diff --git a/src/test/scala/service/RepositoryServiceSpec.scala b/src/test/scala/service/RepositoryServiceSpec.scala index 33c74bc..23a2215 100644 --- a/src/test/scala/service/RepositoryServiceSpec.scala +++ b/src/test/scala/service/RepositoryServiceSpec.scala @@ -1,33 +1,33 @@ -package service -import org.specs2.mutable.Specification -import java.util.Date -import model._ -import model.Profile._ -import profile.simple._ -class RepositoryServiceSpec extends Specification with ServiceSpecBase with RepositoryService with AccountService{ - "RepositoryService" should { - "renameRepository can rename CommitState" in { withTestDB { implicit session => - val tester = generateNewAccount("tester") - createRepository("repo","root",None,false) - val commitStatusService = new CommitStatusService{} - val id = commitStatusService.createCommitStatus( - userName = "root", - repositoryName = "repo", - sha = "0e97b8f59f7cdd709418bb59de53f741fd1c1bd7", - context = "jenkins/test", - state = CommitState.PENDING, - targetUrl = Some("http://example.com/target"), - description = Some("description"), - creator = tester, - now = new java.util.Date) - val org = commitStatusService.getCommitStatus("root","repo", id).get - renameRepository("root","repo","tester","repo2") - val neo = commitStatusService.getCommitStatus("tester","repo2", org.commitId, org.context).get - neo must_== - org.copy( - commitStatusId=neo.commitStatusId, - repositoryName="repo2", - userName="tester") - }} - } -} +package service +import org.specs2.mutable.Specification +import java.util.Date +import model._ +import model.Profile._ +import profile.simple._ +class RepositoryServiceSpec extends Specification with ServiceSpecBase with RepositoryService with AccountService{ + "RepositoryService" should { + "renameRepository can rename CommitState" in { withTestDB { implicit session => + val tester = generateNewAccount("tester") + createRepository("repo","root",None,false) + val commitStatusService = new CommitStatusService{} + val id = commitStatusService.createCommitStatus( + userName = "root", + repositoryName = "repo", + sha = "0e97b8f59f7cdd709418bb59de53f741fd1c1bd7", + context = "jenkins/test", + state = CommitState.PENDING, + targetUrl = Some("http://example.com/target"), + description = Some("description"), + creator = tester, + now = new java.util.Date) + val org = commitStatusService.getCommitStatus("root","repo", id).get + renameRepository("root","repo","tester","repo2") + val neo = commitStatusService.getCommitStatus("tester","repo2", org.commitId, org.context).get + neo must_== + org.copy( + commitStatusId=neo.commitStatusId, + repositoryName="repo2", + userName="tester") + }} + } +} diff --git a/src/test/scala/service/WebHookServiceSpec.scala b/src/test/scala/service/WebHookServiceSpec.scala index c23f708..13c587c 100644 --- a/src/test/scala/service/WebHookServiceSpec.scala +++ b/src/test/scala/service/WebHookServiceSpec.scala @@ -1,43 +1,43 @@ -package service - -import org.specs2.mutable.Specification -import java.util.Date -import model._ - -class WebHookServiceSpec extends Specification with ServiceSpecBase { - lazy val service = new WebHookPullRequestService with AccountService with RepositoryService with PullRequestService with IssuesService - - "WebHookPullRequestService.getPullRequestsByRequestForWebhook" should { - "find from request branch" in { withTestDB { implicit session => - val user1 = generateNewUserWithDBRepository("user1","repo1") - val user2 = generateNewUserWithDBRepository("user2","repo2") - val user3 = generateNewUserWithDBRepository("user3","repo3") - val (issue1, pullreq1) = generateNewPullRequest("user1/repo1/master1", "user2/repo2/master2") - val (issue3, pullreq3) = generateNewPullRequest("user3/repo3/master3", "user2/repo2/master2") - val (issue32, pullreq32) = generateNewPullRequest("user3/repo3/master32", "user2/repo2/master2") - generateNewPullRequest("user2/repo2/master2", "user1/repo1/master2") - service.addWebHookURL("user1", "repo1", "webhook1-1") - service.addWebHookURL("user1", "repo1", "webhook1-2") - service.addWebHookURL("user2", "repo2", "webhook2-1") - service.addWebHookURL("user2", "repo2", "webhook2-2") - service.addWebHookURL("user3", "repo3", "webhook3-1") - service.addWebHookURL("user3", "repo3", "webhook3-2") - - service.getPullRequestsByRequestForWebhook("user1","repo1","master1") must_== Map.empty - - var r = service.getPullRequestsByRequestForWebhook("user2","repo2","master2").mapValues(_.map(_.url).toSet) - r.size must_== 3 - r((issue1, pullreq1, user1, user2)) must_== Set("webhook1-1","webhook1-2") - r((issue3, pullreq3, user3, user2)) must_== Set("webhook3-1","webhook3-2") - r((issue32, pullreq32, user3, user2)) must_== Set("webhook3-1","webhook3-2") - - // when closed, it not founds. - service.updateClosed("user1","repo1",issue1.issueId, true) - - var r2 = service.getPullRequestsByRequestForWebhook("user2","repo2","master2").mapValues(_.map(_.url).toSet) - r2.size must_== 2 - r2((issue3, pullreq3, user3, user2)) must_== Set("webhook3-1","webhook3-2") - r2((issue32, pullreq32, user3, user2)) must_== Set("webhook3-1","webhook3-2") - } } - } +package service + +import org.specs2.mutable.Specification +import java.util.Date +import model._ + +class WebHookServiceSpec extends Specification with ServiceSpecBase { + lazy val service = new WebHookPullRequestService with AccountService with RepositoryService with PullRequestService with IssuesService + + "WebHookPullRequestService.getPullRequestsByRequestForWebhook" should { + "find from request branch" in { withTestDB { implicit session => + val user1 = generateNewUserWithDBRepository("user1","repo1") + val user2 = generateNewUserWithDBRepository("user2","repo2") + val user3 = generateNewUserWithDBRepository("user3","repo3") + val (issue1, pullreq1) = generateNewPullRequest("user1/repo1/master1", "user2/repo2/master2") + val (issue3, pullreq3) = generateNewPullRequest("user3/repo3/master3", "user2/repo2/master2") + val (issue32, pullreq32) = generateNewPullRequest("user3/repo3/master32", "user2/repo2/master2") + generateNewPullRequest("user2/repo2/master2", "user1/repo1/master2") + service.addWebHookURL("user1", "repo1", "webhook1-1") + service.addWebHookURL("user1", "repo1", "webhook1-2") + service.addWebHookURL("user2", "repo2", "webhook2-1") + service.addWebHookURL("user2", "repo2", "webhook2-2") + service.addWebHookURL("user3", "repo3", "webhook3-1") + service.addWebHookURL("user3", "repo3", "webhook3-2") + + service.getPullRequestsByRequestForWebhook("user1","repo1","master1") must_== Map.empty + + var r = service.getPullRequestsByRequestForWebhook("user2","repo2","master2").mapValues(_.map(_.url).toSet) + r.size must_== 3 + r((issue1, pullreq1, user1, user2)) must_== Set("webhook1-1","webhook1-2") + r((issue3, pullreq3, user3, user2)) must_== Set("webhook3-1","webhook3-2") + r((issue32, pullreq32, user3, user2)) must_== Set("webhook3-1","webhook3-2") + + // when closed, it not founds. + service.updateClosed("user1","repo1",issue1.issueId, true) + + var r2 = service.getPullRequestsByRequestForWebhook("user2","repo2","master2").mapValues(_.map(_.url).toSet) + r2.size must_== 2 + r2((issue3, pullreq3, user3, user2)) must_== Set("webhook3-1","webhook3-2") + r2((issue32, pullreq32, user3, user2)) must_== Set("webhook3-1","webhook3-2") + } } + } } \ No newline at end of file diff --git a/src/test/scala/util/DirectorySpec.scala b/src/test/scala/util/DirectorySpec.scala index d961ea1..c40aafe 100644 --- a/src/test/scala/util/DirectorySpec.scala +++ b/src/test/scala/util/DirectorySpec.scala @@ -1,14 +1,14 @@ -package util - -import org.specs2.mutable._ - -class DirectorySpec extends Specification { - "GitBucketHome" should { - "set under target in test scope" in { - Directory.GitBucketHome mustEqual new java.io.File("target/gitbucket_home_for_test").getAbsolutePath - } - "exists" in { - new java.io.File(Directory.GitBucketHome).exists - } - } -} +package util + +import org.specs2.mutable._ + +class DirectorySpec extends Specification { + "GitBucketHome" should { + "set under target in test scope" in { + Directory.GitBucketHome mustEqual new java.io.File("target/gitbucket_home_for_test").getAbsolutePath + } + "exists" in { + new java.io.File(Directory.GitBucketHome).exists + } + } +}