Compare commits
26 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
753403b4c8 | ||
|
|
5a0f9f8bbb | ||
|
|
8fa22b4de2 | ||
|
|
d17cae16fd | ||
|
|
c4c48962cf | ||
|
|
4140e92f0b | ||
|
|
887e560a1b | ||
|
|
e2d70181e8 | ||
|
|
148c453dbc | ||
|
|
f6ee9d311d | ||
|
|
35209e43bb | ||
|
|
4a3ecf063d | ||
|
|
4c79101624 | ||
|
|
921b01661b | ||
|
|
c63301d8e6 | ||
|
|
c9ed9d2237 | ||
|
|
ca55cbe456 | ||
|
|
d4828613ee | ||
|
|
a0be02ce2f | ||
|
|
9b8016a4d5 | ||
|
|
8fdd3bfd21 | ||
|
|
695a061e3c | ||
|
|
bd50d9218e | ||
|
|
d8f13bc1ce | ||
|
|
ed84d1a3c9 | ||
|
|
3c765d879c |
2
.gitignore
vendored
@@ -2,6 +2,8 @@
|
||||
*.log
|
||||
.ensime
|
||||
.ensime_cache
|
||||
.DS_Store
|
||||
.java-version
|
||||
|
||||
# sbt specific
|
||||
dist/*
|
||||
|
||||
@@ -1,6 +1,10 @@
|
||||
# Changelog
|
||||
All changes to the project will be documented in this file.
|
||||
|
||||
## 4.38.3 - 30 Oct 2022
|
||||
- Fix several issues around multiple assignees in issues and pull requests
|
||||
- Fix IllegalStateException when returning unknown avatar image
|
||||
|
||||
## 4.38.2 - 20 Sep 2022
|
||||
- Resurrect assignee icons on the issue list
|
||||
|
||||
|
||||
@@ -61,6 +61,10 @@ Support
|
||||
|
||||
What's New in 4.38.x
|
||||
-------------
|
||||
## 4.38.3 - 30 Oct 2022
|
||||
- Fix several issues around multiple assignees in issues and pull requests
|
||||
- Fix IllegalStateException when returning unknown avatar image
|
||||
|
||||
## 4.38.2 - 20 Sep 2022
|
||||
- Resurrect assignee icons on the issue list
|
||||
|
||||
|
||||
28
build.sbt
@@ -3,8 +3,8 @@ import com.jsuereth.sbtpgp.PgpKeys._
|
||||
|
||||
val Organization = "io.github.gitbucket"
|
||||
val Name = "gitbucket"
|
||||
val GitBucketVersion = "4.38.2"
|
||||
val ScalatraVersion = "2.8.2"
|
||||
val GitBucketVersion = "4.38.3"
|
||||
val ScalatraVersion = "2.8.4"
|
||||
val JettyVersion = "9.4.49.v20220914"
|
||||
val JgitVersion = "5.13.1.202206130422-r"
|
||||
|
||||
@@ -15,9 +15,9 @@ sourcesInBase := false
|
||||
organization := Organization
|
||||
name := Name
|
||||
version := GitBucketVersion
|
||||
scalaVersion := "2.13.9"
|
||||
scalaVersion := "2.13.10"
|
||||
|
||||
scalafmtOnCompile := true
|
||||
// scalafmtOnCompile := true
|
||||
|
||||
coverageExcludedPackages := ".*\\.html\\..*"
|
||||
|
||||
@@ -33,7 +33,7 @@ libraryDependencies ++= Seq(
|
||||
"org.scalatra" %% "scalatra" % ScalatraVersion cross CrossVersion.for3Use2_13,
|
||||
"org.scalatra" %% "scalatra-json" % ScalatraVersion cross CrossVersion.for3Use2_13,
|
||||
"org.scalatra" %% "scalatra-forms" % ScalatraVersion cross CrossVersion.for3Use2_13,
|
||||
"org.json4s" %% "json4s-jackson" % "4.0.5" cross CrossVersion.for3Use2_13,
|
||||
"org.json4s" %% "json4s-jackson" % "4.0.6" cross CrossVersion.for3Use2_13,
|
||||
"commons-io" % "commons-io" % "2.11.0",
|
||||
"io.github.gitbucket" % "solidbase" % "1.0.5",
|
||||
"io.github.gitbucket" % "markedj" % "1.0.17",
|
||||
@@ -42,11 +42,11 @@ libraryDependencies ++= Seq(
|
||||
"commons-net" % "commons-net" % "3.8.0",
|
||||
"org.apache.httpcomponents" % "httpclient" % "4.5.13",
|
||||
"org.apache.sshd" % "apache-sshd" % "2.9.1" exclude ("org.slf4j", "slf4j-jdk14") exclude ("org.apache.sshd", "sshd-mina") exclude ("org.apache.sshd", "sshd-netty"),
|
||||
"org.apache.tika" % "tika-core" % "2.4.1",
|
||||
"org.apache.tika" % "tika-core" % "2.5.0",
|
||||
"com.github.takezoe" %% "blocking-slick-32" % "0.0.12" cross CrossVersion.for3Use2_13,
|
||||
"com.novell.ldap" % "jldap" % "2009-10-07",
|
||||
"com.h2database" % "h2" % "1.4.199",
|
||||
"org.mariadb.jdbc" % "mariadb-java-client" % "3.0.7",
|
||||
"org.mariadb.jdbc" % "mariadb-java-client" % "3.0.8",
|
||||
"org.postgresql" % "postgresql" % "42.5.0",
|
||||
"ch.qos.logback" % "logback-classic" % "1.2.11",
|
||||
"com.zaxxer" % "HikariCP" % "4.0.3" exclude ("org.slf4j", "slf4j-api"),
|
||||
@@ -54,21 +54,21 @@ libraryDependencies ++= Seq(
|
||||
"fr.brouillard.oss.security.xhub" % "xhub4j-core" % "1.1.0",
|
||||
"io.github.java-diff-utils" % "java-diff-utils" % "4.12",
|
||||
"org.cache2k" % "cache2k-all" % "1.6.0.Final",
|
||||
"net.coobird" % "thumbnailator" % "0.4.17",
|
||||
"net.coobird" % "thumbnailator" % "0.4.18",
|
||||
"com.github.zafarkhaja" % "java-semver" % "0.9.0",
|
||||
"com.nimbusds" % "oauth2-oidc-sdk" % "9.43.1",
|
||||
"com.nimbusds" % "oauth2-oidc-sdk" % "10.1",
|
||||
"org.eclipse.jetty" % "jetty-webapp" % JettyVersion % "provided",
|
||||
"javax.servlet" % "javax.servlet-api" % "3.1.0" % "provided",
|
||||
"junit" % "junit" % "4.13.2" % "test",
|
||||
"org.scalatra" %% "scalatra-scalatest" % ScalatraVersion % "test" cross CrossVersion.for3Use2_13,
|
||||
"org.mockito" % "mockito-core" % "4.8.0" % "test",
|
||||
"com.dimafeng" %% "testcontainers-scala" % "0.40.10" % "test",
|
||||
"org.testcontainers" % "mysql" % "1.17.3" % "test",
|
||||
"org.testcontainers" % "postgresql" % "1.17.3" % "test",
|
||||
"org.mockito" % "mockito-core" % "4.8.1" % "test",
|
||||
"com.dimafeng" %% "testcontainers-scala" % "0.40.11" % "test",
|
||||
"org.testcontainers" % "mysql" % "1.17.5" % "test",
|
||||
"org.testcontainers" % "postgresql" % "1.17.5" % "test",
|
||||
"net.i2p.crypto" % "eddsa" % "0.3.0",
|
||||
"is.tagomor.woothee" % "woothee-java" % "1.11.0",
|
||||
"org.ec4j.core" % "ec4j-core" % "0.3.0",
|
||||
"org.kohsuke" % "github-api" % "1.308" % "test"
|
||||
"org.kohsuke" % "github-api" % "1.313" % "test"
|
||||
)
|
||||
|
||||
libraryDependencies ~= {
|
||||
|
||||
|
Before Width: | Height: | Size: 203 KiB After Width: | Height: | Size: 112 KiB |
@@ -1 +1 @@
|
||||
sbt.version=1.7.1
|
||||
sbt.version=1.7.2
|
||||
|
||||
@@ -2,7 +2,7 @@ scalacOptions ++= Seq("-unchecked", "-deprecation", "-feature")
|
||||
|
||||
addSbtPlugin("org.scalameta" % "sbt-scalafmt" % "2.4.6")
|
||||
addSbtPlugin("com.typesafe.sbt" % "sbt-twirl" % "1.5.1")
|
||||
addSbtPlugin("com.eed3si9n" % "sbt-assembly" % "1.2.0")
|
||||
addSbtPlugin("com.eed3si9n" % "sbt-assembly" % "2.0.0")
|
||||
addSbtPlugin("org.scalatra.sbt" % "sbt-scalatra" % "1.0.4")
|
||||
addSbtPlugin("com.github.sbt" % "sbt-pgp" % "2.1.2")
|
||||
addSbtPlugin("com.typesafe.sbt" % "sbt-license-report" % "1.2.0")
|
||||
|
||||
|
Before Width: | Height: | Size: 3.0 KiB After Width: | Height: | Size: 1.5 KiB |
@@ -113,5 +113,6 @@ object GitBucketCoreModule
|
||||
new Version("4.37.2"),
|
||||
new Version("4.38.0", new LiquibaseMigration("update/gitbucket-core_4.38.xml")),
|
||||
new Version("4.38.1"),
|
||||
new Version("4.38.2")
|
||||
new Version("4.38.2"),
|
||||
new Version("4.38.3")
|
||||
)
|
||||
|
||||
@@ -100,4 +100,16 @@ trait ApiControllerBase extends ControllerBase {
|
||||
get("/api/v3/gitbucket/plugins") {
|
||||
PluginRegistry().getPlugins().map { ApiPlugin(_) }
|
||||
}
|
||||
|
||||
/**
|
||||
* https://docs.github.com/en/enterprise-server@2.21/rest/reference/meta#get-github-enterprise-server-meta-information
|
||||
*/
|
||||
get("/api/v3/meta") {
|
||||
JsonFormat(
|
||||
Map(
|
||||
"https://api.github.com/meta" -> context.loginAccount.isDefined,
|
||||
"installed_version" -> "2.21.0"
|
||||
)
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -69,7 +69,7 @@ trait PullRequestsControllerBase extends ControllerBase {
|
||||
"commitIdFrom" -> trim(text(required, maxlength(40))),
|
||||
"commitIdTo" -> trim(text(required, maxlength(40))),
|
||||
"isDraft" -> trim(boolean(required)),
|
||||
"assignedUserName" -> trim(optional(text())),
|
||||
"assigneeUserNames" -> trim(optional(text())),
|
||||
"milestoneId" -> trim(optional(number())),
|
||||
"priorityId" -> trim(optional(number())),
|
||||
"labelNames" -> trim(optional(text()))
|
||||
@@ -92,7 +92,7 @@ trait PullRequestsControllerBase extends ControllerBase {
|
||||
commitIdFrom: String,
|
||||
commitIdTo: String,
|
||||
isDraft: Boolean,
|
||||
assignedUserNames: Option[String],
|
||||
assigneeUserNames: Option[String],
|
||||
milestoneId: Option[Int],
|
||||
priorityId: Option[Int],
|
||||
labelNames: Option[String]
|
||||
@@ -144,25 +144,6 @@ trait PullRequestsControllerBase extends ControllerBase {
|
||||
getRepository(pullreq.requestUserName, pullreq.requestRepositoryName),
|
||||
flash.iterator.map(f => f._1 -> f._2.toString).toMap
|
||||
)
|
||||
|
||||
// html.pullreq(
|
||||
// issue,
|
||||
// pullreq,
|
||||
// comments,
|
||||
// getIssueLabels(owner, name, issueId),
|
||||
// getAssignableUserNames(owner, name),
|
||||
// getMilestonesWithIssueCount(owner, name),
|
||||
// getPriorities(owner, name),
|
||||
// getLabels(owner, name),
|
||||
// commits,
|
||||
// diffs,
|
||||
// isEditable(repository),
|
||||
// isManageable(repository),
|
||||
// hasDeveloperRole(pullreq.requestUserName, pullreq.requestRepositoryName, context.loginAccount),
|
||||
// repository,
|
||||
// getRepository(pullreq.requestUserName, pullreq.requestRepositoryName),
|
||||
// flash.toMap.map(f => f._1 -> f._2.toString)
|
||||
// )
|
||||
}
|
||||
} getOrElse NotFound()
|
||||
})
|
||||
@@ -396,9 +377,9 @@ trait PullRequestsControllerBase extends ControllerBase {
|
||||
})
|
||||
|
||||
get("/:owner/:repository/compare")(referrersOnly { forkedRepository =>
|
||||
val headBranch: Option[String] = params.get("head")
|
||||
val headBranch = params.get("head")
|
||||
(forkedRepository.repository.originUserName, forkedRepository.repository.originRepositoryName) match {
|
||||
case (Some(originUserName), Some(originRepositoryName)) => {
|
||||
case (Some(originUserName), Some(originRepositoryName)) =>
|
||||
getRepository(originUserName, originRepositoryName).map {
|
||||
originRepository =>
|
||||
Using.resources(
|
||||
@@ -415,8 +396,7 @@ trait PullRequestsControllerBase extends ControllerBase {
|
||||
)
|
||||
}
|
||||
} getOrElse NotFound()
|
||||
}
|
||||
case _ => {
|
||||
case _ =>
|
||||
Using.resource(Git.open(getRepositoryDir(forkedRepository.owner, forkedRepository.name))) { git =>
|
||||
JGitUtil.getDefaultBranch(git, forkedRepository).map {
|
||||
case (_, defaultBranch) =>
|
||||
@@ -428,15 +408,14 @@ trait PullRequestsControllerBase extends ControllerBase {
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
})
|
||||
|
||||
get("/:owner/:repository/compare/*...*")(referrersOnly { forkedRepository =>
|
||||
val Seq(origin, forked) = multiParams("splat")
|
||||
val (originOwner, originId) = parseCompareIdentifier(origin, forkedRepository.owner)
|
||||
val (forkedOwner, forkedId) = parseCompareIdentifier(forked, forkedRepository.owner)
|
||||
|
||||
(for (originRepositoryName <- if (originOwner == forkedOwner) {
|
||||
private def getOriginRepositoryName(
|
||||
originOwner: String,
|
||||
forkedOwner: String,
|
||||
forkedRepository: RepositoryInfo
|
||||
): Option[String] = {
|
||||
if (originOwner == forkedOwner) {
|
||||
// Self repository
|
||||
Some(forkedRepository.name)
|
||||
} else if (forkedRepository.repository.originUserName.isEmpty) {
|
||||
@@ -455,13 +434,21 @@ trait PullRequestsControllerBase extends ControllerBase {
|
||||
x.repository.originRepositoryName == forkedRepository.repository.originRepositoryName
|
||||
}
|
||||
.map(_.repository.repositoryName)
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
get("/:owner/:repository/compare/*...*")(referrersOnly { forkedRepository =>
|
||||
val Seq(origin, forked) = multiParams("splat")
|
||||
val (originOwner, originId) = parseCompareIdentifier(origin, forkedRepository.owner)
|
||||
val (forkedOwner, forkedId) = parseCompareIdentifier(forked, forkedRepository.owner)
|
||||
|
||||
(for (originRepositoryName <- getOriginRepositoryName(originOwner, forkedOwner, forkedRepository);
|
||||
originRepository <- getRepository(originOwner, originRepositoryName)) yield {
|
||||
val (oldId, newId) =
|
||||
getPullRequestCommitFromTo(originRepository, forkedRepository, originId, forkedId)
|
||||
|
||||
(oldId, newId) match {
|
||||
case (Some(oldId), Some(newId)) => {
|
||||
case (Some(oldId), Some(newId)) =>
|
||||
val (commits, diffs) = getRequestCompareInfo(
|
||||
originRepository.owner,
|
||||
originRepository.name,
|
||||
@@ -512,7 +499,6 @@ trait PullRequestsControllerBase extends ControllerBase {
|
||||
getLabels(originRepository.owner, originRepository.name),
|
||||
getCustomFields(originRepository.owner, originRepository.name).filter(_.enableForPullRequests)
|
||||
)
|
||||
}
|
||||
case (oldId, newId) =>
|
||||
redirect(
|
||||
s"/${forkedRepository.owner}/${forkedRepository.name}/compare/" +
|
||||
@@ -524,6 +510,54 @@ trait PullRequestsControllerBase extends ControllerBase {
|
||||
}) getOrElse NotFound()
|
||||
})
|
||||
|
||||
ajaxGet("/:owner/:repository/diff/:id")(referrersOnly { repository =>
|
||||
(for {
|
||||
commitId <- params.get("id")
|
||||
path <- params.get("path")
|
||||
diff <- getSingleDiff(repository.owner, repository.name, commitId, path)
|
||||
} yield {
|
||||
contentType = formats("json")
|
||||
org.json4s.jackson.Serialization.write(
|
||||
Map(
|
||||
"oldContent" -> diff.oldContent,
|
||||
"newContent" -> diff.newContent
|
||||
)
|
||||
)
|
||||
}) getOrElse NotFound()
|
||||
})
|
||||
|
||||
ajaxGet("/:owner/:repository/diff/*...*")(referrersOnly { forkedRepository =>
|
||||
val Seq(origin, forked) = multiParams("splat")
|
||||
val (originOwner, originId) = parseCompareIdentifier(origin, forkedRepository.owner)
|
||||
val (forkedOwner, forkedId) = parseCompareIdentifier(forked, forkedRepository.owner)
|
||||
|
||||
(for {
|
||||
path <- params.get("path")
|
||||
originRepositoryName <- getOriginRepositoryName(originOwner, forkedOwner, forkedRepository)
|
||||
originRepository <- getRepository(originOwner, originRepositoryName)
|
||||
(oldId, newId) = getPullRequestCommitFromTo(originRepository, forkedRepository, originId, forkedId)
|
||||
oldId <- oldId
|
||||
newId <- newId
|
||||
diff <- getSingleDiff(
|
||||
originRepository.owner,
|
||||
originRepository.name,
|
||||
oldId.getName,
|
||||
forkedRepository.owner,
|
||||
forkedRepository.name,
|
||||
newId.getName,
|
||||
path
|
||||
)
|
||||
} yield {
|
||||
contentType = formats("json")
|
||||
org.json4s.jackson.Serialization.write(
|
||||
Map(
|
||||
"oldContent" -> diff.oldContent,
|
||||
"newContent" -> diff.newContent
|
||||
)
|
||||
)
|
||||
}) getOrElse NotFound()
|
||||
})
|
||||
|
||||
ajaxGet("/:owner/:repository/compare/*...*/mergecheck")(readableUsersOnly { forkedRepository =>
|
||||
val Seq(origin, forked) = multiParams("splat")
|
||||
val (originOwner, tmpOriginBranch) = parseCompareIdentifier(origin, forkedRepository.owner)
|
||||
@@ -593,7 +627,7 @@ trait PullRequestsControllerBase extends ControllerBase {
|
||||
|
||||
if (manageable) {
|
||||
// insert assignees
|
||||
form.assignedUserNames.foreach { value =>
|
||||
form.assigneeUserNames.foreach { value =>
|
||||
value.split(",").foreach { userName =>
|
||||
registerIssueAssignee(repository.owner, repository.name, issueId, userName)
|
||||
}
|
||||
|
||||
@@ -331,15 +331,12 @@ trait RepositoryViewerControllerBase extends ControllerBase {
|
||||
post("/:owner/:repository/upload", uploadForm)(writableUsersOnly { (form, repository) =>
|
||||
def _commit(
|
||||
branchName: String,
|
||||
//files: Seq[CommitFile],
|
||||
newFiles: Seq[CommitFile],
|
||||
loginAccount: Account
|
||||
): Either[String, ObjectId] = {
|
||||
commitFiles(
|
||||
repository = repository,
|
||||
branch = branchName,
|
||||
//path = form.path,
|
||||
//files = files.toIndexedSeq,
|
||||
message = form.message.getOrElse("Add files via upload"),
|
||||
loginAccount = loginAccount,
|
||||
settings = context.settings
|
||||
@@ -614,7 +611,7 @@ trait RepositoryViewerControllerBase extends ControllerBase {
|
||||
} else {
|
||||
_commit(form.branch, loginAccount) match {
|
||||
case Right(_) =>
|
||||
if (form.path.length == 0) {
|
||||
if (form.path.isEmpty) {
|
||||
redirect(s"/${repository.owner}/${repository.name}/tree/${encodeRefName(form.branch)}")
|
||||
} else {
|
||||
redirect(
|
||||
|
||||
@@ -242,14 +242,17 @@ trait IssuesService {
|
||||
case (issue, commentCount, _, _, _, milestone, priority, commitId, _) =>
|
||||
IssueInfo(
|
||||
issue,
|
||||
issues.flatMap { t =>
|
||||
issues
|
||||
.flatMap { t =>
|
||||
t._3.map(Label(issue.userName, issue.repositoryName, _, t._4.get, t._5.get))
|
||||
} toList,
|
||||
}
|
||||
.distinct
|
||||
.toList,
|
||||
milestone,
|
||||
priority,
|
||||
commentCount,
|
||||
commitId,
|
||||
issues.flatMap(_._9)
|
||||
issues.flatMap(_._9).distinct
|
||||
)
|
||||
}
|
||||
} toList
|
||||
|
||||
@@ -472,6 +472,40 @@ trait PullRequestService {
|
||||
}
|
||||
}
|
||||
|
||||
def getSingleDiff(
|
||||
userName: String,
|
||||
repositoryName: String,
|
||||
commitId: String,
|
||||
path: String
|
||||
): Option[DiffInfo] = {
|
||||
Using.resource(
|
||||
Git.open(getRepositoryDir(userName, repositoryName))
|
||||
) { git =>
|
||||
val newId = git.getRepository.resolve(commitId)
|
||||
JGitUtil.getDiff(git, None, newId.getName, path)
|
||||
}
|
||||
}
|
||||
|
||||
def getSingleDiff(
|
||||
userName: String,
|
||||
repositoryName: String,
|
||||
branch: String,
|
||||
requestUserName: String,
|
||||
requestRepositoryName: String,
|
||||
requestCommitId: String,
|
||||
path: String
|
||||
): Option[DiffInfo] = {
|
||||
Using.resources(
|
||||
Git.open(getRepositoryDir(userName, repositoryName)),
|
||||
Git.open(getRepositoryDir(requestUserName, requestRepositoryName))
|
||||
) { (oldGit, newGit) =>
|
||||
val oldId = oldGit.getRepository.resolve(branch)
|
||||
val newId = newGit.getRepository.resolve(requestCommitId)
|
||||
|
||||
JGitUtil.getDiff(newGit, Some(oldId.getName), newId.getName, path)
|
||||
}
|
||||
}
|
||||
|
||||
def getRequestCompareInfo(
|
||||
userName: String,
|
||||
repositoryName: String,
|
||||
|
||||
@@ -37,7 +37,7 @@ object JGitUtil {
|
||||
|
||||
private val logger = LoggerFactory.getLogger(JGitUtil.getClass)
|
||||
|
||||
implicit val objectDatabaseReleasable: Releasable[ObjectDatabase] =
|
||||
private implicit val objectDatabaseReleasable: Releasable[ObjectDatabase] =
|
||||
_.close()
|
||||
|
||||
/**
|
||||
@@ -690,7 +690,7 @@ object JGitUtil {
|
||||
|
||||
val toCommit = revWalk.parseCommit(git.getRepository.resolve(to))
|
||||
(from match {
|
||||
case None => {
|
||||
case None =>
|
||||
toCommit.getParentCount match {
|
||||
case 0 =>
|
||||
df.scan(
|
||||
@@ -700,11 +700,9 @@ object JGitUtil {
|
||||
.asScala
|
||||
case _ => df.scan(toCommit.getParent(0), toCommit.getTree).asScala
|
||||
}
|
||||
}
|
||||
case Some(from) => {
|
||||
case Some(from) =>
|
||||
val fromCommit = revWalk.parseCommit(git.getRepository.resolve(from))
|
||||
df.scan(fromCommit.getTree, toCommit.getTree).asScala
|
||||
}
|
||||
}).toSeq
|
||||
}
|
||||
}
|
||||
@@ -719,6 +717,29 @@ object JGitUtil {
|
||||
}
|
||||
}
|
||||
|
||||
def getDiff(git: Git, from: Option[String], to: String, path: String): Option[DiffInfo] = {
|
||||
getDiffEntries(git, from, to).find(_.getNewPath == path).map { diff =>
|
||||
val oldIsImage = FileUtil.isImage(diff.getOldPath)
|
||||
val newIsImage = FileUtil.isImage(diff.getNewPath)
|
||||
val includeContent = oldIsImage || newIsImage
|
||||
DiffInfo(
|
||||
changeType = diff.getChangeType,
|
||||
oldPath = diff.getOldPath,
|
||||
newPath = diff.getNewPath,
|
||||
oldContent = if (includeContent) None else getTextContent(git, diff.getOldId.toObjectId),
|
||||
newContent = if (includeContent) None else getTextContent(git, diff.getNewId.toObjectId),
|
||||
oldIsImage = oldIsImage,
|
||||
newIsImage = newIsImage,
|
||||
oldObjectId = Option(diff.getOldId).map(_.name),
|
||||
newObjectId = Option(diff.getNewId).map(_.name),
|
||||
oldMode = diff.getOldMode.toString,
|
||||
newMode = diff.getNewMode.toString,
|
||||
tooLarge = false,
|
||||
patch = None
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
def getDiffs(
|
||||
git: Git,
|
||||
from: Option[String],
|
||||
@@ -728,7 +749,7 @@ object JGitUtil {
|
||||
): List[DiffInfo] = {
|
||||
val diffs = getDiffEntries(git, from, to)
|
||||
diffs.map { diff =>
|
||||
if (diffs.size > 100) {
|
||||
if (diffs.size > 100) { // Don't show diff if there are more than 100 files
|
||||
DiffInfo(
|
||||
changeType = diff.getChangeType,
|
||||
oldPath = diff.getOldPath,
|
||||
@@ -747,49 +768,35 @@ object JGitUtil {
|
||||
} else {
|
||||
val oldIsImage = FileUtil.isImage(diff.getOldPath)
|
||||
val newIsImage = FileUtil.isImage(diff.getNewPath)
|
||||
if (!fetchContent || oldIsImage || newIsImage) {
|
||||
val patch = if (oldIsImage || newIsImage) None else Some(makePatchFromDiffEntry(git, diff)) // TODO use DiffFormatter
|
||||
val tooLarge = patch.exists(_.count(_ == '\n') > 1000) // Don't show diff if the file has more than 1000 lines diff
|
||||
val includeContent = tooLarge || !fetchContent || oldIsImage || newIsImage
|
||||
DiffInfo(
|
||||
changeType = diff.getChangeType,
|
||||
oldPath = diff.getOldPath,
|
||||
newPath = diff.getNewPath,
|
||||
oldContent = None,
|
||||
newContent = None,
|
||||
oldContent = if (includeContent) None else getTextContent(git, diff.getOldId.toObjectId),
|
||||
newContent = if (includeContent) None else getTextContent(git, diff.getNewId.toObjectId),
|
||||
oldIsImage = oldIsImage,
|
||||
newIsImage = newIsImage,
|
||||
oldObjectId = Option(diff.getOldId).map(_.name),
|
||||
newObjectId = Option(diff.getNewId).map(_.name),
|
||||
oldMode = diff.getOldMode.toString,
|
||||
newMode = diff.getNewMode.toString,
|
||||
tooLarge = false,
|
||||
patch = (if (makePatch) Some(makePatchFromDiffEntry(git, diff)) else None) // TODO use DiffFormatter
|
||||
tooLarge = tooLarge,
|
||||
patch = if (makePatch) patch else None
|
||||
)
|
||||
} else {
|
||||
DiffInfo(
|
||||
changeType = diff.getChangeType,
|
||||
oldPath = diff.getOldPath,
|
||||
newPath = diff.getNewPath,
|
||||
oldContent = JGitUtil
|
||||
.getContentFromId(git, diff.getOldId.toObjectId, false)
|
||||
.filter(FileUtil.isText)
|
||||
.map(convertFromByteArray),
|
||||
newContent = JGitUtil
|
||||
.getContentFromId(git, diff.getNewId.toObjectId, false)
|
||||
.filter(FileUtil.isText)
|
||||
.map(convertFromByteArray),
|
||||
oldIsImage = oldIsImage,
|
||||
newIsImage = newIsImage,
|
||||
oldObjectId = Option(diff.getOldId).map(_.name),
|
||||
newObjectId = Option(diff.getNewId).map(_.name),
|
||||
oldMode = diff.getOldMode.toString,
|
||||
newMode = diff.getNewMode.toString,
|
||||
tooLarge = false,
|
||||
patch = (if (makePatch) Some(makePatchFromDiffEntry(git, diff)) else None) // TODO use DiffFormatter
|
||||
)
|
||||
}
|
||||
}
|
||||
}.toList
|
||||
}
|
||||
|
||||
private def getTextContent(git: Git, objectId: ObjectId): Option[String] = {
|
||||
JGitUtil
|
||||
.getContentFromId(git, objectId, false)
|
||||
.filter(FileUtil.isText)
|
||||
.map(convertFromByteArray)
|
||||
}
|
||||
|
||||
private def makePatchFromDiffEntry(git: Git, diff: DiffEntry): String = {
|
||||
val out = new ByteArrayOutputStream()
|
||||
Using.resource(new DiffFormatter(out)) { formatter =>
|
||||
|
||||
@@ -100,6 +100,19 @@
|
||||
</tr>
|
||||
<tr class="diff-collapse-@i collapse in">
|
||||
<td style="padding: 0;">
|
||||
@if(diff.tooLarge) {
|
||||
<div style="padding: 12px;" id="show-diff-@i">
|
||||
@if(oldCommitId.isEmpty && newCommitId.isDefined) {
|
||||
Too large (<a href="javascript:showDiff(@i, '', '@newCommitId', '@diff.newPath')">Show diff</a>)
|
||||
}
|
||||
@if(oldCommitId.isDefined && newCommitId.isDefined) {
|
||||
Too large (<a href="javascript:showDiff(@i, '@oldCommitId', '@newCommitId', '@diff.newPath')">Show diff</a>)
|
||||
}
|
||||
</div>
|
||||
<div id="diffText-@i" class="diffText"></div>
|
||||
<input type="hidden" id="newText-@i" data-file-name="@diff.newPath" data-val="">
|
||||
<input type="hidden" id="oldText-@i" data-file-name="@diff.oldPath" data-val="">
|
||||
} else {
|
||||
@if(diff.oldObjectId == diff.newObjectId) {
|
||||
@if(diff.oldPath != diff.newPath) {
|
||||
<div class="diff-same">File renamed without changes</div>
|
||||
@@ -129,9 +142,6 @@
|
||||
}
|
||||
}
|
||||
</div>
|
||||
} else {
|
||||
@if(diff.tooLarge){
|
||||
<div style="padding: 12px;">Too large</div>
|
||||
} else {
|
||||
<div style="padding: 12px;">Not supported</div>
|
||||
}
|
||||
@@ -200,53 +210,10 @@ $(function(){
|
||||
renderOneDiff($(this).closest("table").find(".diffText"), window.viewType, $(this).closest("table").find(".file-hash")[0].id);
|
||||
});
|
||||
|
||||
function getInlineContainer(where) {
|
||||
if (window.viewType == 0) {
|
||||
if (where === 'new') {
|
||||
return $('<tr class="not-diff"><td colspan="2"></td><td colspan="2" class="comment-box-container"></td></tr>');
|
||||
} else {
|
||||
return $('<tr class="not-diff"><td colspan="2" class="comment-box-container"></td><td colspan="2"></td></tr>');
|
||||
}
|
||||
}
|
||||
return $('<tr class="not-diff"><td colspan="3" class="comment-box-container"></td></tr>');
|
||||
}
|
||||
|
||||
if (typeof $('#show-notes')[0] !== 'undefined' && !$('#show-notes')[0].checked) {
|
||||
$('#comment-list').children('.inline-comment').hide();
|
||||
}
|
||||
|
||||
function showCommentForm(commitId, fileName, oldLineNumber, newLineNumber, $tr){
|
||||
// assemble Ajax url
|
||||
let url = '@helpers.url(repository)/commit/' + commitId + '/comment/_form?fileName=' + fileName@issueId.map { id => + '&issueId=@id' };
|
||||
if (!isNaN(oldLineNumber) && oldLineNumber) {
|
||||
url += ('&oldLineNumber=' + oldLineNumber)
|
||||
}
|
||||
if (!isNaN(newLineNumber) && newLineNumber) {
|
||||
url += ('&newLineNumber=' + newLineNumber)
|
||||
}
|
||||
// send Ajax request
|
||||
$.get(url, { dataType : 'html' }, function(responseContent) {
|
||||
// create container
|
||||
let tmp;
|
||||
if (!isNaN(oldLineNumber) && oldLineNumber) {
|
||||
if (!isNaN(newLineNumber) && newLineNumber) {
|
||||
tmp = getInlineContainer();
|
||||
} else {
|
||||
tmp = getInlineContainer('old');
|
||||
}
|
||||
} else {
|
||||
tmp = getInlineContainer('new');
|
||||
}
|
||||
// add comment textarea
|
||||
tmp.addClass('inline-comment-form').children('.comment-box-container').html(responseContent);
|
||||
$tr.nextAll(':not(.not-diff):first').before(tmp);
|
||||
// hide reply comment field
|
||||
$(tmp).closest('.not-diff').prev().find('.reply-comment').closest('.not-diff').hide();
|
||||
// focus textarea
|
||||
tmp.find('textarea').focus();
|
||||
});
|
||||
}
|
||||
|
||||
// Add comment button
|
||||
$('.diff-outside').on('click','table.diff .add-comment',function() {
|
||||
const $this = $(this);
|
||||
@@ -302,6 +269,50 @@ $(function(){
|
||||
getSelection().empty();
|
||||
updateHighlighting();
|
||||
});
|
||||
});
|
||||
|
||||
function getInlineContainer(where) {
|
||||
if (window.viewType == 0) {
|
||||
if (where === 'new') {
|
||||
return $('<tr class="not-diff"><td colspan="2"></td><td colspan="2" class="comment-box-container"></td></tr>');
|
||||
} else {
|
||||
return $('<tr class="not-diff"><td colspan="2" class="comment-box-container"></td><td colspan="2"></td></tr>');
|
||||
}
|
||||
}
|
||||
return $('<tr class="not-diff"><td colspan="3" class="comment-box-container"></td></tr>');
|
||||
}
|
||||
|
||||
function showCommentForm(commitId, fileName, oldLineNumber, newLineNumber, $tr){
|
||||
// assemble Ajax url
|
||||
let url = '@helpers.url(repository)/commit/' + commitId + '/comment/_form?fileName=' + fileName@issueId.map { id => + '&issueId=@id' };
|
||||
if (!isNaN(oldLineNumber) && oldLineNumber) {
|
||||
url += ('&oldLineNumber=' + oldLineNumber)
|
||||
}
|
||||
if (!isNaN(newLineNumber) && newLineNumber) {
|
||||
url += ('&newLineNumber=' + newLineNumber)
|
||||
}
|
||||
// send Ajax request
|
||||
$.get(url, { dataType : 'html' }, function(responseContent) {
|
||||
// create container
|
||||
let tmp;
|
||||
if (!isNaN(oldLineNumber) && oldLineNumber) {
|
||||
if (!isNaN(newLineNumber) && newLineNumber) {
|
||||
tmp = getInlineContainer();
|
||||
} else {
|
||||
tmp = getInlineContainer('old');
|
||||
}
|
||||
} else {
|
||||
tmp = getInlineContainer('new');
|
||||
}
|
||||
// add comment textarea
|
||||
tmp.addClass('inline-comment-form').children('.comment-box-container').html(responseContent);
|
||||
$tr.nextAll(':not(.not-diff):first').before(tmp);
|
||||
// hide reply comment field
|
||||
$(tmp).closest('.not-diff').prev().find('.reply-comment').closest('.not-diff').hide();
|
||||
// focus textarea
|
||||
tmp.find('textarea').focus();
|
||||
});
|
||||
}
|
||||
|
||||
function renderOneCommitCommentIntoDiff($v, diff){
|
||||
//var filename = $v.attr('filename');
|
||||
@@ -441,7 +452,25 @@ $(function(){
|
||||
}
|
||||
render();
|
||||
}
|
||||
|
||||
function showDiff(index, fromId, toId, path){
|
||||
let url = '@helpers.url(repository)/diff/';
|
||||
if (fromId == '') {
|
||||
url = url + encodeURIComponent(toId);
|
||||
} else {
|
||||
url = url + encodeURIComponent(fromId) + '...' + encodeURIComponent(toId);
|
||||
}
|
||||
$.get(url, { path : path }, function(data) {
|
||||
$('#oldText-' + index).attr('data-val', data.oldContent);
|
||||
$('#newText-' + index).attr('data-val', data.newContent);
|
||||
const diffs = $('.diffText');
|
||||
const $table = renderOneDiff($(diffs[index]), window.viewType, $('.file-hash')[index].id);
|
||||
@if(hasWritePermission) {
|
||||
renderReplyComment($table);
|
||||
}
|
||||
$('#show-diff-' + index).hide();
|
||||
});
|
||||
}
|
||||
|
||||
function changeDisplaySetting(key, value){
|
||||
let url = '';
|
||||
|
||||
@@ -4,7 +4,7 @@
|
||||
comments: Seq[gitbucket.core.model.Comment],
|
||||
changedFileSize: Int,
|
||||
issueLabels: List[gitbucket.core.model.Label],
|
||||
issueAsignees: List[gitbucket.core.model.IssueAssignee],
|
||||
issueAssignees: List[gitbucket.core.model.IssueAssignee],
|
||||
collaborators: List[String],
|
||||
milestones: List[(gitbucket.core.model.Milestone, Int, Int)],
|
||||
priorities: List[gitbucket.core.model.Priority],
|
||||
@@ -56,7 +56,7 @@
|
||||
Some(issue),
|
||||
comments.toList,
|
||||
issueLabels,
|
||||
issueAsignees,
|
||||
issueAssignees,
|
||||
collaborators,
|
||||
milestones,
|
||||
priorities,
|
||||
|
||||
|
Before Width: | Height: | Size: 949 B After Width: | Height: | Size: 85 B |
|
Before Width: | Height: | Size: 691 B After Width: | Height: | Size: 625 B |
|
Before Width: | Height: | Size: 15 KiB After Width: | Height: | Size: 6.9 KiB |
|
Before Width: | Height: | Size: 7.5 KiB After Width: | Height: | Size: 4.8 KiB |