diff --git a/src/main/resources/update/gitbucket-core_4.6.xml b/src/main/resources/update/gitbucket-core_4.6.xml
new file mode 100644
index 0000000..6bf4acf
--- /dev/null
+++ b/src/main/resources/update/gitbucket-core_4.6.xml
@@ -0,0 +1,6 @@
+
+
+
+
+
+
diff --git a/src/main/scala/gitbucket/core/GitBucketCoreModule.scala b/src/main/scala/gitbucket/core/GitBucketCoreModule.scala
index a404be3..6830d2d 100644
--- a/src/main/scala/gitbucket/core/GitBucketCoreModule.scala
+++ b/src/main/scala/gitbucket/core/GitBucketCoreModule.scala
@@ -15,5 +15,8 @@
new Version("4.2.1"),
new Version("4.3.0"),
new Version("4.4.0"),
- new Version("4.5.0")
+ new Version("4.5.0"),
+ new Version("4.6.0",
+ new LiquibaseMigration("update/gitbucket-core_4.6.xml")
+ )
)
diff --git a/src/main/scala/gitbucket/core/controller/AccountController.scala b/src/main/scala/gitbucket/core/controller/AccountController.scala
index c0f0212..0308a4a 100644
--- a/src/main/scala/gitbucket/core/controller/AccountController.scala
+++ b/src/main/scala/gitbucket/core/controller/AccountController.scala
@@ -14,6 +14,7 @@
import io.github.gitbucket.scalatra.forms._
import org.apache.commons.io.FileUtils
import org.scalatra.i18n.Messages
+import org.scalatra.BadRequest
class AccountController extends AccountControllerBase
@@ -355,76 +356,80 @@
})
get("/:owner/:repository/fork")(readableUsersOnly { repository =>
- val loginAccount = context.loginAccount.get
- val loginUserName = loginAccount.userName
- val groups = getGroupsByUserName(loginUserName)
- groups match {
- case _: List[String] =>
- val managerPermissions = groups.map { group =>
- val members = getGroupMembers(group)
- context.loginAccount.exists(x => members.exists { member => member.userName == x.userName && member.isManager })
- }
- helper.html.forkrepository(
- repository,
- (groups zip managerPermissions).toMap
- )
- case _ => redirect(s"/${loginUserName}")
- }
+ if(repository.repository.options.allowFork){
+ val loginAccount = context.loginAccount.get
+ val loginUserName = loginAccount.userName
+ val groups = getGroupsByUserName(loginUserName)
+ groups match {
+ case _: List[String] =>
+ val managerPermissions = groups.map { group =>
+ val members = getGroupMembers(group)
+ context.loginAccount.exists(x => members.exists { member => member.userName == x.userName && member.isManager })
+ }
+ helper.html.forkrepository(
+ repository,
+ (groups zip managerPermissions).toMap
+ )
+ case _ => redirect(s"/${loginUserName}")
+ }
+ } else BadRequest
})
post("/:owner/:repository/fork", accountForm)(readableUsersOnly { (form, repository) =>
- val loginAccount = context.loginAccount.get
- val loginUserName = loginAccount.userName
- val accountName = form.accountName
+ if(repository.repository.options.allowFork){
+ val loginAccount = context.loginAccount.get
+ val loginUserName = loginAccount.userName
+ val accountName = form.accountName
- LockUtil.lock(s"${accountName}/${repository.name}"){
- 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}")
- } else {
- // Insert to the database at first
- val originUserName = repository.repository.originUserName.getOrElse(repository.owner)
- val originRepositoryName = repository.repository.originRepositoryName.getOrElse(repository.name)
+ LockUtil.lock(s"${accountName}/${repository.name}"){
+ 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}")
+ } else {
+ // Insert to the database at first
+ val originUserName = repository.repository.originUserName.getOrElse(repository.owner)
+ val originRepositoryName = repository.repository.originRepositoryName.getOrElse(repository.name)
- insertRepository(
- repositoryName = repository.name,
- userName = accountName,
- description = repository.repository.description,
- isPrivate = repository.repository.isPrivate,
- originRepositoryName = Some(originRepositoryName),
- originUserName = Some(originUserName),
- parentRepositoryName = Some(repository.name),
- parentUserName = Some(repository.owner)
- )
+ insertRepository(
+ repositoryName = repository.name,
+ userName = accountName,
+ description = repository.repository.description,
+ isPrivate = repository.repository.isPrivate,
+ originRepositoryName = Some(originRepositoryName),
+ originUserName = Some(originUserName),
+ parentRepositoryName = Some(repository.name),
+ parentUserName = Some(repository.owner)
+ )
- // Add collaborators for group repository
- val ownerAccount = getAccountByUserName(accountName).get
- if(ownerAccount.isGroupAccount){
- getGroupMembers(accountName).foreach { member =>
- addCollaborator(accountName, repository.name, member.userName)
+ // Add collaborators for group repository
+ val ownerAccount = getAccountByUserName(accountName).get
+ if(ownerAccount.isGroupAccount){
+ getGroupMembers(accountName).foreach { member =>
+ addCollaborator(accountName, repository.name, member.userName)
+ }
}
+
+ // Insert default labels
+ insertDefaultLabels(accountName, repository.name)
+
+ // clone repository actually
+ JGitUtil.cloneRepository(
+ getRepositoryDir(repository.owner, repository.name),
+ getRepositoryDir(accountName, repository.name))
+
+ // Create Wiki repository
+ JGitUtil.cloneRepository(
+ getWikiRepositoryDir(repository.owner, repository.name),
+ getWikiRepositoryDir(accountName, repository.name))
+
+ // Record activity
+ recordForkActivity(repository.owner, repository.name, loginUserName, accountName)
+ // redirect to the repository
+ redirect(s"/${accountName}/${repository.name}")
}
-
- // Insert default labels
- insertDefaultLabels(accountName, repository.name)
-
- // clone repository actually
- JGitUtil.cloneRepository(
- getRepositoryDir(repository.owner, repository.name),
- getRepositoryDir(accountName, repository.name))
-
- // Create Wiki repository
- JGitUtil.cloneRepository(
- getWikiRepositoryDir(repository.owner, repository.name),
- getWikiRepositoryDir(accountName, repository.name))
-
- // Record activity
- recordForkActivity(repository.owner, repository.name, loginUserName, accountName)
- // redirect to the repository
- redirect(s"/${accountName}/${repository.name}")
}
- }
+ } else BadRequest
})
private def existsAccount: Constraint = new Constraint(){
diff --git a/src/main/scala/gitbucket/core/controller/RepositorySettingsController.scala b/src/main/scala/gitbucket/core/controller/RepositorySettingsController.scala
index b60ae5d..6d7c981 100644
--- a/src/main/scala/gitbucket/core/controller/RepositorySettingsController.scala
+++ b/src/main/scala/gitbucket/core/controller/RepositorySettingsController.scala
@@ -35,7 +35,8 @@
externalIssuesUrl: Option[String],
enableWiki: Boolean,
allowWikiEditing: Boolean,
- externalWikiUrl: Option[String]
+ externalWikiUrl: Option[String],
+ allowFork: Boolean
)
val optionsForm = mapping(
@@ -46,7 +47,8 @@
"externalIssuesUrl" -> trim(label("External Issues URL", optional(text(maxlength(200))))),
"enableWiki" -> trim(label("Enable Wiki" , boolean())),
"allowWikiEditing" -> trim(label("Allow Wiki Editing" , boolean())),
- "externalWikiUrl" -> trim(label("External Wiki URL" , optional(text(maxlength(200)))))
+ "externalWikiUrl" -> trim(label("External Wiki URL" , optional(text(maxlength(200))))),
+ "allowFork" -> trim(label("Allow Forking" , boolean()))
)(OptionsForm.apply)
// for default branch
@@ -111,7 +113,8 @@
form.externalIssuesUrl,
form.enableWiki,
form.allowWikiEditing,
- form.externalWikiUrl
+ form.externalWikiUrl,
+ form.allowFork
)
// Change repository name
if(repository.name != form.repositoryName){
diff --git a/src/main/scala/gitbucket/core/controller/RepositoryViewerController.scala b/src/main/scala/gitbucket/core/controller/RepositoryViewerController.scala
index cee8f4f..4307fbb 100644
--- a/src/main/scala/gitbucket/core/controller/RepositoryViewerController.scala
+++ b/src/main/scala/gitbucket/core/controller/RepositoryViewerController.scala
@@ -494,18 +494,20 @@
})
get("/:owner/:repository/network/members")(referrersOnly { repository =>
- html.forked(
- getRepository(
- repository.repository.originUserName.getOrElse(repository.owner),
- repository.repository.originRepositoryName.getOrElse(repository.name)),
- getForkedRepositories(
- repository.repository.originUserName.getOrElse(repository.owner),
- repository.repository.originRepositoryName.getOrElse(repository.name)),
- context.loginAccount match {
- case None => List()
- case account: Option[Account] => getGroupsByUserName(account.get.userName)
- }, // groups of current user
- repository)
+ if(repository.repository.options.allowFork) {
+ html.forked(
+ getRepository(
+ repository.repository.originUserName.getOrElse(repository.owner),
+ repository.repository.originRepositoryName.getOrElse(repository.name)),
+ getForkedRepositories(
+ repository.repository.originUserName.getOrElse(repository.owner),
+ repository.repository.originRepositoryName.getOrElse(repository.name)),
+ context.loginAccount match {
+ case None => List()
+ case account: Option[Account] => getGroupsByUserName(account.get.userName)
+ }, // groups of current user
+ repository)
+ } else BadRequest()
})
/**
diff --git a/src/main/scala/gitbucket/core/controller/WikiController.scala b/src/main/scala/gitbucket/core/controller/WikiController.scala
index ad98cee..847c421 100644
--- a/src/main/scala/gitbucket/core/controller/WikiController.scala
+++ b/src/main/scala/gitbucket/core/controller/WikiController.scala
@@ -241,7 +241,7 @@
private def targetWikiPage = getWikiPage(params("owner"), params("repository"), params("pageName"))
private def isEditable(repository: RepositoryInfo)(implicit context: Context): Boolean =
- repository.repository.allowWikiEditing || (
+ repository.repository.options.allowWikiEditing || (
hasWritePermission(repository.owner, repository.name, context.loginAccount)
)
diff --git a/src/main/scala/gitbucket/core/model/Repository.scala b/src/main/scala/gitbucket/core/model/Repository.scala
index ebdfb3a..c5c61bb 100644
--- a/src/main/scala/gitbucket/core/model/Repository.scala
+++ b/src/main/scala/gitbucket/core/model/Repository.scala
@@ -7,24 +7,62 @@
lazy val Repositories = TableQuery[Repositories]
class Repositories(tag: Tag) extends Table[Repository](tag, "REPOSITORY") with BasicTemplate {
- val isPrivate = column[Boolean]("PRIVATE")
- val description = column[String]("DESCRIPTION")
- val defaultBranch = column[String]("DEFAULT_BRANCH")
- val registeredDate = column[java.util.Date]("REGISTERED_DATE")
- val updatedDate = column[java.util.Date]("UPDATED_DATE")
- val lastActivityDate = column[java.util.Date]("LAST_ACTIVITY_DATE")
- val originUserName = column[String]("ORIGIN_USER_NAME")
+ val isPrivate = column[Boolean]("PRIVATE")
+ val description = column[String]("DESCRIPTION")
+ val defaultBranch = column[String]("DEFAULT_BRANCH")
+ val registeredDate = column[java.util.Date]("REGISTERED_DATE")
+ val updatedDate = column[java.util.Date]("UPDATED_DATE")
+ val lastActivityDate = column[java.util.Date]("LAST_ACTIVITY_DATE")
+ val originUserName = column[String]("ORIGIN_USER_NAME")
val originRepositoryName = column[String]("ORIGIN_REPOSITORY_NAME")
- val parentUserName = column[String]("PARENT_USER_NAME")
+ val parentUserName = column[String]("PARENT_USER_NAME")
val parentRepositoryName = column[String]("PARENT_REPOSITORY_NAME")
- val enableIssues = column[Boolean]("ENABLE_ISSUES")
- val externalIssuesUrl = column[String]("EXTERNAL_ISSUES_URL")
- val enableWiki = column[Boolean]("ENABLE_WIKI")
- val allowWikiEditing = column[Boolean]("ALLOW_WIKI_EDITING")
- val externalWikiUrl = column[String]("EXTERNAL_WIKI_URL")
- def * = (userName, repositoryName, isPrivate, description.?, defaultBranch,
- registeredDate, updatedDate, lastActivityDate, originUserName.?, originRepositoryName.?, parentUserName.?, parentRepositoryName.?,
- enableIssues, externalIssuesUrl.?, enableWiki, allowWikiEditing, externalWikiUrl.?) <> (Repository.tupled, Repository.unapply)
+ val enableIssues = column[Boolean]("ENABLE_ISSUES")
+ val externalIssuesUrl = column[String]("EXTERNAL_ISSUES_URL")
+ val enableWiki = column[Boolean]("ENABLE_WIKI")
+ val allowWikiEditing = column[Boolean]("ALLOW_WIKI_EDITING")
+ val externalWikiUrl = column[String]("EXTERNAL_WIKI_URL")
+ val allowFork = column[Boolean]("ALLOW_FORK")
+
+ def * = (
+ (userName, repositoryName, isPrivate, description.?, defaultBranch,
+ registeredDate, updatedDate, lastActivityDate, originUserName.?, originRepositoryName.?, parentUserName.?, parentRepositoryName.?),
+ (enableIssues, externalIssuesUrl.?, enableWiki, allowWikiEditing, externalWikiUrl.?, allowFork)
+ ).shaped <> (
+ { case (repository, options) =>
+ Repository(
+ repository._1,
+ repository._2,
+ repository._3,
+ repository._4,
+ repository._5,
+ repository._6,
+ repository._7,
+ repository._8,
+ repository._9,
+ repository._10,
+ repository._11,
+ repository._12,
+ RepositoryOptions.tupled.apply(options)
+ )
+ }, { (r: Repository) =>
+ Some(((
+ r.userName,
+ r.repositoryName,
+ r.isPrivate,
+ r.description,
+ r.defaultBranch,
+ r.registeredDate,
+ r.updatedDate,
+ r.lastActivityDate,
+ r.originUserName,
+ r.originRepositoryName,
+ r.parentUserName,
+ r.parentRepositoryName
+ ),(
+ RepositoryOptions.unapply(r.options).get
+ )))
+ })
def byPrimaryKey(owner: String, repository: String) = byRepository(owner, repository)
}
@@ -43,9 +81,14 @@
originRepositoryName: Option[String],
parentUserName: Option[String],
parentRepositoryName: Option[String],
+ options: RepositoryOptions
+)
+
+case class RepositoryOptions(
enableIssues: Boolean,
externalIssuesUrl: Option[String],
enableWiki: Boolean,
allowWikiEditing: Boolean,
- externalWikiUrl: Option[String]
+ externalWikiUrl: Option[String],
+ allowFork: Boolean
)
diff --git a/src/main/scala/gitbucket/core/service/RepositoryService.scala b/src/main/scala/gitbucket/core/service/RepositoryService.scala
index 959e735..3541c07 100644
--- a/src/main/scala/gitbucket/core/service/RepositoryService.scala
+++ b/src/main/scala/gitbucket/core/service/RepositoryService.scala
@@ -1,7 +1,7 @@
package gitbucket.core.service
import gitbucket.core.controller.Context
-import gitbucket.core.model.{Collaborator, Repository, Account}
+import gitbucket.core.model.{Collaborator, Repository, RepositoryOptions, Account}
import gitbucket.core.model.Profile._
import gitbucket.core.util.JGitUtil
import profile.simple._
@@ -37,11 +37,14 @@
originRepositoryName = originRepositoryName,
parentUserName = parentUserName,
parentRepositoryName = parentRepositoryName,
- enableIssues = true,
- externalIssuesUrl = None,
- enableWiki = true,
- allowWikiEditing = true,
- externalWikiUrl = None
+ options = RepositoryOptions(
+ enableIssues = true,
+ externalIssuesUrl = None,
+ enableWiki = true,
+ allowWikiEditing = true,
+ externalWikiUrl = None,
+ allowFork = true
+ )
)
IssueId insert (userName, repositoryName, 0)
@@ -321,10 +324,11 @@
def saveRepositoryOptions(userName: String, repositoryName: String,
description: Option[String], isPrivate: Boolean,
enableIssues: Boolean, externalIssuesUrl: Option[String],
- enableWiki: Boolean, allowWikiEditing: Boolean, externalWikiUrl: Option[String])(implicit s: Session): Unit =
+ enableWiki: Boolean, allowWikiEditing: Boolean, externalWikiUrl: Option[String],
+ allowFork: Boolean)(implicit s: Session): Unit =
Repositories.filter(_.byRepository(userName, repositoryName))
- .map { r => (r.description.?, r.isPrivate, r.enableIssues, r.externalIssuesUrl.?, r.enableWiki, r.allowWikiEditing, r.externalWikiUrl.?, r.updatedDate) }
- .update (description, isPrivate, enableIssues, externalIssuesUrl, enableWiki, allowWikiEditing, externalWikiUrl, currentDate)
+ .map { r => (r.description.?, r.isPrivate, r.enableIssues, r.externalIssuesUrl.?, r.enableWiki, r.allowWikiEditing, r.externalWikiUrl.?, r.allowFork, r.updatedDate) }
+ .update (description, isPrivate, enableIssues, externalIssuesUrl, enableWiki, allowWikiEditing, externalWikiUrl, allowFork, currentDate)
def saveRepositoryDefaultBranch(userName: String, repositoryName: String,
defaultBranch: String)(implicit s: Session): Unit =
diff --git a/src/main/twirl/gitbucket/core/menu.scala.html b/src/main/twirl/gitbucket/core/menu.scala.html
index 061fa02..cefd82c 100644
--- a/src/main/twirl/gitbucket/core/menu.scala.html
+++ b/src/main/twirl/gitbucket/core/menu.scala.html
@@ -27,24 +27,26 @@
@menuitem("/branches", "branches", "Branches", "git-branch", repository.branchList.length)
@menuitem("/tags", "tags", "Tags", "tag", repository.tags.length)
}
- @if(repository.repository.enableIssues) {
+ @if(repository.repository.options.enableIssues) {
@menuitem("/issues", "issues", "Issues", "issue-opened", repository.issueCount)
@menuitem("/pulls", "pulls", "Pull Requests", "git-pull-request", repository.pullCount)
@menuitem("/issues/labels", "labels", "Labels", "tag")
@menuitem("/issues/milestones", "milestones", "Milestones", "milestone")
} else {
- @repository.repository.externalIssuesUrl.map { externalIssuesUrl =>
+ @repository.repository.options.externalIssuesUrl.map { externalIssuesUrl =>
@menuitem(externalIssuesUrl, "issues", "Issues", "issue-opened")
}
}
- @if(repository.repository.enableWiki) {
+ @if(repository.repository.options.enableWiki) {
@menuitem("/wiki", "wiki", "Wiki", "book")
} else {
- @repository.repository.externalWikiUrl.map { externalWikiUrl =>
+ @repository.repository.options.externalWikiUrl.map { externalWikiUrl =>
@menuitem(externalWikiUrl, "wiki", "Wiki", "book")
}
}
- @menuitem("/network/members", "fork", "Forks", "repo-forked", repository.forkedCount)
+ @if(repository.repository.options.allowFork) {
+ @menuitem("/network/members", "fork", "Forks", "repo-forked", repository.forkedCount)
+ }
@if(context.loginAccount.isDefined && (context.loginAccount.get.isAdmin || repository.managers.contains(context.loginAccount.get.userName))){
@menuitem("/settings", "settings", "Settings", "tools")
}
diff --git a/src/main/twirl/gitbucket/core/settings/options.scala.html b/src/main/twirl/gitbucket/core/settings/options.scala.html
index 490da70..7b26310 100644
--- a/src/main/twirl/gitbucket/core/settings/options.scala.html
+++ b/src/main/twirl/gitbucket/core/settings/options.scala.html
@@ -46,7 +46,7 @@