Conflicts:
	src/main/scala/app/DashboardController.scala
This commit is contained in:
shimamoto
2013-07-30 10:51:44 +09:00
10 changed files with 90 additions and 143 deletions

View File

@@ -1,2 +1,2 @@
set SCRIPT_DIR=%~dp0 set SCRIPT_DIR=%~dp0
java -XX:+CMSClassUnloadingEnabled -XX:MaxPermSize=256m -Xmx512M -Xss2M -jar "%SCRIPT_DIR%\sbt-launch-0.12.3.jar" %* java -Dhttp.proxyHost=proxy.intellilink.co.jp -Dhttp.proxyPort=8080 -XX:+CMSClassUnloadingEnabled -XX:MaxPermSize=256m -Xmx512M -Xss2M -jar "%SCRIPT_DIR%\sbt-launch-0.12.3.jar" %*

View File

@@ -58,7 +58,7 @@ trait AccountControllerBase extends AccountManagementControllerBase with FlashMa
case _ => case _ =>
_root_.account.html.repositories(account, _root_.account.html.repositories(account,
if(account.isGroupAccount) Nil else getGroupsByUserName(userName), if(account.isGroupAccount) Nil else getGroupsByUserName(userName),
getVisibleRepositories(userName, baseUrl, context.loginAccount.map(_.userName))) getVisibleRepositories(context.loginAccount, baseUrl, Some(userName)))
} }
} getOrElse NotFound } getOrElse NotFound
} }

View File

@@ -16,19 +16,22 @@ trait IndexControllerBase extends ControllerBase {
val loginAccount = context.loginAccount val loginAccount = context.loginAccount
html.index(getRecentActivities(), html.index(getRecentActivities(),
getAccessibleRepositories(loginAccount, baseUrl), getVisibleRepositories(loginAccount, baseUrl),
loadSystemSettings(), loadSystemSettings(),
loginAccount.map{ account => getRepositoryNamesOfUser(account.userName) }.getOrElse(Nil) loginAccount.map{ account => getUserRepositories(account.userName, baseUrl) }.getOrElse(Nil)
) )
} }
/** /**
* JSON API for collaborator completion. * JSON API for collaborator completion.
*
* TODO Move to other controller?
*/ */
// TODO Move to other controller?
get("/_user/proposals")(usersOnly { get("/_user/proposals")(usersOnly {
contentType = formats("json") contentType = formats("json")
org.json4s.jackson.Serialization.write(Map("options" -> getAllUsers.filter(!_.isGroupAccount).map(_.userName).toArray)) org.json4s.jackson.Serialization.write(
Map("options" -> getAllUsers.filter(!_.isGroupAccount).map(_.userName).toArray)
)
}) })

View File

@@ -37,49 +37,29 @@ trait RepositoryViewerControllerBase extends ControllerBase {
fileList(_) fileList(_)
}) })
/**
* Displays the file list of the repository root and the specified branch.
*/
get("/:owner/:repository/tree/:id")(referrersOnly {
fileList(_, params("id"))
})
/** /**
* Displays the file list of the specified path and branch. * Displays the file list of the specified path and branch.
*/ */
get("/:owner/:repository/tree/:id/*")(referrersOnly { get("/:owner/:repository/tree/*")(referrersOnly { repository =>
fileList(_, params("id"), multiParams("splat").head) val (id, path) = splitPath(repository, multiParams("splat").head)
}) if(path.isEmpty){
fileList(repository, id)
/** } else {
* Displays the commit list of the specified branch. fileList(repository, id, path)
*/
get("/:owner/:repository/commits/:branch")(referrersOnly { repository =>
val branchName = params("branch")
val page = params.getOrElse("page", "1").toInt
JGitUtil.withGit(getRepositoryDir(repository.owner, repository.name)){ git =>
JGitUtil.getCommitLog(git, branchName, page, 30) match {
case Right((logs, hasNext)) =>
repo.html.commits(Nil, branchName, repository, logs.splitWith{ (commit1, commit2) =>
view.helpers.date(commit1.time) == view.helpers.date(commit2.time)
}, page, hasNext)
case Left(_) => NotFound
}
} }
}) })
/** /**
* Displays the commit list of the specified resource. * Displays the commit list of the specified resource.
*/ */
get("/:owner/:repository/commits/:branch/*")(referrersOnly { repository => get("/:owner/:repository/commits/*")(referrersOnly { repository =>
val branchName = params("branch") val (branchName, path) = splitPath(repository, multiParams("splat").head)
val path = multiParams("splat").head //.replaceFirst("^tree/.+?/", "")
val page = params.getOrElse("page", "1").toInt val page = params.getOrElse("page", "1").toInt
JGitUtil.withGit(getRepositoryDir(repository.owner, repository.name)){ git => JGitUtil.withGit(getRepositoryDir(repository.owner, repository.name)){ git =>
JGitUtil.getCommitLog(git, branchName, page, 30, path) match { JGitUtil.getCommitLog(git, branchName, page, 30, path) match {
case Right((logs, hasNext)) => case Right((logs, hasNext)) =>
repo.html.commits(path.split("/").toList, branchName, repository, repo.html.commits(if(path.isEmpty) Nil else path.split("/").toList, branchName, repository,
logs.splitWith{ (commit1, commit2) => logs.splitWith{ (commit1, commit2) =>
view.helpers.date(commit1.time) == view.helpers.date(commit2.time) view.helpers.date(commit1.time) == view.helpers.date(commit2.time)
}, page, hasNext) }, page, hasNext)
@@ -91,10 +71,9 @@ trait RepositoryViewerControllerBase extends ControllerBase {
/** /**
* Displays the file content of the specified branch or commit. * Displays the file content of the specified branch or commit.
*/ */
get("/:owner/:repository/blob/:id/*")(referrersOnly { repository => get("/:owner/:repository/blob/*")(referrersOnly { repository =>
val id = params("id") // branch name or commit id val (id, path) = splitPath(repository, multiParams("splat").head)
val raw = params.get("raw").getOrElse("false").toBoolean val raw = params.get("raw").getOrElse("false").toBoolean
val path = multiParams("splat").head //.replaceFirst("^tree/.+?/", "")
JGitUtil.withGit(getRepositoryDir(repository.owner, repository.name)){ git => JGitUtil.withGit(getRepositoryDir(repository.owner, repository.name)){ git =>
val revCommit = JGitUtil.getRevCommitFromId(git, git.getRepository.resolve(id)) val revCommit = JGitUtil.getRevCommitFromId(git, git.getRepository.resolve(id))
@@ -203,6 +182,16 @@ trait RepositoryViewerControllerBase extends ControllerBase {
} }
}) })
private def splitPath(repository: service.RepositoryService.RepositoryInfo, path: String): (String, String) = {
val id = repository.branchList.collectFirst {
case branch if(path == branch || path.startsWith(branch + "/")) => branch
} orElse repository.tags.collectFirst {
case tag if(path == tag.name || path.startsWith(tag.name + "/")) => tag.name
} orElse Some(path) get
(id, path.substring(id.length).replaceFirst("^/", ""))
}
/** /**
* Provides HTML of the file list. * Provides HTML of the file list.
* *

View File

@@ -53,39 +53,6 @@ trait RepositoryService { self: AccountService =>
def getRepositoryNamesOfUser(userName: String): List[String] = def getRepositoryNamesOfUser(userName: String): List[String] =
Query(Repositories) filter(_.userName is userName.bind) map (_.repositoryName) list Query(Repositories) filter(_.userName is userName.bind) map (_.repositoryName) list
/**
* Returns the list of specified user's repositories information.
*
* @param userName the user name
* @param baseUrl the base url of this application
* @param loginUserName the logged in user name
* @return the list of repository information which is sorted in descending order of lastActivityDate.
*/
def getVisibleRepositories(userName: String, baseUrl: String, loginUserName: Option[String]): List[RepositoryInfo] = {
val q1 = Repositories
.filter { t => t.userName is userName.bind }
.map { r => r }
val q2 = Collaborators
.innerJoin(Repositories).on((t1, t2) => t1.byRepository(t2.userName, t2.repositoryName))
.filter{ case (t1, t2) => t1.collaboratorName is userName.bind}
.map { case (t1, t2) => t2 }
def visibleFor(t: Repositories.type, loginUserName: Option[String]) = {
loginUserName match {
case Some(x) => (t.isPrivate is false.bind) || (
(t.isPrivate is true.bind) && ((t.userName is x.bind) || (Collaborators.filter { c =>
c.byRepository(t.userName, t.repositoryName) && (c.collaboratorName is x.bind)
}.exists)))
case None => (t.isPrivate is false.bind)
}
}
q1.union(q2).filter(visibleFor(_, loginUserName)).sortBy(_.lastActivityDate desc).list map { repository =>
new RepositoryInfo(JGitUtil.getRepositoryInfo(repository.userName, repository.repositoryName, baseUrl), repository)
}
}
/** /**
* Returns the specified repository information. * Returns the specified repository information.
* *
@@ -101,29 +68,46 @@ trait RepositoryService { self: AccountService =>
} }
/** /**
* Returns the list of accessible repositories information for the specified account user. * Returns the list of specified user's repositories.
* * It contains own repositories and collaboration repositories.
* @param account the account
* @param baseUrl the base url of this application
* @return the repository informations which is sorted in descending order of lastActivityDate.
*/ */
def getAccessibleRepositories(account: Option[Account], baseUrl: String): List[RepositoryInfo] = { def getUserRepositories(userName: String, baseUrl: String): List[RepositoryInfo] = {
Query(Repositories).filter { t1 =>
def newRepositoryInfo(repository: Repository): RepositoryInfo = { (t1.userName is userName.bind) ||
(Query(Collaborators).filter { t2 => t2.byRepository(t1.userName, t1.repositoryName) && (t2.collaboratorName is userName.bind)} exists)
}.sortBy(_.lastActivityDate desc).list.map{ repository =>
new RepositoryInfo(JGitUtil.getRepositoryInfo(repository.userName, repository.repositoryName, baseUrl), repository) new RepositoryInfo(JGitUtil.getRepositoryInfo(repository.userName, repository.repositoryName, baseUrl), repository)
} }
}
(account match { /**
* Returns the list of visible repositories for the specified user.
* If repositoryUserName is given then filters results by repository owner.
*
* @param loginAccount the logged in account
* @param baseUrl the base url of this application
* @param repositoryUserName the repository owner (if None then returns all repositories which are visible for logged in user)
* @return the repository information which is sorted in descending order of lastActivityDate.
*/
def getVisibleRepositories(loginAccount: Option[Account], baseUrl: String, repositoryUserName: Option[String] = None): List[RepositoryInfo] = {
val query = loginAccount match {
// for Administrators // for Administrators
case Some(x) if(x.isAdmin) => Query(Repositories) case Some(x) if(x.isAdmin) => Query(Repositories)
// for Normal Users // for Normal Users
case Some(x) if(!x.isAdmin) => case Some(x) if(!x.isAdmin) =>
Query(Repositories) filter { t => (t.isPrivate is false.bind) || Query(Repositories) filter { t => (t.isPrivate is false.bind) ||
(Query(Collaborators).filter(t2 => t2.byRepository(t.userName, t.repositoryName) && (t2.collaboratorName is x.userName.bind)) exists) (Query(Collaborators).filter { t2 => t2.byRepository(t.userName, t.repositoryName) && (t2.collaboratorName is x.userName.bind)} exists)
} }
// for Guests // for Guests
case None => Query(Repositories) filter(_.isPrivate is false.bind) case None => Query(Repositories) filter(_.isPrivate is false.bind)
}).sortBy(_.lastActivityDate desc).list.map(newRepositoryInfo _) }
val filtered = repositoryUserName.map { userName => query.filter(_.userName is userName.bind) } getOrElse query
filtered.sortBy(_.lastActivityDate desc).list.map{ repository =>
new RepositoryInfo(JGitUtil.getRepositoryInfo(repository.userName, repository.repositoryName, baseUrl), repository)
}
} }
/** /**

View File

@@ -348,51 +348,11 @@ object JGitUtil {
* @return the list of latest commit * @return the list of latest commit
*/ */
def getLatestCommitFromPaths(git: Git, paths: List[String], revision: String): Map[String, RevCommit] = { def getLatestCommitFromPaths(git: Git, paths: List[String], revision: String): Map[String, RevCommit] = {
val start = git.getRepository.resolve(revision)
val map = new scala.collection.mutable.HashMap[String, RevCommit] paths.map { path =>
val commit = git.log.add(start).addPath(path).setMaxCount(1).call.iterator.next
val revWalk = new RevWalk(git.getRepository) (path, commit)
revWalk.markStart(revWalk.parseCommit(git.getRepository.resolve(revision))) }.toMap
//revWalk.sort(RevSort.REVERSE);
val i = revWalk.iterator
while(i.hasNext && map.size != paths.length){
val commit = i.next
if(commit.getParentCount == 0){
// Initial commit
val treeWalk = new TreeWalk(git.getRepository)
treeWalk.reset()
treeWalk.setRecursive(true)
treeWalk.addTree(commit.getTree)
while (treeWalk.next) {
paths.foreach { path =>
if(treeWalk.getPathString.startsWith(path) && !map.contains(path)){
map.put(path, commit)
}
}
}
treeWalk.release
} else {
(0 to commit.getParentCount - 1).foreach { i =>
val parent = revWalk.parseCommit(commit.getParent(i).getId())
val df = new DiffFormatter(DisabledOutputStream.INSTANCE)
df.setRepository(git.getRepository)
df.setDiffComparator(RawTextComparator.DEFAULT)
df.setDetectRenames(true)
val diffs = df.scan(parent.getTree(), commit.getTree)
diffs.asScala.foreach { diff =>
paths.foreach { path =>
if(diff.getChangeType != ChangeType.DELETE && diff.getNewPath.startsWith(path) && !map.contains(path)){
map.put(path, commit)
}
}
}
}
}
revWalk.release
}
map.toMap
} }
/** /**

View File

@@ -12,8 +12,13 @@ trait AvatarImageProvider { self: RequestCache =>
*/ */
protected def getAvatarImageHtml(userName: String, size: Int, protected def getAvatarImageHtml(userName: String, size: Int,
mailAddress: String = "", tooltip: Boolean = false)(implicit context: app.Context): Html = { mailAddress: String = "", tooltip: Boolean = false)(implicit context: app.Context): Html = {
val src = getAccountByUserName(userName).collect { case account if(account.image.isEmpty) =>
val src = getAccountByUserName(userName).map { account =>
if(account.image.isEmpty){
s"""http://www.gravatar.com/avatar/${StringUtil.md5(account.mailAddress)}?s=${size}""" s"""http://www.gravatar.com/avatar/${StringUtil.md5(account.mailAddress)}?s=${size}"""
} else {
s"""${context.path}/${userName}/_avatar"""
}
} getOrElse { } getOrElse {
if(mailAddress.nonEmpty){ if(mailAddress.nonEmpty){
s"""http://www.gravatar.com/avatar/${StringUtil.md5(mailAddress)}?s=${size}""" s"""http://www.gravatar.com/avatar/${StringUtil.md5(mailAddress)}?s=${size}"""

View File

@@ -1,7 +1,7 @@
@(activities: List[model.Activity], @(activities: List[model.Activity],
repositories: List[service.RepositoryService.RepositoryInfo], recentRepositories: List[service.RepositoryService.RepositoryInfo],
systemSettings: service.SystemSettingsService.SystemSettings, systemSettings: service.SystemSettingsService.SystemSettings,
userRepositories: List[String])(implicit context: app.Context) userRepositories: List[service.RepositoryService.RepositoryInfo])(implicit context: app.Context)
@import context._ @import context._
@import view.helpers._ @import view.helpers._
@main("GitBucket"){ @main("GitBucket"){
@@ -28,9 +28,15 @@
<td>No repositories</td> <td>No repositories</td>
</tr> </tr>
} else { } else {
@userRepositories.map { repositoryName => @userRepositories.map { repository =>
<tr> <tr>
<td><a href="@path/@loginAccount.get.userName/@repositoryName"><strong>@repositoryName</strong></a></td> <td>
@if(repository.owner == loginAccount.get.userName){
<a href="@url(repository)"><strong>@repository.name</strong></a>
} else {
<a href="@url(repository)">@repository.owner/<strong>@repository.name</strong></a>
}
</td>
</tr> </tr>
} }
} }
@@ -43,12 +49,12 @@
Recent updated repositories Recent updated repositories
</th> </th>
</tr> </tr>
@if(repositories.isEmpty){ @if(recentRepositories.isEmpty){
<tr> <tr>
<td>No repositories</td> <td>No repositories</td>
</tr> </tr>
} else { } else {
@repositories.map { repository => @recentRepositories.map { repository =>
<tr> <tr>
<td> <td>
<a href="@url(repository)">@repository.owner/<strong>@repository.name</strong></a> <a href="@url(repository)">@repository.owner/<strong>@repository.name</strong></a>