mirror of
https://github.com/gitbucket/gitbucket.git
synced 2025-11-08 14:35:52 +01:00
Merge branch 'wip/baseurl' of https://github.com/ritschwumm/gitbucket into ritschwumm-wip/baseurl
This commit is contained in:
@@ -133,7 +133,7 @@ trait AccountControllerBase extends AccountManagementControllerBase {
|
||||
val members = getGroupMembers(account.userName)
|
||||
gitbucket.core.account.html.repositories(account,
|
||||
if(account.isGroupAccount) Nil else getGroupsByUserName(userName),
|
||||
getVisibleRepositories(context.loginAccount, context.baseUrl, Some(userName)),
|
||||
getVisibleRepositories(context.loginAccount, Some(userName)),
|
||||
context.loginAccount.exists(x => members.exists { member => member.userName == x.userName && member.isManager }))
|
||||
}
|
||||
}
|
||||
@@ -366,7 +366,7 @@ trait AccountControllerBase extends AccountManagementControllerBase {
|
||||
*/
|
||||
post("/new", newRepositoryForm)(usersOnly { form =>
|
||||
LockUtil.lock(s"${form.owner}/${form.name}"){
|
||||
if(getRepository(form.owner, form.name, context.baseUrl).isEmpty){
|
||||
if(getRepository(form.owner, form.name).isEmpty){
|
||||
createRepository(form.owner, form.name, form.description, form.isPrivate, form.createReadme)
|
||||
}
|
||||
|
||||
@@ -385,9 +385,9 @@ trait AccountControllerBase extends AccountManagementControllerBase {
|
||||
data <- extractFromJsonBody[CreateARepository] if data.isValid
|
||||
} yield {
|
||||
LockUtil.lock(s"${owner}/${data.name}") {
|
||||
if(getRepository(owner, data.name, context.baseUrl).isEmpty){
|
||||
if(getRepository(owner, data.name).isEmpty){
|
||||
createRepository(owner, data.name, data.description, data.`private`, data.auto_init)
|
||||
val repository = getRepository(owner, data.name, context.baseUrl).get
|
||||
val repository = getRepository(owner, data.name).get
|
||||
JsonFormat(ApiRepository(repository, ApiUser(getAccountByUserName(owner).get)))
|
||||
} else {
|
||||
ApiError(
|
||||
@@ -409,9 +409,9 @@ trait AccountControllerBase extends AccountManagementControllerBase {
|
||||
data <- extractFromJsonBody[CreateARepository] if data.isValid
|
||||
} yield {
|
||||
LockUtil.lock(s"${groupName}/${data.name}") {
|
||||
if(getRepository(groupName, data.name, context.baseUrl).isEmpty){
|
||||
if(getRepository(groupName, data.name).isEmpty){
|
||||
createRepository(groupName, data.name, data.description, data.`private`, data.auto_init)
|
||||
val repository = getRepository(groupName, data.name, context.baseUrl).get
|
||||
val repository = getRepository(groupName, data.name).get
|
||||
JsonFormat(ApiRepository(repository, ApiUser(getAccountByUserName(groupName).get)))
|
||||
} else {
|
||||
ApiError(
|
||||
@@ -447,7 +447,7 @@ trait AccountControllerBase extends AccountManagementControllerBase {
|
||||
val accountName = form.accountName
|
||||
|
||||
LockUtil.lock(s"${accountName}/${repository.name}"){
|
||||
if(getRepository(accountName, repository.name, baseUrl).isDefined ||
|
||||
if(getRepository(accountName, repository.name).isDefined ||
|
||||
(accountName != loginUserName && !getGroupsByUserName(loginUserName).contains(accountName))){
|
||||
// redirect to the repository if repository already exists
|
||||
redirect(s"/${accountName}/${repository.name}")
|
||||
|
||||
@@ -3,6 +3,7 @@ package gitbucket.core.controller
|
||||
import gitbucket.core.api.ApiError
|
||||
import gitbucket.core.model.Account
|
||||
import gitbucket.core.service.{AccountService, SystemSettingsService}
|
||||
import gitbucket.core.service.RepositoryService.{RepositoryInfo, RepositoryUrls}
|
||||
import gitbucket.core.util.ControlUtil._
|
||||
import gitbucket.core.util.Directory._
|
||||
import gitbucket.core.util.Implicits._
|
||||
@@ -180,11 +181,12 @@ abstract class ControllerBase extends ScalatraFilter
|
||||
* Context object for the current request.
|
||||
*/
|
||||
case class Context(settings: SystemSettingsService.SystemSettings, loginAccount: Option[Account], request: HttpServletRequest){
|
||||
|
||||
val path = settings.baseUrl.getOrElse(request.getContextPath)
|
||||
val currentPath = request.getRequestURI.substring(request.getContextPath.length)
|
||||
val baseUrl = settings.baseUrl(request)
|
||||
val host = new java.net.URL(baseUrl).getHost
|
||||
val urls = (repositoryInfo:RepositoryInfo) => new RepositoryUrls(baseUrl, settings.sshAddress, repositoryInfo.owner, repositoryInfo.name)
|
||||
val wikiUrls = (repositoryInfo:RepositoryInfo) => new RepositoryUrls(baseUrl, settings.sshAddress, repositoryInfo.owner, repositoryInfo.name + ".wiki")
|
||||
val platform = request.getHeader("User-Agent") match {
|
||||
case null => null
|
||||
case agent if agent.contains("Mac") => "mac"
|
||||
|
||||
@@ -94,7 +94,7 @@ trait DashboardControllerBase extends ControllerBase {
|
||||
|
||||
val userName = context.loginAccount.get.userName
|
||||
val condition = getOrCreateCondition(Keys.Session.DashboardIssues, filter, userName)
|
||||
val userRepos = getUserRepositories(userName, context.baseUrl, true).map(repo => repo.owner -> repo.name)
|
||||
val userRepos = getUserRepositories(userName, true).map(repo => repo.owner -> repo.name)
|
||||
val page = IssueSearchCondition.page(request)
|
||||
|
||||
html.issues(
|
||||
|
||||
@@ -29,8 +29,8 @@ trait IndexControllerBase extends ControllerBase {
|
||||
val loginAccount = context.loginAccount
|
||||
if(loginAccount.isEmpty) {
|
||||
html.index(getRecentActivities(),
|
||||
getVisibleRepositories(loginAccount, context.baseUrl, withoutPhysicalInfo = true),
|
||||
loginAccount.map{ account => getUserRepositories(account.userName, context.baseUrl, withoutPhysicalInfo = true) }.getOrElse(Nil)
|
||||
getVisibleRepositories(loginAccount, withoutPhysicalInfo = true),
|
||||
loginAccount.map{ account => getUserRepositories(account.userName, withoutPhysicalInfo = true) }.getOrElse(Nil)
|
||||
)
|
||||
} else {
|
||||
val loginUserName = loginAccount.get.userName
|
||||
@@ -40,8 +40,8 @@ trait IndexControllerBase extends ControllerBase {
|
||||
visibleOwnerSet ++= loginUserGroups
|
||||
|
||||
html.index(getRecentActivitiesByOwners(visibleOwnerSet),
|
||||
getVisibleRepositories(loginAccount, context.baseUrl, withoutPhysicalInfo = true),
|
||||
loginAccount.map{ account => getUserRepositories(account.userName, context.baseUrl, withoutPhysicalInfo = true) }.getOrElse(Nil)
|
||||
getVisibleRepositories(loginAccount, withoutPhysicalInfo = true),
|
||||
loginAccount.map{ account => getUserRepositories(account.userName, withoutPhysicalInfo = true) }.getOrElse(Nil)
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -137,7 +137,7 @@ trait PullRequestsControllerBase extends ControllerBase {
|
||||
baseOwner <- users.get(repository.owner)
|
||||
headOwner <- users.get(pullRequest.requestUserName)
|
||||
issueUser <- users.get(issue.openedUserName)
|
||||
headRepo <- getRepository(pullRequest.requestUserName, pullRequest.requestRepositoryName, baseUrl)
|
||||
headRepo <- getRepository(pullRequest.requestUserName, pullRequest.requestRepositoryName)
|
||||
} yield {
|
||||
JsonFormat(ApiPullRequest(
|
||||
issue,
|
||||
@@ -196,7 +196,7 @@ trait PullRequestsControllerBase extends ControllerBase {
|
||||
issue,
|
||||
pullreq,
|
||||
repository,
|
||||
getRepository(pullreq.requestUserName, pullreq.requestRepositoryName, context.baseUrl).get)
|
||||
getRepository(pullreq.requestUserName, pullreq.requestRepositoryName).get)
|
||||
}
|
||||
} getOrElse NotFound
|
||||
})
|
||||
@@ -229,7 +229,7 @@ trait PullRequestsControllerBase extends ControllerBase {
|
||||
if(branchProtection.needStatusCheck(loginAccount.userName)){
|
||||
flash += "error" -> s"branch ${pullreq.requestBranch} is protected need status check."
|
||||
} else {
|
||||
val repository = getRepository(owner, name, context.baseUrl).get
|
||||
val repository = getRepository(owner, name).get
|
||||
LockUtil.lock(s"${owner}/${name}"){
|
||||
val alias = if(pullreq.repositoryName == pullreq.requestRepositoryName && pullreq.userName == pullreq.requestUserName){
|
||||
pullreq.branch
|
||||
@@ -310,7 +310,7 @@ trait PullRequestsControllerBase extends ControllerBase {
|
||||
pullreq.requestUserName, pullreq.requestRepositoryName, pullreq.commitIdTo)
|
||||
|
||||
// close issue by content of pull request
|
||||
val defaultBranch = getRepository(owner, name, context.baseUrl).get.repository.defaultBranch
|
||||
val defaultBranch = getRepository(owner, name).get.repository.defaultBranch
|
||||
if(pullreq.branch == defaultBranch){
|
||||
commits.flatten.foreach { commit =>
|
||||
closeIssuesFromMessage(commit.fullMessage, loginAccount.userName, owner, name)
|
||||
@@ -343,7 +343,7 @@ trait PullRequestsControllerBase extends ControllerBase {
|
||||
val headBranch:Option[String] = params.get("head")
|
||||
(forkedRepository.repository.originUserName, forkedRepository.repository.originRepositoryName) match {
|
||||
case (Some(originUserName), Some(originRepositoryName)) => {
|
||||
getRepository(originUserName, originRepositoryName, context.baseUrl).map { originRepository =>
|
||||
getRepository(originUserName, originRepositoryName).map { originRepository =>
|
||||
using(
|
||||
Git.open(getRepositoryDir(originUserName, originRepositoryName)),
|
||||
Git.open(getRepositoryDir(forkedRepository.owner, forkedRepository.name))
|
||||
@@ -384,12 +384,12 @@ trait PullRequestsControllerBase extends ControllerBase {
|
||||
forkedRepository.repository.originRepositoryName
|
||||
} else {
|
||||
// Sibling repository
|
||||
getUserRepositories(originOwner, context.baseUrl).find { x =>
|
||||
getUserRepositories(originOwner).find { x =>
|
||||
x.repository.originUserName == forkedRepository.repository.originUserName &&
|
||||
x.repository.originRepositoryName == forkedRepository.repository.originRepositoryName
|
||||
}.map(_.repository.repositoryName)
|
||||
};
|
||||
originRepository <- getRepository(originOwner, originRepositoryName, context.baseUrl)
|
||||
originRepository <- getRepository(originOwner, originRepositoryName)
|
||||
) yield {
|
||||
using(
|
||||
Git.open(getRepositoryDir(originRepository.owner, originRepository.name)),
|
||||
@@ -457,7 +457,7 @@ trait PullRequestsControllerBase extends ControllerBase {
|
||||
getForkedRepositories(forkedRepository.owner, forkedRepository.name).find(_._1 == originOwner).map(_._2)
|
||||
}
|
||||
};
|
||||
originRepository <- getRepository(originOwner, originRepositoryName, context.baseUrl)
|
||||
originRepository <- getRepository(originOwner, originRepositoryName)
|
||||
) yield {
|
||||
using(
|
||||
Git.open(getRepositoryDir(originRepository.owner, originRepository.name)),
|
||||
|
||||
@@ -560,8 +560,7 @@ trait RepositoryViewerControllerBase extends ControllerBase {
|
||||
html.forked(
|
||||
getRepository(
|
||||
repository.repository.originUserName.getOrElse(repository.owner),
|
||||
repository.repository.originRepositoryName.getOrElse(repository.name),
|
||||
context.baseUrl),
|
||||
repository.repository.originRepositoryName.getOrElse(repository.name)),
|
||||
getForkedRepositories(
|
||||
repository.repository.originUserName.getOrElse(repository.owner),
|
||||
repository.repository.originRepositoryName.getOrElse(repository.name)),
|
||||
|
||||
@@ -23,6 +23,7 @@ trait SystemSettingsControllerBase extends ControllerBase {
|
||||
"notification" -> trim(label("Notification", boolean())),
|
||||
"activityLogLimit" -> trim(label("Limit of activity logs", optional(number()))),
|
||||
"ssh" -> trim(label("SSH access", boolean())),
|
||||
"sshHost" -> trim(label("SSH host", optional(text()))),
|
||||
"sshPort" -> trim(label("SSH port", optional(number()))),
|
||||
"useSMTP" -> trim(label("SMTP", boolean())),
|
||||
"smtp" -> optionalIfNotChecked("useSMTP", mapping(
|
||||
@@ -50,9 +51,14 @@ trait SystemSettingsControllerBase extends ControllerBase {
|
||||
"keystore" -> trim(label("Keystore", optional(text())))
|
||||
)(Ldap.apply))
|
||||
)(SystemSettings.apply).verifying { settings =>
|
||||
if(settings.ssh && settings.baseUrl.isEmpty){
|
||||
Seq("baseUrl" -> "Base URL is required if SSH access is enabled.")
|
||||
} else Nil
|
||||
Vector(
|
||||
if(settings.ssh && settings.baseUrl.isEmpty){
|
||||
Some("baseUrl" -> "Base URL is required if SSH access is enabled.")
|
||||
} else None,
|
||||
if(settings.ssh && settings.sshHost.isEmpty){
|
||||
Some("sshHost" -> "SSH host is required if SSH access is enabled.")
|
||||
} else None
|
||||
).flatten
|
||||
}
|
||||
|
||||
private val pluginForm = mapping(
|
||||
@@ -68,16 +74,13 @@ trait SystemSettingsControllerBase extends ControllerBase {
|
||||
post("/admin/system", form)(adminOnly { form =>
|
||||
saveSystemSettings(form)
|
||||
|
||||
if(form.ssh && SshServer.isActive && context.settings.sshPort != form.sshPort){
|
||||
SshServer.stop()
|
||||
}
|
||||
|
||||
if(form.ssh && !SshServer.isActive && form.baseUrl.isDefined){
|
||||
SshServer.start(
|
||||
form.sshPort.getOrElse(SystemSettingsService.DefaultSshPort),
|
||||
form.baseUrl.get)
|
||||
} else if(!form.ssh && SshServer.isActive){
|
||||
if (form.sshAddress != context.settings.sshAddress) {
|
||||
SshServer.stop()
|
||||
for {
|
||||
sshAddress <- form.sshAddress
|
||||
baseUrl <- form.baseUrl
|
||||
}
|
||||
SshServer.start(sshAddress, baseUrl)
|
||||
}
|
||||
|
||||
flash += "info" -> "System settings has been updated."
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
package gitbucket.core.service
|
||||
|
||||
import gitbucket.core.service.SystemSettingsService.SshAddress
|
||||
import gitbucket.core.model.{Collaborator, Repository, Account}
|
||||
import gitbucket.core.model.Profile._
|
||||
import gitbucket.core.util.JGitUtil
|
||||
@@ -194,10 +195,9 @@ trait RepositoryService { self: AccountService =>
|
||||
*
|
||||
* @param userName the user name of the repository owner
|
||||
* @param repositoryName the repository name
|
||||
* @param baseUrl the base url of this application
|
||||
* @return the repository information
|
||||
*/
|
||||
def getRepository(userName: String, repositoryName: String, baseUrl: String)(implicit s: Session): Option[RepositoryInfo] = {
|
||||
def getRepository(userName: String, repositoryName: String)(implicit s: Session): Option[RepositoryInfo] = {
|
||||
(Repositories filter { t => t.byRepository(userName, repositoryName) } firstOption) map { repository =>
|
||||
// for getting issue count and pull request count
|
||||
val issues = Issues.filter { t =>
|
||||
@@ -205,7 +205,7 @@ trait RepositoryService { self: AccountService =>
|
||||
}.map(_.pullRequest).list
|
||||
|
||||
new RepositoryInfo(
|
||||
JGitUtil.getRepositoryInfo(repository.userName, repository.repositoryName, baseUrl),
|
||||
JGitUtil.getRepositoryInfo(repository.userName, repository.repositoryName),
|
||||
repository,
|
||||
issues.count(_ == false),
|
||||
issues.count(_ == true),
|
||||
@@ -234,7 +234,7 @@ trait RepositoryService { self: AccountService =>
|
||||
}.list
|
||||
}
|
||||
|
||||
def getUserRepositories(userName: String, baseUrl: String, withoutPhysicalInfo: Boolean = false)
|
||||
def getUserRepositories(userName: String, withoutPhysicalInfo: Boolean = false)
|
||||
(implicit s: Session): List[RepositoryInfo] = {
|
||||
Repositories.filter { t1 =>
|
||||
(t1.userName === userName.bind) ||
|
||||
@@ -242,9 +242,9 @@ trait RepositoryService { self: AccountService =>
|
||||
}.sortBy(_.lastActivityDate desc).list.map{ repository =>
|
||||
new RepositoryInfo(
|
||||
if(withoutPhysicalInfo){
|
||||
new JGitUtil.RepositoryInfo(repository.userName, repository.repositoryName, baseUrl)
|
||||
new JGitUtil.RepositoryInfo(repository.userName, repository.repositoryName)
|
||||
} else {
|
||||
JGitUtil.getRepositoryInfo(repository.userName, repository.repositoryName, baseUrl)
|
||||
JGitUtil.getRepositoryInfo(repository.userName, repository.repositoryName)
|
||||
},
|
||||
repository,
|
||||
getForkedCount(
|
||||
@@ -260,13 +260,12 @@ trait RepositoryService { self: AccountService =>
|
||||
* 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)
|
||||
* @param withoutPhysicalInfo if true then the result does not include physical repository information such as commit count,
|
||||
* branches and tags
|
||||
* @return the repository information which is sorted in descending order of lastActivityDate.
|
||||
*/
|
||||
def getVisibleRepositories(loginAccount: Option[Account], baseUrl: String, repositoryUserName: Option[String] = None,
|
||||
def getVisibleRepositories(loginAccount: Option[Account], repositoryUserName: Option[String] = None,
|
||||
withoutPhysicalInfo: Boolean = false)
|
||||
(implicit s: Session): List[RepositoryInfo] = {
|
||||
(loginAccount match {
|
||||
@@ -284,9 +283,9 @@ trait RepositoryService { self: AccountService =>
|
||||
}.sortBy(_.lastActivityDate desc).list.map{ repository =>
|
||||
new RepositoryInfo(
|
||||
if(withoutPhysicalInfo){
|
||||
new JGitUtil.RepositoryInfo(repository.userName, repository.repositoryName, baseUrl)
|
||||
new JGitUtil.RepositoryInfo(repository.userName, repository.repositoryName)
|
||||
} else {
|
||||
JGitUtil.getRepositoryInfo(repository.userName, repository.repositoryName, baseUrl)
|
||||
JGitUtil.getRepositoryInfo(repository.userName, repository.repositoryName)
|
||||
},
|
||||
repository,
|
||||
getForkedCount(
|
||||
@@ -389,31 +388,45 @@ trait RepositoryService { self: AccountService =>
|
||||
|
||||
object RepositoryService {
|
||||
|
||||
case class RepositoryInfo(owner: String, name: String, httpUrl: String, repository: Repository,
|
||||
case class RepositoryInfo(owner: String, name: String, repository: Repository,
|
||||
issueCount: Int, pullCount: Int, commitCount: Int, forkedCount: Int,
|
||||
branchList: Seq[String], tags: Seq[JGitUtil.TagInfo], managers: Seq[String]){
|
||||
|
||||
lazy val host = """^https?://(.+?)(:\d+)?/""".r.findFirstMatchIn(httpUrl).get.group(1)
|
||||
|
||||
def sshUrl(port: Int, userName: String) = s"ssh://${userName}@${host}:${port}/${owner}/${name}.git"
|
||||
|
||||
def sshOpenRepoUrl(platform: String, port: Int, userName: String) = openRepoUrl(platform, sshUrl(port, userName))
|
||||
|
||||
def httpOpenRepoUrl(platform: String) = openRepoUrl(platform, httpUrl)
|
||||
|
||||
def openRepoUrl(platform: String, openUrl: String) = s"github-${platform}://openRepo/${openUrl}"
|
||||
branchList: Seq[String], tags: Seq[JGitUtil.TagInfo], managers: Seq[String]) {
|
||||
|
||||
/**
|
||||
* Creates instance with issue count and pull request count.
|
||||
*/
|
||||
def this(repo: JGitUtil.RepositoryInfo, model: Repository, issueCount: Int, pullCount: Int, forkedCount: Int, managers: Seq[String]) =
|
||||
this(repo.owner, repo.name, repo.url, model, issueCount, pullCount, repo.commitCount, forkedCount, repo.branchList, repo.tags, managers)
|
||||
this(
|
||||
repo.owner, repo.name, model,
|
||||
issueCount, pullCount,
|
||||
repo.commitCount, forkedCount, repo.branchList, repo.tags, managers)
|
||||
|
||||
/**
|
||||
* Creates instance without issue count and pull request count.
|
||||
*/
|
||||
def this(repo: JGitUtil.RepositoryInfo, model: Repository, forkedCount: Int, managers: Seq[String]) =
|
||||
this(repo.owner, repo.name, repo.url, model, 0, 0, repo.commitCount, forkedCount, repo.branchList, repo.tags, managers)
|
||||
def this(repo: JGitUtil.RepositoryInfo, model: Repository, forkedCount: Int, managers: Seq[String]) =
|
||||
this(
|
||||
repo.owner, repo.name, model,
|
||||
0, 0,
|
||||
repo.commitCount, forkedCount, repo.branchList, repo.tags, managers)
|
||||
}
|
||||
|
||||
final class RepositoryUrls(baseUrl:String, sshAddress:Option[SshAddress], owner:String, name:String) {
|
||||
def httpUrl:String =
|
||||
s"${baseUrl}/git/${owner}/${name}.git"
|
||||
|
||||
// BETTER make this return an Option and use it in the gui
|
||||
def sshUrl(userName: String):String =
|
||||
sshAddress.fold("")(adr => s"ssh://${userName}@${adr.host}:${adr.port}/${owner}/${name}.git")
|
||||
|
||||
def sshOpenRepoUrl(platform: String, userName: String) =
|
||||
openRepoUrl(platform, sshUrl(userName))
|
||||
|
||||
def httpOpenRepoUrl(platform: String) =
|
||||
openRepoUrl(platform, httpUrl)
|
||||
|
||||
private def openRepoUrl(platform: String, openUrl: String) =
|
||||
s"github-${platform}://openRepo/${openUrl}"
|
||||
}
|
||||
|
||||
case class RepositoryTreeNode(owner: String, name: String, children: List[RepositoryTreeNode])
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
package gitbucket.core.service
|
||||
|
||||
import gitbucket.core.util.{Directory, ControlUtil}
|
||||
import gitbucket.core.util.Implicits._
|
||||
import Directory._
|
||||
import ControlUtil._
|
||||
import SystemSettingsService._
|
||||
@@ -21,6 +22,7 @@ trait SystemSettingsService {
|
||||
props.setProperty(Notification, settings.notification.toString)
|
||||
settings.activityLogLimit.foreach(x => props.setProperty(ActivityLogLimit, x.toString))
|
||||
props.setProperty(Ssh, settings.ssh.toString)
|
||||
settings.sshHost.foreach(x => props.setProperty(SshHost, x.trim))
|
||||
settings.sshPort.foreach(x => props.setProperty(SshPort, x.toString))
|
||||
props.setProperty(UseSMTP, settings.useSMTP.toString)
|
||||
if(settings.useSMTP) {
|
||||
@@ -75,6 +77,7 @@ trait SystemSettingsService {
|
||||
getValue(props, Notification, false),
|
||||
getOptionValue[Int](props, ActivityLogLimit, None),
|
||||
getValue(props, Ssh, false),
|
||||
getOptionValue[String](props, SshHost, None).map(_.trim),
|
||||
getOptionValue(props, SshPort, Some(DefaultSshPort)),
|
||||
getValue(props, UseSMTP, getValue(props, Notification, false)), // handle migration scenario from only notification to useSMTP
|
||||
if(getValue(props, UseSMTP, getValue(props, Notification, false))){
|
||||
@@ -126,16 +129,20 @@ object SystemSettingsService {
|
||||
notification: Boolean,
|
||||
activityLogLimit: Option[Int],
|
||||
ssh: Boolean,
|
||||
sshHost: Option[String],
|
||||
sshPort: Option[Int],
|
||||
useSMTP: Boolean,
|
||||
smtp: Option[Smtp],
|
||||
ldapAuthentication: Boolean,
|
||||
ldap: Option[Ldap]){
|
||||
def baseUrl(request: HttpServletRequest): String = baseUrl.getOrElse {
|
||||
defining(request.getRequestURL.toString){ url =>
|
||||
url.substring(0, url.length - (request.getRequestURI.length - request.getContextPath.length))
|
||||
def baseUrl(request: HttpServletRequest): String = baseUrl.fold(request.baseUrl)(_.stripSuffix("/"))
|
||||
|
||||
def sshAddress:Option[SshAddress] =
|
||||
for {
|
||||
host <- sshHost
|
||||
if ssh
|
||||
}
|
||||
}.stripSuffix("/")
|
||||
yield SshAddress(host, sshPort.getOrElse(DefaultSshPort))
|
||||
}
|
||||
|
||||
case class Ldap(
|
||||
@@ -161,6 +168,10 @@ object SystemSettingsService {
|
||||
fromAddress: Option[String],
|
||||
fromName: Option[String])
|
||||
|
||||
case class SshAddress(
|
||||
host:String,
|
||||
port:Int)
|
||||
|
||||
val DefaultSshPort = 29418
|
||||
val DefaultSmtpPort = 25
|
||||
val DefaultLdapPort = 389
|
||||
@@ -174,6 +185,7 @@ object SystemSettingsService {
|
||||
private val Notification = "notification"
|
||||
private val ActivityLogLimit = "activity_log_limit"
|
||||
private val Ssh = "ssh"
|
||||
private val SshHost = "ssh.host"
|
||||
private val SshPort = "ssh.port"
|
||||
private val UseSMTP = "useSMTP"
|
||||
private val SmtpHost = "smtp.host"
|
||||
|
||||
@@ -161,7 +161,7 @@ trait WebHookPullRequestService extends WebHookService {
|
||||
baseOwner <- users.get(repository.owner)
|
||||
headOwner <- users.get(pullRequest.requestUserName)
|
||||
issueUser <- users.get(issue.openedUserName)
|
||||
headRepo <- getRepository(pullRequest.requestUserName, pullRequest.requestRepositoryName, baseUrl)
|
||||
headRepo <- getRepository(pullRequest.requestUserName, pullRequest.requestRepositoryName)
|
||||
} yield {
|
||||
WebHookPullRequestPayload(
|
||||
action = action,
|
||||
@@ -200,7 +200,7 @@ trait WebHookPullRequestService extends WebHookService {
|
||||
import WebHookService._
|
||||
for{
|
||||
((issue, issueUser, pullRequest, baseOwner, headOwner), webHooks) <- getPullRequestsByRequestForWebhook(requestRepository.owner, requestRepository.name, requestBranch)
|
||||
baseRepo <- getRepository(pullRequest.userName, pullRequest.repositoryName, baseUrl)
|
||||
baseRepo <- getRepository(pullRequest.userName, pullRequest.repositoryName)
|
||||
} yield {
|
||||
val payload = WebHookPullRequestPayload(
|
||||
action = action,
|
||||
@@ -229,7 +229,7 @@ trait WebHookPullRequestReviewCommentService extends WebHookService {
|
||||
baseOwner <- users.get(repository.owner)
|
||||
headOwner <- users.get(pullRequest.requestUserName)
|
||||
issueUser <- users.get(issue.openedUserName)
|
||||
headRepo <- getRepository(pullRequest.requestUserName, pullRequest.requestRepositoryName, baseUrl)
|
||||
headRepo <- getRepository(pullRequest.requestUserName, pullRequest.requestRepositoryName)
|
||||
} yield {
|
||||
WebHookPullRequestReviewCommentPayload(
|
||||
action = action,
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
package gitbucket.core.service
|
||||
|
||||
import java.util.Date
|
||||
import gitbucket.core.service.SystemSettingsService.SshAddress
|
||||
import gitbucket.core.model.Account
|
||||
import gitbucket.core.util._
|
||||
import gitbucket.core.util.ControlUtil._
|
||||
@@ -14,6 +15,7 @@ import org.eclipse.jgit.patch._
|
||||
import org.eclipse.jgit.api.errors.PatchFormatException
|
||||
import scala.collection.JavaConverters._
|
||||
import RepositoryService.RepositoryInfo
|
||||
import RepositoryService.RepositoryUrls
|
||||
|
||||
object WikiService {
|
||||
|
||||
@@ -37,11 +39,6 @@ object WikiService {
|
||||
* @param date the commit date
|
||||
*/
|
||||
case class WikiPageHistoryInfo(name: String, committer: String, message: String, date: Date)
|
||||
|
||||
def httpUrl(repository: RepositoryInfo) = repository.httpUrl.replaceFirst("\\.git\\Z", ".wiki.git")
|
||||
|
||||
def sshUrl(repository: RepositoryInfo, settings: SystemSettingsService.SystemSettings, userName: String) =
|
||||
repository.sshUrl(settings.sshPort.getOrElse(SystemSettingsService.DefaultSshPort), userName).replaceFirst("\\.git\\Z", ".wiki.git")
|
||||
}
|
||||
|
||||
trait WikiService {
|
||||
|
||||
@@ -74,7 +74,7 @@ class BasicAuthenticationFilter extends Filter with RepositoryService with Accou
|
||||
|
||||
request.paths match {
|
||||
case Array(_, repositoryOwner, repositoryName, _*) =>
|
||||
getRepository(repositoryOwner, repositoryName.replaceFirst("\\.wiki\\.git$|\\.git$", ""), "") match {
|
||||
getRepository(repositoryOwner, repositoryName.replaceFirst("\\.wiki\\.git$|\\.git$", "")) match {
|
||||
case Some(repository) => {
|
||||
if(!isUpdating && !repository.repository.isPrivate && settings.allowAnonymousAccess){
|
||||
chain.doFilter(request, response)
|
||||
|
||||
@@ -160,7 +160,7 @@ class CommitLogHook(owner: String, repository: String, pusher: String, baseUrl:
|
||||
countIssue(IssueSearchCondition(state = "open"), false, owner -> repository) +
|
||||
countIssue(IssueSearchCondition(state = "closed"), false, owner -> repository)
|
||||
|
||||
val repositoryInfo = getRepository(owner, repository, baseUrl).get
|
||||
val repositoryInfo = getRepository(owner, repository).get
|
||||
|
||||
// Extract new commit and apply issue comment
|
||||
val defaultBranch = repositoryInfo.repository.defaultBranch
|
||||
|
||||
@@ -87,11 +87,11 @@ abstract class DefaultGitCommand(val owner: String, val repoName: String) extend
|
||||
}
|
||||
|
||||
|
||||
class DefaultGitUploadPack(owner: String, repoName: String, baseUrl: String) extends DefaultGitCommand(owner, repoName)
|
||||
class DefaultGitUploadPack(owner: String, repoName: String) extends DefaultGitCommand(owner, repoName)
|
||||
with RepositoryService with AccountService {
|
||||
|
||||
override protected def runTask(user: String)(implicit session: Session): Unit = {
|
||||
getRepository(owner, repoName.replaceFirst("\\.wiki\\Z", ""), baseUrl).foreach { repositoryInfo =>
|
||||
getRepository(owner, repoName.replaceFirst("\\.wiki\\Z", "")).foreach { repositoryInfo =>
|
||||
if(!repositoryInfo.repository.isPrivate || isWritableUser(user, repositoryInfo)){
|
||||
using(Git.open(getRepositoryDir(owner, repoName))) { git =>
|
||||
val repository = git.getRepository
|
||||
@@ -107,7 +107,7 @@ class DefaultGitReceivePack(owner: String, repoName: String, baseUrl: String) ex
|
||||
with RepositoryService with AccountService {
|
||||
|
||||
override protected def runTask(user: String)(implicit session: Session): Unit = {
|
||||
getRepository(owner, repoName.replaceFirst("\\.wiki\\Z", ""), baseUrl).foreach { repositoryInfo =>
|
||||
getRepository(owner, repoName.replaceFirst("\\.wiki\\Z", "")).foreach { repositoryInfo =>
|
||||
if(isWritableUser(user, repositoryInfo)){
|
||||
using(Git.open(getRepositoryDir(owner, repoName))) { git =>
|
||||
val repository = git.getRepository
|
||||
@@ -124,7 +124,7 @@ class DefaultGitReceivePack(owner: String, repoName: String, baseUrl: String) ex
|
||||
}
|
||||
}
|
||||
|
||||
class PluginGitUploadPack(repoName: String, baseUrl: String, routing: GitRepositoryRouting) extends GitCommand
|
||||
class PluginGitUploadPack(repoName: String, routing: GitRepositoryRouting) extends GitCommand
|
||||
with SystemSettingsService {
|
||||
|
||||
override protected def runTask(user: String)(implicit session: Session): Unit = {
|
||||
@@ -139,7 +139,7 @@ class PluginGitUploadPack(repoName: String, baseUrl: String, routing: GitReposit
|
||||
}
|
||||
}
|
||||
|
||||
class PluginGitReceivePack(repoName: String, baseUrl: String, routing: GitRepositoryRouting) extends GitCommand
|
||||
class PluginGitReceivePack(repoName: String, routing: GitRepositoryRouting) extends GitCommand
|
||||
with SystemSettingsService {
|
||||
|
||||
override protected def runTask(user: String)(implicit session: Session): Unit = {
|
||||
@@ -163,9 +163,9 @@ class GitCommandFactory(baseUrl: String) extends CommandFactory {
|
||||
logger.debug(s"command: $command")
|
||||
|
||||
command match {
|
||||
case SimpleCommandRegex ("upload" , repoName) if(pluginRepository(repoName)) => new PluginGitUploadPack (repoName, baseUrl, routing(repoName))
|
||||
case SimpleCommandRegex ("receive", repoName) if(pluginRepository(repoName)) => new PluginGitReceivePack(repoName, baseUrl, routing(repoName))
|
||||
case DefaultCommandRegex("upload" , owner, repoName) => new DefaultGitUploadPack (owner, repoName, baseUrl)
|
||||
case SimpleCommandRegex ("upload" , repoName) if(pluginRepository(repoName)) => new PluginGitUploadPack (repoName, routing(repoName))
|
||||
case SimpleCommandRegex ("receive", repoName) if(pluginRepository(repoName)) => new PluginGitReceivePack(repoName, routing(repoName))
|
||||
case DefaultCommandRegex("upload" , owner, repoName) => new DefaultGitUploadPack (owner, repoName)
|
||||
case DefaultCommandRegex("receive", owner, repoName) => new DefaultGitReceivePack(owner, repoName, baseUrl)
|
||||
case _ => new UnknownCommand(command)
|
||||
}
|
||||
|
||||
@@ -1,12 +1,13 @@
|
||||
package gitbucket.core.ssh
|
||||
|
||||
import gitbucket.core.service.SystemSettingsService
|
||||
import gitbucket.core.service.SystemSettingsService.SshAddress
|
||||
import org.apache.sshd.common.Factory
|
||||
import org.apache.sshd.server.{Environment, ExitCallback, Command}
|
||||
import java.io.{OutputStream, InputStream}
|
||||
import org.eclipse.jgit.lib.Constants
|
||||
|
||||
class NoShell extends Factory[Command] with SystemSettingsService {
|
||||
class NoShell(sshAddress:SshAddress) extends Factory[Command] {
|
||||
override def create(): Command = new Command() {
|
||||
private var in: InputStream = null
|
||||
private var out: OutputStream = null
|
||||
@@ -15,7 +16,6 @@ class NoShell extends Factory[Command] with SystemSettingsService {
|
||||
|
||||
override def start(env: Environment): Unit = {
|
||||
val user = env.getEnv.get("USER")
|
||||
val port = loadSystemSettings().sshPort.getOrElse(SystemSettingsService.DefaultSshPort)
|
||||
val message =
|
||||
"""
|
||||
| Welcome to
|
||||
@@ -31,8 +31,8 @@ class NoShell extends Factory[Command] with SystemSettingsService {
|
||||
|
|
||||
| Please use:
|
||||
|
|
||||
| git clone ssh://%s@GITBUCKET_HOST:%d/OWNER/REPOSITORY_NAME.git
|
||||
""".stripMargin.format(user, port).replace("\n", "\r\n") + "\r\n"
|
||||
| git clone ssh://%s@%s:%d/OWNER/REPOSITORY_NAME.git
|
||||
""".stripMargin.format(user, sshAddress.host, sshAddress.port).replace("\n", "\r\n") + "\r\n"
|
||||
err.write(Constants.encode(message))
|
||||
err.flush()
|
||||
in.close()
|
||||
|
||||
@@ -5,7 +5,8 @@ import java.util.concurrent.atomic.AtomicBoolean
|
||||
import javax.servlet.{ServletContextEvent, ServletContextListener}
|
||||
|
||||
import gitbucket.core.service.SystemSettingsService
|
||||
import gitbucket.core.util.Directory
|
||||
import gitbucket.core.service.SystemSettingsService.SshAddress
|
||||
import gitbucket.core.util.{Directory}
|
||||
import org.apache.sshd.server.keyprovider.SimpleGeneratorHostKeyProvider
|
||||
import org.slf4j.LoggerFactory
|
||||
|
||||
@@ -14,20 +15,20 @@ object SshServer {
|
||||
private val server = org.apache.sshd.server.SshServer.setUpDefaultServer()
|
||||
private val active = new AtomicBoolean(false)
|
||||
|
||||
private def configure(port: Int, baseUrl: String) = {
|
||||
server.setPort(port)
|
||||
private def configure(sshAddress: SshAddress, baseUrl: String) = {
|
||||
server.setPort(sshAddress.port)
|
||||
val provider = new SimpleGeneratorHostKeyProvider(new File(s"${Directory.GitBucketHome}/gitbucket.ser"))
|
||||
provider.setAlgorithm("RSA")
|
||||
provider.setOverwriteAllowed(false)
|
||||
server.setKeyPairProvider(provider)
|
||||
server.setPublickeyAuthenticator(new PublicKeyAuthenticator)
|
||||
server.setCommandFactory(new GitCommandFactory(baseUrl))
|
||||
server.setShellFactory(new NoShell)
|
||||
server.setShellFactory(new NoShell(sshAddress))
|
||||
}
|
||||
|
||||
def start(port: Int, baseUrl: String) = {
|
||||
def start(sshAddress: SshAddress, baseUrl: String) = {
|
||||
if(active.compareAndSet(false, true)){
|
||||
configure(port, baseUrl)
|
||||
configure(sshAddress, baseUrl)
|
||||
server.start()
|
||||
logger.info(s"Start SSH Server Listen on ${server.getPort}")
|
||||
}
|
||||
@@ -55,20 +56,18 @@ class SshServerListener extends ServletContextListener with SystemSettingsServic
|
||||
|
||||
override def contextInitialized(sce: ServletContextEvent): Unit = {
|
||||
val settings = loadSystemSettings()
|
||||
if(settings.ssh){
|
||||
settings.baseUrl match {
|
||||
case None =>
|
||||
logger.error("Could not start SshServer because the baseUrl is not configured.")
|
||||
case Some(baseUrl) =>
|
||||
SshServer.start(settings.sshPort.getOrElse(SystemSettingsService.DefaultSshPort), baseUrl)
|
||||
}
|
||||
if (settings.sshAddress.isDefined && settings.baseUrl.isEmpty) {
|
||||
logger.error("Could not start SshServer because the baseUrl is not configured.")
|
||||
}
|
||||
for {
|
||||
sshAddress <- settings.sshAddress
|
||||
baseUrl <- settings.baseUrl
|
||||
}
|
||||
SshServer.start(sshAddress, baseUrl)
|
||||
}
|
||||
|
||||
override def contextDestroyed(sce: ServletContextEvent): Unit = {
|
||||
if(loadSystemSettings().ssh){
|
||||
SshServer.stop()
|
||||
}
|
||||
SshServer.stop()
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -36,7 +36,7 @@ trait OwnerAuthenticator { self: ControllerBase with RepositoryService with Acco
|
||||
private def authenticate(action: (RepositoryInfo) => Any) = {
|
||||
{
|
||||
defining(request.paths){ paths =>
|
||||
getRepository(paths(0), paths(1), baseUrl).map { repository =>
|
||||
getRepository(paths(0), paths(1)).map { repository =>
|
||||
context.loginAccount match {
|
||||
case Some(x) if(x.isAdmin) => action(repository)
|
||||
case Some(x) if(repository.owner == x.userName) => action(repository)
|
||||
@@ -95,7 +95,7 @@ trait CollaboratorsAuthenticator { self: ControllerBase with RepositoryService =
|
||||
private def authenticate(action: (RepositoryInfo) => Any) = {
|
||||
{
|
||||
defining(request.paths){ paths =>
|
||||
getRepository(paths(0), paths(1), baseUrl).map { repository =>
|
||||
getRepository(paths(0), paths(1)).map { repository =>
|
||||
context.loginAccount match {
|
||||
case Some(x) if(x.isAdmin) => action(repository)
|
||||
case Some(x) if(paths(0) == x.userName) => action(repository)
|
||||
@@ -118,7 +118,7 @@ trait ReferrerAuthenticator { self: ControllerBase with RepositoryService =>
|
||||
private def authenticate(action: (RepositoryInfo) => Any) = {
|
||||
{
|
||||
defining(request.paths){ paths =>
|
||||
getRepository(paths(0), paths(1), baseUrl).map { repository =>
|
||||
getRepository(paths(0), paths(1)).map { repository =>
|
||||
if(!repository.repository.isPrivate){
|
||||
action(repository)
|
||||
} else {
|
||||
@@ -145,7 +145,7 @@ trait ReadableUsersAuthenticator { self: ControllerBase with RepositoryService =
|
||||
private def authenticate(action: (RepositoryInfo) => Any) = {
|
||||
{
|
||||
defining(request.paths){ paths =>
|
||||
getRepository(paths(0), paths(1), baseUrl).map { repository =>
|
||||
getRepository(paths(0), paths(1)).map { repository =>
|
||||
context.loginAccount match {
|
||||
case Some(x) if(x.isAdmin) => action(repository)
|
||||
case Some(x) if(!repository.repository.isPrivate) => action(repository)
|
||||
|
||||
@@ -75,6 +75,11 @@ object Implicits {
|
||||
|
||||
def gitRepositoryPath: String = request.getRequestURI.replaceFirst("^/git/", "/")
|
||||
|
||||
def baseUrl:String = {
|
||||
val url = request.getRequestURL.toString
|
||||
val len = url.length - (request.getRequestURI.length - request.getContextPath.length)
|
||||
url.substring(0, len).stripSuffix("/")
|
||||
}
|
||||
}
|
||||
|
||||
implicit class RichSession(session: HttpSession){
|
||||
|
||||
@@ -32,14 +32,13 @@ object JGitUtil {
|
||||
*
|
||||
* @param owner the user name of the repository owner
|
||||
* @param name the repository name
|
||||
* @param url the repository URL
|
||||
* @param commitCount the commit count. If the repository has over 1000 commits then this property is 1001.
|
||||
* @param branchList the list of branch names
|
||||
* @param tags the list of tags
|
||||
*/
|
||||
case class RepositoryInfo(owner: String, name: String, url: String, commitCount: Int, branchList: List[String], tags: List[TagInfo]){
|
||||
def this(owner: String, name: String, baseUrl: String) = {
|
||||
this(owner, name, s"${baseUrl}/git/${owner}/${name}.git", 0, Nil, Nil)
|
||||
case class RepositoryInfo(owner: String, name: String, commitCount: Int, branchList: List[String], tags: List[TagInfo]){
|
||||
def this(owner: String, name: String) = {
|
||||
this(owner, name, 0, Nil, Nil)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -174,14 +173,14 @@ object JGitUtil {
|
||||
/**
|
||||
* Returns the repository information. It contains branch names and tag names.
|
||||
*/
|
||||
def getRepositoryInfo(owner: String, repository: String, baseUrl: String): RepositoryInfo = {
|
||||
def getRepositoryInfo(owner: String, repository: String): RepositoryInfo = {
|
||||
using(Git.open(getRepositoryDir(owner, repository))){ git =>
|
||||
try {
|
||||
// get commit count
|
||||
val commitCount = git.log.all.call.iterator.asScala.map(_ => 1).take(10001).sum
|
||||
|
||||
RepositoryInfo(
|
||||
owner, repository, s"${baseUrl}/git/${owner}/${repository}.git",
|
||||
owner, repository,
|
||||
// commit count
|
||||
commitCount,
|
||||
// branches
|
||||
@@ -197,7 +196,7 @@ object JGitUtil {
|
||||
} catch {
|
||||
// not initialized
|
||||
case e: NoHeadException => RepositoryInfo(
|
||||
owner, repository, s"${baseUrl}/git/${owner}/${repository}.git", 0, Nil, Nil)
|
||||
owner, repository, 0, Nil, Nil)
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
@@ -60,6 +60,8 @@ object Markdown {
|
||||
pages: List[String])
|
||||
(implicit val context: Context) extends Renderer(options) with LinkConverter with RequestCache {
|
||||
|
||||
private val repositoryUrls = context.urls(repository)
|
||||
|
||||
override def heading(text: String, level: Int, raw: String): String = {
|
||||
val id = generateAnchorName(text)
|
||||
val out = new StringBuilder()
|
||||
@@ -135,7 +137,7 @@ object Markdown {
|
||||
(link, link)
|
||||
}
|
||||
|
||||
val url = repository.httpUrl.replaceFirst("/git/", "/").stripSuffix(".git") + "/wiki/" + StringUtil.urlEncode(page)
|
||||
val url = repositoryUrls.httpUrl.replaceFirst("/git/", "/").stripSuffix(".git") + "/wiki/" + StringUtil.urlEncode(page)
|
||||
if(pages.contains(page)){
|
||||
"<a href=\"" + url + "\">" + escape(label) + "</a>"
|
||||
} else {
|
||||
@@ -157,14 +159,14 @@ object Markdown {
|
||||
} else if(context.currentPath.contains("/tree/")){
|
||||
val paths = context.currentPath.split("/")
|
||||
val branch = if(paths.length > 3) paths.drop(4).mkString("/") else repository.repository.defaultBranch
|
||||
repository.httpUrl.replaceFirst("/git/", "/").stripSuffix(".git") + "/blob/" + branch + "/" + url + (if(isImage) "?raw=true" else "")
|
||||
repositoryUrls.httpUrl.replaceFirst("/git/", "/").stripSuffix(".git") + "/blob/" + branch + "/" + url + (if(isImage) "?raw=true" else "")
|
||||
} else {
|
||||
val paths = context.currentPath.split("/")
|
||||
val branch = if(paths.length > 3) paths.last else repository.repository.defaultBranch
|
||||
repository.httpUrl.replaceFirst("/git/", "/").stripSuffix(".git") + "/blob/" + branch + "/" + url + (if(isImage) "?raw=true" else "")
|
||||
repositoryUrls.httpUrl.replaceFirst("/git/", "/").stripSuffix(".git") + "/blob/" + branch + "/" + url + (if(isImage) "?raw=true" else "")
|
||||
}
|
||||
} else {
|
||||
repository.httpUrl.replaceFirst("/git/", "/").stripSuffix(".git") + "/wiki/_blob/" + url
|
||||
repositoryUrls.httpUrl.replaceFirst("/git/", "/").stripSuffix(".git") + "/wiki/_blob/" + url
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -111,15 +111,24 @@
|
||||
Enable SSH access to git repository
|
||||
</label>
|
||||
</fieldset>
|
||||
<div class="form-group ssh">
|
||||
<label class="control-label col-md-3" for="sshPort">SSH Port</label>
|
||||
<div class="col-md-9">
|
||||
<input type="text" id="sshPort" name="sshPort" class="form-control" value="@settings.sshPort"/>
|
||||
<span id="error-sshPort" class="error"></span>
|
||||
<div class="ssh">
|
||||
<div class="form-group">
|
||||
<label class="control-label col-md-3" for="sshHost">SSH Host</label>
|
||||
<div class="col-md-9">
|
||||
<input type="text" id="sshHost" name="sshHost" class="form-control" value="@settings.sshHost"/>
|
||||
<span id="error-sshHost" class="error"></span>
|
||||
</div>
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<label class="control-label col-md-3" for="sshPort">SSH Port</label>
|
||||
<div class="col-md-9">
|
||||
<input type="text" id="sshPort" name="sshPort" class="form-control" value="@settings.sshPort"/>
|
||||
<span id="error-sshPort" class="error"></span>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<p class="muted">
|
||||
Base URL is required if SSH access is enabled.
|
||||
Base URL is required if SSH access is enabled.
|
||||
</p>
|
||||
<!--====================================================================-->
|
||||
<!-- Authentication -->
|
||||
|
||||
@@ -37,7 +37,7 @@
|
||||
<script src="@assets/vendors/jquery-hotkeys/jquery.hotkeys.js"></script>
|
||||
@repository.map { repository =>
|
||||
@if(!repository.repository.isPrivate){
|
||||
<meta name="go-import" content="@context.baseUrl.replaceFirst("^https?://", "")/@repository.owner/@repository.name git @repository.httpUrl" />
|
||||
<meta name="go-import" content="@context.baseUrl.replaceFirst("^https?://", "")/@repository.owner/@repository.name git @context.urls(repository).httpUrl" />
|
||||
}
|
||||
}
|
||||
</head>
|
||||
|
||||
@@ -80,8 +80,8 @@
|
||||
<div class="small">
|
||||
<strong id="repository-url-proto">HTTP</strong> <span class="mute">clone URL</span>
|
||||
</div>
|
||||
@helper.html.copy("repository-url-copy", repository.httpUrl){
|
||||
<input type="text" value="@repository.httpUrl" id="repository-url" class="form-control input-sm" readonly>
|
||||
@helper.html.copy("repository-url-copy", context.urls(repository).httpUrl){
|
||||
<input type="text" value="@context.urls(repository).httpUrl" id="repository-url" class="form-control input-sm" readonly>
|
||||
}
|
||||
@if(settings.ssh && loginAccount.isDefined){
|
||||
<div class="small">
|
||||
@@ -91,7 +91,7 @@
|
||||
@id.map { id =>
|
||||
@if(context.platform != "linux" && context.platform != null){
|
||||
<div style="margin-top: 10px;">
|
||||
<a href="@repository.httpOpenRepoUrl(context.platform)" id="repository-clone-url" class="btn btn-sm btn-default btn-block"><i class="octicon octicon-desktop-download"></i> Clone in Desktop</a>
|
||||
<a href="@context.urls(repository).httpOpenRepoUrl(context.platform)" id="repository-clone-url" class="btn btn-sm btn-default btn-block"><i class="octicon octicon-desktop-download"></i> Clone in Desktop</a>
|
||||
</div>
|
||||
}
|
||||
<div style="margin-top: 10px;">
|
||||
@@ -184,15 +184,15 @@ $(function(){
|
||||
@if(settings.ssh && loginAccount.isDefined){
|
||||
$('#repository-url-http').click(function(){
|
||||
$('#repository-url-proto').text('HTTP');
|
||||
$('#repository-url').val('@repository.httpUrl');
|
||||
$('#repository-clone-url').attr('href', '@repository.httpOpenRepoUrl(context.platform)')
|
||||
$('#repository-url').val('@context.urls(repository).httpUrl');
|
||||
$('#repository-clone-url').attr('href', '@context.urls(repository).httpOpenRepoUrl(context.platform)')
|
||||
$('#repository-url-copy').attr('data-clipboard-text', $('#repository-url').val());
|
||||
});
|
||||
|
||||
$('#repository-url-ssh').click(function(){
|
||||
$('#repository-url-proto').text('SSH');
|
||||
$('#repository-url').val('@repository.sshUrl(settings.sshPort.getOrElse(SystemSettingsService.DefaultSshPort), loginAccount.get.userName)');
|
||||
$('#repository-clone-url').attr('href', '@repository.sshOpenRepoUrl(context.platform, settings.sshPort.getOrElse(SystemSettingsService.DefaultSshPort), loginAccount.get.userName)');
|
||||
$('#repository-url').val('@context.urls(repository).sshUrl(loginAccount.get.userName)');
|
||||
$('#repository-clone-url').attr('href', '@context.urls(repository).sshOpenRepoUrl(context.platform, loginAccount.get.userName)');
|
||||
$('#repository-url-copy').attr('data-clipboard-text', $('#repository-url').val());
|
||||
});
|
||||
}
|
||||
|
||||
@@ -100,21 +100,21 @@
|
||||
you can perform a manual merge on the command line.
|
||||
</p>
|
||||
}
|
||||
@helper.html.copy("repository-url-copy", forkedRepository.httpUrl, true){
|
||||
@helper.html.copy("repository-url-copy", context.urls(forkedRepository).httpUrl, true){
|
||||
<div class="btn-group" data-toggle="buttons-radio">
|
||||
<button class="btn btn-small active" type="button" id="repository-url-http">HTTP</button>
|
||||
@if(settings.ssh && loginAccount.isDefined){
|
||||
<button class="btn btn-small" type="button" id="repository-url-ssh" style="border-radius: 0px;">SSH</button>
|
||||
}
|
||||
</div>
|
||||
<input type="text" style="width: 500px;" value="@forkedRepository.httpUrl" id="repository-url" readonly />
|
||||
<input type="text" style="width: 500px;" value="@context.urls(forkedRepository).httpUrl" id="repository-url" readonly />
|
||||
}
|
||||
<div>
|
||||
<p>
|
||||
<span class="strong">Step 1:</span> From your project repository, check out a new branch and test the changes.
|
||||
</p>
|
||||
@defining(s"git checkout -b ${pullreq.requestUserName}-${pullreq.requestBranch} ${pullreq.branch}\n" +
|
||||
s"git pull ${forkedRepository.httpUrl} ${pullreq.requestBranch}"){ command =>
|
||||
s"git pull ${context.urls(forkedRepository).httpUrl} ${pullreq.requestBranch}"){ command =>
|
||||
@helper.html.copy("merge-command-copy-1", command){
|
||||
<pre style="width: 600px; float: left; font-size: 12px; border-radius: 3px 0px 3px 3px;" id="merge-command">@Html(command)</pre>
|
||||
}
|
||||
@@ -174,24 +174,24 @@ $(function(){
|
||||
@if(settings.ssh && loginAccount.isDefined){
|
||||
$('#repository-url-http').click(function(){
|
||||
// Update URL box
|
||||
$('#repository-url').val('@forkedRepository.httpUrl');
|
||||
$('#repository-url').val('@context.urls(forkedRepository).httpUrl');
|
||||
$('#repository-url-copy').attr('data-clipboard-text', $('#repository-url').val());
|
||||
// Update command guidance
|
||||
$('#merge-command').text($('#merge-command').text().replace(
|
||||
'@forkedRepository.sshUrl(settings.sshPort.getOrElse(SystemSettingsService.DefaultSshPort), loginAccount.get.userName)',
|
||||
'@forkedRepository.httpUrl'
|
||||
'@context.urls(forkedRepository).sshUrl(loginAccount.get.userName)',
|
||||
'@context.urls(forkedRepository).httpUrl'
|
||||
));
|
||||
$('#merge-command-copy-1').attr('data-clipboard-text', $('#merge-command').text());
|
||||
});
|
||||
|
||||
$('#repository-url-ssh').click(function(){
|
||||
// Update URL box
|
||||
$('#repository-url').val('@forkedRepository.sshUrl(settings.sshPort.getOrElse(SystemSettingsService.DefaultSshPort), loginAccount.get.userName)');
|
||||
$('#repository-url').val('@context.urls(forkedRepository).sshUrl(loginAccount.get.userName)');
|
||||
$('#repository-url-copy').attr('data-clipboard-text', $('#repository-url').val());
|
||||
// Update command guidance
|
||||
$('#merge-command').text($('#merge-command').text().replace(
|
||||
'@forkedRepository.httpUrl',
|
||||
'@forkedRepository.sshUrl(settings.sshPort.getOrElse(SystemSettingsService.DefaultSshPort), loginAccount.get.userName)'
|
||||
'@context.urls(forkedRepository).httpUrl',
|
||||
'@context.urls(forkedRepository).sshUrl(loginAccount.get.userName)'
|
||||
));
|
||||
$('#merge-command-copy-1').attr('data-clipboard-text', $('#merge-command').text());
|
||||
});
|
||||
|
||||
@@ -10,10 +10,10 @@
|
||||
} else {
|
||||
<h3><strong>Quick setup</strong> — if you've done this kind of thing before</h3>
|
||||
<div class="empty-repo-options">
|
||||
via <a href="@repository.httpUrl" class="git-protocol-selector">HTTP</a>
|
||||
via <a href="@context.urls(repository).httpUrl" class="git-protocol-selector">HTTP</a>
|
||||
@if(settings.ssh && loginAccount.isDefined){
|
||||
or
|
||||
<a href="@repository.sshUrl(settings.sshPort.getOrElse(SystemSettingsService.DefaultSshPort), loginAccount.get.userName)" class="git-protocol-selector">SSH</a>
|
||||
<a href="@context.urls(repository).sshUrl(loginAccount.get.userName)" class="git-protocol-selector">SSH</a>
|
||||
}
|
||||
</div>
|
||||
<h3 style="margin-top: 30px;">Create a new repository on the command line</h3>
|
||||
@@ -22,12 +22,12 @@
|
||||
git init
|
||||
git add README.md
|
||||
git commit -m "first commit"
|
||||
git remote add origin <span class="live-clone-url">@repository.httpUrl</span>
|
||||
git remote add origin <span class="live-clone-url">@context.urls(repository).httpUrl</span>
|
||||
git push -u origin master
|
||||
}
|
||||
<h3 style="margin-top: 30px;">Push an existing repository from the command line</h3>
|
||||
@pre {
|
||||
git remote add origin <span class="live-clone-url">@repository.httpUrl</span>
|
||||
git remote add origin <span class="live-clone-url">@context.urls(repository).httpUrl</span>
|
||||
git push -u origin master
|
||||
}
|
||||
<script>
|
||||
|
||||
@@ -67,8 +67,8 @@
|
||||
<div class="small">
|
||||
<strong>Clone this wiki locally</strong>
|
||||
</div>
|
||||
@helper.html.copy("repository-url-copy", httpUrl(repository)){
|
||||
<input type="text" value="@httpUrl(repository)" id="repository-url" class="form-control input-sm" readonly>
|
||||
@helper.html.copy("repository-url-copy", context.wikiUrls(repository).httpUrl){
|
||||
<input type="text" value="@context.wikiUrls(repository).httpUrl" id="repository-url" class="form-control input-sm" readonly>
|
||||
}
|
||||
@if(settings.ssh && loginAccount.isDefined){
|
||||
<div class="small">
|
||||
@@ -133,11 +133,11 @@ $(function(){
|
||||
|
||||
@if(settings.ssh && loginAccount.isDefined){
|
||||
$('#repository-url-http').click(function(){
|
||||
$('#repository-url').val('@httpUrl(repository)');
|
||||
$('#repository-url').val('@context.wikiUrls(repository).httpUrl');
|
||||
$('#repository-url-copy').attr('data-clipboard-text', $('#repository-url').val());
|
||||
});
|
||||
$('#repository-url-ssh').click(function(){
|
||||
$('#repository-url').val('@sshUrl(repository, settings, loginAccount.get.userName)');
|
||||
$('#repository-url').val('@context.wikiUrls(repository).sshUrl(loginAccount.get.userName)');
|
||||
$('#repository-url-copy').attr('data-clipboard-text', $('#repository-url').val());
|
||||
});
|
||||
}
|
||||
|
||||
@@ -104,6 +104,7 @@ class AvatarImageProviderSpec extends FunSpec with MockitoSugar {
|
||||
notification = false,
|
||||
activityLogLimit = None,
|
||||
ssh = false,
|
||||
sshHost = None,
|
||||
sshPort = None,
|
||||
useSMTP = false,
|
||||
smtp = None,
|
||||
|
||||
Reference in New Issue
Block a user