mirror of
https://github.com/gitbucket/gitbucket.git
synced 2026-01-08 08:32:20 +01:00
(api-support)change crlf
This commit is contained in:
@@ -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;
|
||||
|
||||
@@ -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)
|
||||
}
|
||||
|
||||
@@ -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)
|
||||
}
|
||||
|
||||
@@ -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)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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}")
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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))
|
||||
}
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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)
|
||||
}
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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)
|
||||
}
|
||||
|
||||
@@ -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
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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))
|
||||
|
||||
}
|
||||
|
||||
@@ -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
|
||||
)
|
||||
}
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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))
|
||||
}
|
||||
|
||||
@@ -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
|
||||
)
|
||||
|
||||
@@ -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.<<?[String].map(CommitState(_)))
|
||||
}
|
||||
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.<<?[String].map(CommitState(_)))
|
||||
}
|
||||
|
||||
@@ -1,52 +1,52 @@
|
||||
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
|
||||
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
|
||||
|
||||
@@ -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)
|
||||
|
||||
}
|
||||
@@ -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))
|
||||
}
|
||||
}
|
||||
@@ -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()
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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)
|
||||
}
|
||||
|
||||
@@ -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"){
|
||||
<div class="container">
|
||||
<div class="row-fluid">
|
||||
<div class="span3">
|
||||
@menu("application", settings.ssh)
|
||||
</div>
|
||||
<div class="span9">
|
||||
<div class="box">
|
||||
<div class="box-header">Personal access tokens</div>
|
||||
<div class="box-content">
|
||||
@if(personalTokens.isEmpty && gneratedToken.isEmpty){
|
||||
No tokens.
|
||||
}else{
|
||||
Tokens you have generated that can be used to access the GitBucket API.<hr>
|
||||
}
|
||||
@gneratedToken.map{ case (token, tokenString) =>
|
||||
<div class="alert alert-info">
|
||||
Make sure to copy your new personal access token now. You won't be able to see it again!
|
||||
</div>
|
||||
@helper.html.copy("generated-token-copy", tokenString){
|
||||
<input type="text" value="@tokenString" style="width:21em" readonly>
|
||||
}
|
||||
<a href="@path/@account.userName/_personalToken/delete/@token.accessTokenId" class="btn btn-mini btn-danger pull-right">Delete</a>
|
||||
<hr>
|
||||
}
|
||||
@personalTokens.zipWithIndex.map { case (token, i) =>
|
||||
@if(i != 0){
|
||||
<hr>
|
||||
}
|
||||
<strong>@token.note</strong>
|
||||
<a href="@path/@account.userName/_personalToken/delete/@token.accessTokenId" class="btn btn-mini btn-danger pull-right">Delete</a>
|
||||
}
|
||||
</div>
|
||||
</div>
|
||||
<form method="POST" action="@path/@account.userName/_personalToken" validate="true">
|
||||
<div class="box">
|
||||
<div class="box-header">Generate new token</div>
|
||||
<div class="box-content">
|
||||
<fieldset>
|
||||
<label for="note" class="strong">Token description</label>
|
||||
<div><span id="error-note" class="error"></span></div>
|
||||
<input type="text" name="note" id="note" style="width: 400px;"/>
|
||||
<p class="muted">What's this token for?</p>
|
||||
</fieldset>
|
||||
<input type="submit" class="btn btn-success" value="Generate token"/>
|
||||
</div>
|
||||
</div>
|
||||
</form>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
}
|
||||
@(account: model.Account, personalTokens: List[model.AccessToken], gneratedToken:Option[(model.AccessToken, String)])(implicit context: app.Context)
|
||||
@import context._
|
||||
@import view.helpers._
|
||||
@html.main("Applications"){
|
||||
<div class="container">
|
||||
<div class="row-fluid">
|
||||
<div class="span3">
|
||||
@menu("application", settings.ssh)
|
||||
</div>
|
||||
<div class="span9">
|
||||
<div class="box">
|
||||
<div class="box-header">Personal access tokens</div>
|
||||
<div class="box-content">
|
||||
@if(personalTokens.isEmpty && gneratedToken.isEmpty){
|
||||
No tokens.
|
||||
}else{
|
||||
Tokens you have generated that can be used to access the GitBucket API.<hr>
|
||||
}
|
||||
@gneratedToken.map{ case (token, tokenString) =>
|
||||
<div class="alert alert-info">
|
||||
Make sure to copy your new personal access token now. You won't be able to see it again!
|
||||
</div>
|
||||
@helper.html.copy("generated-token-copy", tokenString){
|
||||
<input type="text" value="@tokenString" style="width:21em" readonly>
|
||||
}
|
||||
<a href="@path/@account.userName/_personalToken/delete/@token.accessTokenId" class="btn btn-mini btn-danger pull-right">Delete</a>
|
||||
<hr>
|
||||
}
|
||||
@personalTokens.zipWithIndex.map { case (token, i) =>
|
||||
@if(i != 0){
|
||||
<hr>
|
||||
}
|
||||
<strong>@token.note</strong>
|
||||
<a href="@path/@account.userName/_personalToken/delete/@token.accessTokenId" class="btn btn-mini btn-danger pull-right">Delete</a>
|
||||
}
|
||||
</div>
|
||||
</div>
|
||||
<form method="POST" action="@path/@account.userName/_personalToken" validate="true">
|
||||
<div class="box">
|
||||
<div class="box-header">Generate new token</div>
|
||||
<div class="box-content">
|
||||
<fieldset>
|
||||
<label for="note" class="strong">Token description</label>
|
||||
<div><span id="error-note" class="error"></span></div>
|
||||
<input type="text" name="note" id="note" style="width: 400px;"/>
|
||||
<p class="muted">What's this token for?</p>
|
||||
</fieldset>
|
||||
<input type="submit" class="btn btn-success" value="Generate token"/>
|
||||
</div>
|
||||
</div>
|
||||
</form>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
}
|
||||
|
||||
@@ -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)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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"
|
||||
}
|
||||
}}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -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))
|
||||
}}
|
||||
}
|
||||
}
|
||||
@@ -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))
|
||||
} }
|
||||
}
|
||||
}
|
||||
@@ -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"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -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")
|
||||
}}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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")
|
||||
} }
|
||||
}
|
||||
}
|
||||
@@ -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
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user