diff --git a/CHANGELOG.md b/CHANGELOG.md
index 143e619..66987e4 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -1,6 +1,12 @@
# Changelog
All changes to the project will be documented in this file.
+### 4.27.0 - 29 Jul 2018
+- Create new tag on the browser
+- EditorConfig support
+- Improve issues / pull requests search
+- Some improvements and bug fixes for plugin installation via internet and pull request commenting
+
### 4.26.0 - 30 Jun 2018
- Installing plugins from the central registry
- Repositories tab in the dashboard
diff --git a/README.md b/README.md
index 6307665..e46cbb6 100644
--- a/README.md
+++ b/README.md
@@ -68,14 +68,12 @@
- If you can't find same question and report, send it to [gitter room](https://gitter.im/gitbucket/gitbucket) before raising an issue.
- The highest priority of GitBucket is the ease of installation and API compatibility with GitHub, so your feature request might be rejected if they go against those principles.
-What's New in 4.26.x
+What's New in 4.27.x
-------------
-### 4.26.0 - 30 Jun 2018
-- Installing plugins from the central registry
-- Repositories tab in the dashboard
-- Fork dialog enhancement
-- Adjust pull request creation suggestor
-- Keep showing incompleted task list
-- New notification hooks
+### 4.27.0 - 29 Jul 2018
+- Create new tag on the browser
+- EditorConfig support
+- Improve issues / pull requests search
+- Some improvements and bug fixes for plugin installation via internet and pull request commenting
See the [change log](CHANGELOG.md) for all of the updates.
diff --git a/build.sbt b/build.sbt
index a31963b..f37c815 100644
--- a/build.sbt
+++ b/build.sbt
@@ -3,7 +3,7 @@
val Organization = "io.github.gitbucket"
val Name = "gitbucket"
-val GitBucketVersion = "4.26.0"
+val GitBucketVersion = "4.27.0"
val ScalatraVersion = "2.6.1"
val JettyVersion = "9.4.7.v20170914"
@@ -47,8 +47,8 @@
"com.github.takezoe" %% "blocking-slick-32" % "0.0.10",
"com.novell.ldap" % "jldap" % "2009-10-07",
"com.h2database" % "h2" % "1.4.196",
- "org.mariadb.jdbc" % "mariadb-java-client" % "2.2.5",
- "org.postgresql" % "postgresql" % "42.1.4",
+ "org.mariadb.jdbc" % "mariadb-java-client" % "2.2.6",
+ "org.postgresql" % "postgresql" % "42.2.4",
"ch.qos.logback" % "logback-classic" % "1.2.3",
"com.zaxxer" % "HikariCP" % "2.7.4",
"com.typesafe" % "config" % "1.3.2",
diff --git a/src/main/resources/update/gitbucket-core_4.27.xml b/src/main/resources/update/gitbucket-core_4.27.xml
new file mode 100644
index 0000000..b939f53
--- /dev/null
+++ b/src/main/resources/update/gitbucket-core_4.27.xml
@@ -0,0 +1,14 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/src/main/scala/gitbucket/core/GitBucketCoreModule.scala b/src/main/scala/gitbucket/core/GitBucketCoreModule.scala
index 99b0c6e..c0345f4 100644
--- a/src/main/scala/gitbucket/core/GitBucketCoreModule.scala
+++ b/src/main/scala/gitbucket/core/GitBucketCoreModule.scala
@@ -55,5 +55,6 @@
new Version("4.24.0", new LiquibaseMigration("update/gitbucket-core_4.24.xml")),
new Version("4.24.1"),
new Version("4.25.0", new LiquibaseMigration("update/gitbucket-core_4.25.xml")),
- new Version("4.26.0")
+ new Version("4.26.0"),
+ new Version("4.27.0", new LiquibaseMigration("update/gitbucket-core_4.27.xml"))
)
diff --git a/src/main/scala/gitbucket/core/controller/IndexController.scala b/src/main/scala/gitbucket/core/controller/IndexController.scala
index 7770ccc..e553864 100644
--- a/src/main/scala/gitbucket/core/controller/IndexController.scala
+++ b/src/main/scala/gitbucket/core/controller/IndexController.scala
@@ -237,9 +237,19 @@
}
target.toLowerCase match {
- case "issue" =>
+ case "issues" =>
gitbucket.core.search.html.issues(
- if (query.nonEmpty) searchIssues(repository.owner, repository.name, query) else Nil,
+ if (query.nonEmpty) searchIssues(repository.owner, repository.name, query, false) else Nil,
+ false,
+ query,
+ page,
+ repository
+ )
+
+ case "pulls" =>
+ gitbucket.core.search.html.issues(
+ if (query.nonEmpty) searchIssues(repository.owner, repository.name, query, true) else Nil,
+ true,
query,
page,
repository
diff --git a/src/main/scala/gitbucket/core/controller/RepositoryViewerController.scala b/src/main/scala/gitbucket/core/controller/RepositoryViewerController.scala
index 8e4e3d5..1054149 100644
--- a/src/main/scala/gitbucket/core/controller/RepositoryViewerController.scala
+++ b/src/main/scala/gitbucket/core/controller/RepositoryViewerController.scala
@@ -117,6 +117,12 @@
diff: Option[String]
)
+ case class TagForm(
+ commitId: String,
+ tagName: String,
+ message: Option[String]
+ )
+
val uploadForm = mapping(
"branch" -> trim(label("Branch", text(required))),
"path" -> trim(label("Path", text())),
@@ -153,6 +159,12 @@
"diff" -> optional(text())
)(CommentForm.apply)
+ val tagForm = mapping(
+ "commitId" -> trim(label("Commit id", text(required))),
+ "tagName" -> trim(label("Tag name", text(required))),
+ "message" -> trim(label("Message", optional(text())))
+ )(TagForm.apply)
+
/**
* Returns converted HTML from Markdown for preview.
*/
@@ -427,8 +439,10 @@
commit = form.commit
)
+ println(form.path)
+
redirect(
- s"/${repository.owner}/${repository.name}/tree/${form.branch}${if (form.path.length == 0) "" else form.path}"
+ s"/${repository.owner}/${repository.name}/tree/${form.branch}${if (form.path.length == 0) "" else "/" + form.path}"
)
})
@@ -540,7 +554,9 @@
repository,
diffs,
oldCommitId,
- hasDeveloperRole(repository.owner, repository.name, context.loginAccount)
+ hasDeveloperRole(repository.owner, repository.name, context.loginAccount),
+ flash.get("info"),
+ flash.get("error")
)
}
}
@@ -790,6 +806,29 @@
})
/**
+ * Displays the create tag dialog.
+ */
+ get("/:owner/:repository/tag/:id")(writableUsersOnly { repository =>
+ html.tag(params("id"), repository)
+ })
+
+ /**
+ * Creates a tag.
+ */
+ post("/:owner/:repository/tag", tagForm)(writableUsersOnly { (form, repository) =>
+ using(Git.open(getRepositoryDir(repository.owner, repository.name))) { git =>
+ JGitUtil.createTag(git, form.tagName, form.message, form.commitId)
+ } match {
+ case Right(message) =>
+ flash += "info" -> message
+ redirect(s"/${repository.owner}/${repository.name}/commit/${form.commitId}")
+ case Left(message) =>
+ flash += "error" -> message
+ redirect(s"/${repository.owner}/${repository.name}/commit/${form.commitId}")
+ }
+ })
+
+ /**
* Creates a branch.
*/
post("/:owner/:repository/branches")(writableUsersOnly { repository =>
diff --git a/src/main/scala/gitbucket/core/model/Comment.scala b/src/main/scala/gitbucket/core/model/Comment.scala
index 8e5044c..9314b2e 100644
--- a/src/main/scala/gitbucket/core/model/Comment.scala
+++ b/src/main/scala/gitbucket/core/model/Comment.scala
@@ -54,6 +54,9 @@
val registeredDate = column[java.util.Date]("REGISTERED_DATE")
val updatedDate = column[java.util.Date]("UPDATED_DATE")
val issueId = column[Option[Int]]("ISSUE_ID")
+ val originalCommitId = column[String]("ORIGINAL_COMMIT_ID")
+ val originalOldLine = column[Option[Int]]("ORIGINAL_OLD_LINE")
+ val originalNewLine = column[Option[Int]]("ORIGINAL_NEW_LINE")
def * =
(
userName,
@@ -67,7 +70,10 @@
newLine,
registeredDate,
updatedDate,
- issueId
+ issueId,
+ originalCommitId,
+ originalOldLine,
+ originalNewLine
) <> (CommitComment.tupled, CommitComment.unapply)
def byPrimaryKey(commentId: Int) = this.commentId === commentId.bind
@@ -86,7 +92,10 @@
newLine: Option[Int],
registeredDate: java.util.Date,
updatedDate: java.util.Date,
- issueId: Option[Int]
+ issueId: Option[Int],
+ originalCommitId: String,
+ originalOldLine: Option[Int],
+ originalNewLine: Option[Int]
) extends Comment
case class CommitComments(
diff --git a/src/main/scala/gitbucket/core/service/CommitsService.scala b/src/main/scala/gitbucket/core/service/CommitsService.scala
index 8f81b76..b59c929 100644
--- a/src/main/scala/gitbucket/core/service/CommitsService.scala
+++ b/src/main/scala/gitbucket/core/service/CommitsService.scala
@@ -49,7 +49,10 @@
newLine = newLine,
registeredDate = currentDate,
updatedDate = currentDate,
- issueId = issueId
+ issueId = issueId,
+ originalCommitId = commitId,
+ originalOldLine = oldLine,
+ originalNewLine = newLine
)
def updateCommitCommentPosition(commentId: Int, commitId: String, oldLine: Option[Int], newLine: Option[Int])(
diff --git a/src/main/scala/gitbucket/core/service/IssuesService.scala b/src/main/scala/gitbucket/core/service/IssuesService.scala
index 05255c4..24a0566 100644
--- a/src/main/scala/gitbucket/core/service/IssuesService.scala
+++ b/src/main/scala/gitbucket/core/service/IssuesService.scala
@@ -630,7 +630,7 @@
* @param query the keywords separated by whitespace.
* @return issues with comment count and matched content of issue or comment
*/
- def searchIssuesByKeyword(owner: String, repository: String, query: String)(
+ def searchIssuesByKeyword(owner: String, repository: String, query: String, pullRequest: Boolean)(
implicit s: Session
): List[(Issue, Int, String)] = {
//import slick.driver.JdbcDriver.likeEncode
@@ -638,7 +638,9 @@
// Search Issue
val issues = Issues
- .filter(_.byRepository(owner, repository))
+ .filter { t =>
+ t.byRepository(owner, repository) && t.pullRequest === pullRequest.bind
+ }
.join(IssueOutline)
.on {
case (t1, t2) =>
@@ -673,11 +675,12 @@
}
.filter {
case ((t1, t2), t3) =>
- keywords
- .map { query =>
- t1.content.toLowerCase like (s"%${likeEncode(query)}%", '^')
- }
- .reduceLeft(_ && _)
+ t2.pullRequest === pullRequest.bind &&
+ keywords
+ .map { query =>
+ t1.content.toLowerCase like (s"%${likeEncode(query)}%", '^')
+ }
+ .reduceLeft(_ && _)
}
.map {
case ((t1, t2), t3) =>
@@ -688,7 +691,7 @@
.union(comments)
.sortBy {
case (issue, commentId, _, _) =>
- issue.issueId -> commentId
+ issue.issueId.desc -> commentId
}
.list
.splitWith {
diff --git a/src/main/scala/gitbucket/core/service/PullRequestService.scala b/src/main/scala/gitbucket/core/service/PullRequestService.scala
index c6cde8e..8612d74 100644
--- a/src/main/scala/gitbucket/core/service/PullRequestService.scala
+++ b/src/main/scala/gitbucket/core/service/PullRequestService.scala
@@ -181,9 +181,9 @@
// Collect comment positions
val positions = getCommitComments(pullreq.userName, pullreq.repositoryName, pullreq.commitIdTo, true)
.collect {
- case CommitComment(_, _, _, commentId, _, _, Some(file), None, Some(newLine), _, _, _) =>
+ case CommitComment(_, _, _, commentId, _, _, Some(file), None, Some(newLine), _, _, _, _, _, _) =>
(file, commentId, Right(newLine))
- case CommitComment(_, _, _, commentId, _, _, Some(file), Some(oldLine), None, _, _, _) =>
+ case CommitComment(_, _, _, commentId, _, _, Some(file), Some(oldLine), None, _, _, _, _, _, _) =>
(file, commentId, Left(oldLine))
}
.groupBy { case (file, _, _) => file }
@@ -348,7 +348,7 @@
.groupBy {
case x: IssueComment => (Some(x.commentId), None, None, None)
case x: CommitComment if x.fileName.isEmpty => (Some(x.commentId), None, None, None)
- case x: CommitComment => (None, x.fileName, x.oldLine, x.newLine)
+ case x: CommitComment => (None, x.fileName, x.originalOldLine, x.originalNewLine)
case x => throw new MatchError(x)
}
.toSeq
@@ -366,7 +366,7 @@
diff = loadCommitCommentDiff(
userName,
repositoryName,
- comments.head.asInstanceOf[CommitComment].commitId,
+ comments.head.asInstanceOf[CommitComment].originalCommitId,
fileName,
oldLine,
newLine
diff --git a/src/main/scala/gitbucket/core/service/RepositorySearchService.scala b/src/main/scala/gitbucket/core/service/RepositorySearchService.scala
index 4c53792..a06af1d 100644
--- a/src/main/scala/gitbucket/core/service/RepositorySearchService.scala
+++ b/src/main/scala/gitbucket/core/service/RepositorySearchService.scala
@@ -14,18 +14,21 @@
trait RepositorySearchService { self: IssuesService =>
import RepositorySearchService._
- def countIssues(owner: String, repository: String, query: String)(implicit session: Session): Int =
- searchIssuesByKeyword(owner, repository, query).length
+ def countIssues(owner: String, repository: String, query: String, pullRequest: Boolean)(
+ implicit session: Session
+ ): Int =
+ searchIssuesByKeyword(owner, repository, query, pullRequest).length
- def searchIssues(owner: String, repository: String, query: String)(
+ def searchIssues(owner: String, repository: String, query: String, pullRequest: Boolean)(
implicit session: Session
): List[IssueSearchResult] =
- searchIssuesByKeyword(owner, repository, query).map {
+ searchIssuesByKeyword(owner, repository, query, pullRequest).map {
case (issue, commentCount, content) =>
IssueSearchResult(
issue.issueId,
issue.isPullRequest,
issue.title,
+ issue.closed,
issue.openedUserName,
issue.registeredDate,
commentCount,
@@ -142,6 +145,7 @@
issueId: Int,
isPullRequest: Boolean,
title: String,
+ isClosed: Boolean,
openedUserName: String,
registeredDate: java.util.Date,
commentCount: Int,
diff --git a/src/main/scala/gitbucket/core/util/JDBCUtil.scala b/src/main/scala/gitbucket/core/util/JDBCUtil.scala
index bb3b160..9d34c84 100644
--- a/src/main/scala/gitbucket/core/util/JDBCUtil.scala
+++ b/src/main/scala/gitbucket/core/util/JDBCUtil.scala
@@ -143,6 +143,7 @@
case Types.BOOLEAN | Types.BIT => rs.getBoolean(columnName)
case Types.VARCHAR | Types.CLOB | Types.CHAR | Types.LONGVARCHAR => rs.getString(columnName)
case Types.INTEGER => rs.getInt(columnName)
+ case Types.BIGINT => rs.getLong(columnName)
case Types.TIMESTAMP => rs.getTimestamp(columnName)
}
}
@@ -202,8 +203,7 @@
private def allTablesOrderByDependencies(meta: DatabaseMetaData): Seq[String] = {
val tables = allTableNames.map { tableName =>
- val result = TableDependency(tableName, childTables(meta, tableName))
- result
+ TableDependency(tableName, childTables(meta, tableName))
}
val edges = tables.flatMap { table =>
@@ -212,7 +212,10 @@
}
}
- tsort(edges).toSeq
+ val ordered = tsort(edges).toSeq
+ val orphans = tables.collect { case x if !ordered.contains(x.tableName) => x.tableName }
+
+ ordered ++ orphans
}
def tsort[A](edges: Traversable[(A, A)]): Iterable[A] = {
diff --git a/src/main/scala/gitbucket/core/util/JGitUtil.scala b/src/main/scala/gitbucket/core/util/JGitUtil.scala
index 0381fdb..bef631a 100644
--- a/src/main/scala/gitbucket/core/util/JGitUtil.scala
+++ b/src/main/scala/gitbucket/core/util/JGitUtil.scala
@@ -23,12 +23,7 @@
import java.util.function.Consumer
import org.cache2k.Cache2kBuilder
-import org.eclipse.jgit.api.errors.{
- InvalidRefNameException,
- JGitInternalException,
- NoHeadException,
- RefAlreadyExistsException
-}
+import org.eclipse.jgit.api.errors._
import org.eclipse.jgit.diff.{DiffEntry, DiffFormatter, RawTextComparator}
import org.eclipse.jgit.dircache.DirCacheEntry
import org.eclipse.jgit.util.io.DisabledOutputStream
@@ -836,6 +831,25 @@
.find(_._1 != null)
}
+ def createTag(git: Git, name: String, message: Option[String], commitId: String) = {
+ try {
+ val objectId: ObjectId = git.getRepository.resolve(commitId)
+ using(new RevWalk(git.getRepository)) { walk =>
+ val tagCommand = git.tag().setName(name).setObjectId(walk.parseCommit(objectId))
+ message.foreach { message =>
+ tagCommand.setMessage(message)
+ }
+ tagCommand.call()
+ }
+ Right("Tag added.")
+ } catch {
+ case e: GitAPIException => Left("Sorry, some Git operation error occurs.")
+ case e: ConcurrentRefUpdateException => Left("Sorry some error occurs.")
+ case e: InvalidTagNameException => Left("Sorry, that name is invalid.")
+ case e: NoHeadException => Left("Sorry, this repo doesn't have HEAD reference")
+ }
+ }
+
def createBranch(git: Git, fromBranch: String, newBranch: String) = {
try {
git.branchCreate().setStartPoint(fromBranch).setName(newBranch).call()
diff --git a/src/main/scala/gitbucket/core/util/LDAPUtil.scala b/src/main/scala/gitbucket/core/util/LDAPUtil.scala
index 9facd51..a2ec686 100644
--- a/src/main/scala/gitbucket/core/util/LDAPUtil.scala
+++ b/src/main/scala/gitbucket/core/util/LDAPUtil.scala
@@ -5,8 +5,11 @@
import gitbucket.core.service.SystemSettingsService
import gitbucket.core.service.SystemSettingsService.Ldap
import com.novell.ldap._
-import java.security.Security
+import java.security.{Provider, Security}
+import java.util.concurrent.atomic.AtomicReference
+
import org.slf4j.LoggerFactory
+
import scala.annotation.tailrec
/**
@@ -15,10 +18,11 @@
object LDAPUtil {
private val LDAP_VERSION: Int = LDAPConnection.LDAP_V3
- private val logger = LoggerFactory.getLogger(getClass().getName())
-
private val LDAP_DUMMY_MAL = "@ldap-devnull"
+ private val logger = LoggerFactory.getLogger(getClass().getName())
+ private val provider = new AtomicReference[Provider](null)
+
/**
* Returns true if mail address ends with "@ldap-devnull"
*/
@@ -120,6 +124,17 @@
}).replaceAll("[^a-zA-Z0-9\\-_.]", "").replaceAll("^[_\\-]", "")
}
+ private def getSslProvider(): Provider = {
+ val cachedInstance = provider.get()
+ if (cachedInstance == null) {
+ val newInstance = Class.forName("com.sun.net.ssl.internal.ssl.Provider").newInstance().asInstanceOf[Provider]
+ provider.compareAndSet(null, newInstance)
+ newInstance
+ } else {
+ cachedInstance
+ }
+ }
+
private def bind[A](
host: String,
port: Int,
@@ -132,7 +147,7 @@
)(f: LDAPConnection => Either[String, A]): Either[String, A] = {
if (tls) {
// Dynamically set Sun as the security provider
- Security.addProvider(new com.sun.net.ssl.internal.ssl.Provider())
+ Security.addProvider(getSslProvider())
if (keystore.compareTo("") != 0) {
// Dynamically set the property that JSSE uses to identify
diff --git a/src/main/twirl/gitbucket/core/helper/commitcomments.scala.html b/src/main/twirl/gitbucket/core/helper/commitcomments.scala.html
index 561e94e..bbdd113 100644
--- a/src/main/twirl/gitbucket/core/helper/commitcomments.scala.html
+++ b/src/main/twirl/gitbucket/core/helper/commitcomments.scala.html
@@ -7,7 +7,7 @@
@comments.fileName
@if(!latestCommitId.contains(comments.comments.head.commitId)) {
-
+
}
We couldn't find any code matching '@query'
+We couldn't find any @{if(pullRequest) "pull requests" else "issues"} matching '@query'
} else { -We've found @issues.size @helpers.plural(issues.size, "issue")
+We've found @issues.size @helpers.plural(issues.size, if(pullRequest) "pull request" else "issue")
} } @issues.drop((page - 1) * RepositorySearchService.IssueLimit).take(RepositorySearchService.IssueLimit).map { issue =>@issue.title
@if(issue.highlightText.nonEmpty){ @@ -31,6 +37,6 @@