Compare commits

...

26 Commits

Author SHA1 Message Date
takezoe
753403b4c8 Implement /meta API endpoint 2022-10-30 21:02:23 +09:00
Naoki Takezoe
5a0f9f8bbb Merge 4.38.3 release notes into master 2022-10-30 11:02:49 +09:00
takezoe
8fa22b4de2 Enhance .gitignore 2022-10-30 10:58:07 +09:00
Naoki Takezoe
d17cae16fd Revert "Fix IllegalStateException when returning unknown avatar image (#3158)" (#3179)
This reverts commit a0be02ce2f.
2022-10-30 10:18:49 +09:00
Naoki Takezoe
c4c48962cf Fix an issue that assignees are not saved in PR creation (#3178) 2022-10-30 09:54:33 +09:00
Naoki Takezoe
4140e92f0b Fix an issue that assignees are not saved in PR creation (#3178) 2022-10-30 09:54:18 +09:00
Scala Steward
887e560a1b Update oauth2-oidc-sdk to 10.1 2022-10-28 07:22:22 +09:00
pea-sys
e2d70181e8 png optimization (#3176) 2022-10-27 22:32:08 +09:00
Scala Steward
148c453dbc Update oauth2-oidc-sdk to 10.0 2022-10-24 20:52:36 +09:00
Scala Steward
f6ee9d311d Update thumbnailator to 0.4.18 2022-10-24 08:45:56 +09:00
Scala Steward
35209e43bb Update mockito-core to 4.8.1 2022-10-22 06:50:07 +09:00
Scala Steward
4a3ecf063d Update sbt-assembly to 2.0.0 2022-10-18 06:54:35 +09:00
Naoki Takezoe
4c79101624 Fix duplications in issue labels and assignees (#3168) 2022-10-17 01:00:22 +09:00
Naoki Takezoe
921b01661b Upgrade Scalatra to 2.8.4 (#3165) 2022-10-16 16:49:47 +09:00
Scala Steward
c63301d8e6 Update testcontainers-scala to 0.40.11 2022-10-11 12:22:12 +09:00
Naoki Takezoe
c9ed9d2237 Hide large diffs by default and show on demand (#3157) 2022-10-10 15:49:37 +09:00
Naoki Takezoe
ca55cbe456 Disable scalafmt on compile (#3160) 2022-10-10 03:15:59 +09:00
Scala Steward
d4828613ee Update scala-library to 2.13.10 2022-10-09 05:13:06 +09:00
Naoki Takezoe
a0be02ce2f Fix IllegalStateException when returning unknown avatar image (#3158) 2022-10-08 11:24:03 +09:00
Scala Steward
9b8016a4d5 Update mysql, postgresql to 1.17.5 2022-10-05 06:25:59 +09:00
Scala Steward
8fdd3bfd21 Update tika-core to 2.5.0 2022-10-04 06:11:07 +09:00
Scala Steward
695a061e3c Update sbt, sbt-dependency-tree to 1.7.2 2022-10-03 16:05:29 +09:00
Scala Steward
bd50d9218e Update mysql, postgresql to 1.17.4 2022-09-30 06:13:37 +09:00
Scala Steward
d8f13bc1ce Update json4s-jackson to 4.0.6 2022-09-29 17:14:45 +09:00
Scala Steward
ed84d1a3c9 Update github-api to 1.313 2022-09-27 18:50:29 +09:00
Scala Steward
3c765d879c Update mariadb-java-client to 3.0.8 2022-09-21 01:05:42 +09:00
21 changed files with 442 additions and 315 deletions

2
.gitignore vendored
View File

@@ -2,6 +2,8 @@
*.log *.log
.ensime .ensime
.ensime_cache .ensime_cache
.DS_Store
.java-version
# sbt specific # sbt specific
dist/* dist/*

View File

@@ -1,6 +1,10 @@
# Changelog # Changelog
All changes to the project will be documented in this file. 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 ## 4.38.2 - 20 Sep 2022
- Resurrect assignee icons on the issue list - Resurrect assignee icons on the issue list

View File

@@ -61,6 +61,10 @@ Support
What's New in 4.38.x 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 ## 4.38.2 - 20 Sep 2022
- Resurrect assignee icons on the issue list - Resurrect assignee icons on the issue list

View File

@@ -3,8 +3,8 @@ import com.jsuereth.sbtpgp.PgpKeys._
val Organization = "io.github.gitbucket" val Organization = "io.github.gitbucket"
val Name = "gitbucket" val Name = "gitbucket"
val GitBucketVersion = "4.38.2" val GitBucketVersion = "4.38.3"
val ScalatraVersion = "2.8.2" val ScalatraVersion = "2.8.4"
val JettyVersion = "9.4.49.v20220914" val JettyVersion = "9.4.49.v20220914"
val JgitVersion = "5.13.1.202206130422-r" val JgitVersion = "5.13.1.202206130422-r"
@@ -15,9 +15,9 @@ sourcesInBase := false
organization := Organization organization := Organization
name := Name name := Name
version := GitBucketVersion version := GitBucketVersion
scalaVersion := "2.13.9" scalaVersion := "2.13.10"
scalafmtOnCompile := true // scalafmtOnCompile := true
coverageExcludedPackages := ".*\\.html\\..*" coverageExcludedPackages := ".*\\.html\\..*"
@@ -33,7 +33,7 @@ libraryDependencies ++= Seq(
"org.scalatra" %% "scalatra" % ScalatraVersion cross CrossVersion.for3Use2_13, "org.scalatra" %% "scalatra" % ScalatraVersion cross CrossVersion.for3Use2_13,
"org.scalatra" %% "scalatra-json" % ScalatraVersion cross CrossVersion.for3Use2_13, "org.scalatra" %% "scalatra-json" % ScalatraVersion cross CrossVersion.for3Use2_13,
"org.scalatra" %% "scalatra-forms" % 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", "commons-io" % "commons-io" % "2.11.0",
"io.github.gitbucket" % "solidbase" % "1.0.5", "io.github.gitbucket" % "solidbase" % "1.0.5",
"io.github.gitbucket" % "markedj" % "1.0.17", "io.github.gitbucket" % "markedj" % "1.0.17",
@@ -42,11 +42,11 @@ libraryDependencies ++= Seq(
"commons-net" % "commons-net" % "3.8.0", "commons-net" % "commons-net" % "3.8.0",
"org.apache.httpcomponents" % "httpclient" % "4.5.13", "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.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.github.takezoe" %% "blocking-slick-32" % "0.0.12" cross CrossVersion.for3Use2_13,
"com.novell.ldap" % "jldap" % "2009-10-07", "com.novell.ldap" % "jldap" % "2009-10-07",
"com.h2database" % "h2" % "1.4.199", "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", "org.postgresql" % "postgresql" % "42.5.0",
"ch.qos.logback" % "logback-classic" % "1.2.11", "ch.qos.logback" % "logback-classic" % "1.2.11",
"com.zaxxer" % "HikariCP" % "4.0.3" exclude ("org.slf4j", "slf4j-api"), "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", "fr.brouillard.oss.security.xhub" % "xhub4j-core" % "1.1.0",
"io.github.java-diff-utils" % "java-diff-utils" % "4.12", "io.github.java-diff-utils" % "java-diff-utils" % "4.12",
"org.cache2k" % "cache2k-all" % "1.6.0.Final", "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.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", "org.eclipse.jetty" % "jetty-webapp" % JettyVersion % "provided",
"javax.servlet" % "javax.servlet-api" % "3.1.0" % "provided", "javax.servlet" % "javax.servlet-api" % "3.1.0" % "provided",
"junit" % "junit" % "4.13.2" % "test", "junit" % "junit" % "4.13.2" % "test",
"org.scalatra" %% "scalatra-scalatest" % ScalatraVersion % "test" cross CrossVersion.for3Use2_13, "org.scalatra" %% "scalatra-scalatest" % ScalatraVersion % "test" cross CrossVersion.for3Use2_13,
"org.mockito" % "mockito-core" % "4.8.0" % "test", "org.mockito" % "mockito-core" % "4.8.1" % "test",
"com.dimafeng" %% "testcontainers-scala" % "0.40.10" % "test", "com.dimafeng" %% "testcontainers-scala" % "0.40.11" % "test",
"org.testcontainers" % "mysql" % "1.17.3" % "test", "org.testcontainers" % "mysql" % "1.17.5" % "test",
"org.testcontainers" % "postgresql" % "1.17.3" % "test", "org.testcontainers" % "postgresql" % "1.17.5" % "test",
"net.i2p.crypto" % "eddsa" % "0.3.0", "net.i2p.crypto" % "eddsa" % "0.3.0",
"is.tagomor.woothee" % "woothee-java" % "1.11.0", "is.tagomor.woothee" % "woothee-java" % "1.11.0",
"org.ec4j.core" % "ec4j-core" % "0.3.0", "org.ec4j.core" % "ec4j-core" % "0.3.0",
"org.kohsuke" % "github-api" % "1.308" % "test" "org.kohsuke" % "github-api" % "1.313" % "test"
) )
libraryDependencies ~= { libraryDependencies ~= {

Binary file not shown.

Before

Width:  |  Height:  |  Size: 203 KiB

After

Width:  |  Height:  |  Size: 112 KiB

View File

@@ -1 +1 @@
sbt.version=1.7.1 sbt.version=1.7.2

View File

@@ -2,7 +2,7 @@ scalacOptions ++= Seq("-unchecked", "-deprecation", "-feature")
addSbtPlugin("org.scalameta" % "sbt-scalafmt" % "2.4.6") addSbtPlugin("org.scalameta" % "sbt-scalafmt" % "2.4.6")
addSbtPlugin("com.typesafe.sbt" % "sbt-twirl" % "1.5.1") 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("org.scalatra.sbt" % "sbt-scalatra" % "1.0.4")
addSbtPlugin("com.github.sbt" % "sbt-pgp" % "2.1.2") addSbtPlugin("com.github.sbt" % "sbt-pgp" % "2.1.2")
addSbtPlugin("com.typesafe.sbt" % "sbt-license-report" % "1.2.0") addSbtPlugin("com.typesafe.sbt" % "sbt-license-report" % "1.2.0")

Binary file not shown.

Before

Width:  |  Height:  |  Size: 3.0 KiB

After

Width:  |  Height:  |  Size: 1.5 KiB

View File

@@ -113,5 +113,6 @@ object GitBucketCoreModule
new Version("4.37.2"), new Version("4.37.2"),
new Version("4.38.0", new LiquibaseMigration("update/gitbucket-core_4.38.xml")), new Version("4.38.0", new LiquibaseMigration("update/gitbucket-core_4.38.xml")),
new Version("4.38.1"), new Version("4.38.1"),
new Version("4.38.2") new Version("4.38.2"),
new Version("4.38.3")
) )

View File

@@ -100,4 +100,16 @@ trait ApiControllerBase extends ControllerBase {
get("/api/v3/gitbucket/plugins") { get("/api/v3/gitbucket/plugins") {
PluginRegistry().getPlugins().map { ApiPlugin(_) } 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"
)
)
}
} }

View File

@@ -69,7 +69,7 @@ trait PullRequestsControllerBase extends ControllerBase {
"commitIdFrom" -> trim(text(required, maxlength(40))), "commitIdFrom" -> trim(text(required, maxlength(40))),
"commitIdTo" -> trim(text(required, maxlength(40))), "commitIdTo" -> trim(text(required, maxlength(40))),
"isDraft" -> trim(boolean(required)), "isDraft" -> trim(boolean(required)),
"assignedUserName" -> trim(optional(text())), "assigneeUserNames" -> trim(optional(text())),
"milestoneId" -> trim(optional(number())), "milestoneId" -> trim(optional(number())),
"priorityId" -> trim(optional(number())), "priorityId" -> trim(optional(number())),
"labelNames" -> trim(optional(text())) "labelNames" -> trim(optional(text()))
@@ -92,7 +92,7 @@ trait PullRequestsControllerBase extends ControllerBase {
commitIdFrom: String, commitIdFrom: String,
commitIdTo: String, commitIdTo: String,
isDraft: Boolean, isDraft: Boolean,
assignedUserNames: Option[String], assigneeUserNames: Option[String],
milestoneId: Option[Int], milestoneId: Option[Int],
priorityId: Option[Int], priorityId: Option[Int],
labelNames: Option[String] labelNames: Option[String]
@@ -144,25 +144,6 @@ trait PullRequestsControllerBase extends ControllerBase {
getRepository(pullreq.requestUserName, pullreq.requestRepositoryName), getRepository(pullreq.requestUserName, pullreq.requestRepositoryName),
flash.iterator.map(f => f._1 -> f._2.toString).toMap 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() } getOrElse NotFound()
}) })
@@ -396,9 +377,9 @@ trait PullRequestsControllerBase extends ControllerBase {
}) })
get("/:owner/:repository/compare")(referrersOnly { forkedRepository => 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 { (forkedRepository.repository.originUserName, forkedRepository.repository.originRepositoryName) match {
case (Some(originUserName), Some(originRepositoryName)) => { case (Some(originUserName), Some(originRepositoryName)) =>
getRepository(originUserName, originRepositoryName).map { getRepository(originUserName, originRepositoryName).map {
originRepository => originRepository =>
Using.resources( Using.resources(
@@ -415,8 +396,7 @@ trait PullRequestsControllerBase extends ControllerBase {
) )
} }
} getOrElse NotFound() } getOrElse NotFound()
} case _ =>
case _ => {
Using.resource(Git.open(getRepositoryDir(forkedRepository.owner, forkedRepository.name))) { git => Using.resource(Git.open(getRepositoryDir(forkedRepository.owner, forkedRepository.name))) { git =>
JGitUtil.getDefaultBranch(git, forkedRepository).map { JGitUtil.getDefaultBranch(git, forkedRepository).map {
case (_, defaultBranch) => case (_, defaultBranch) =>
@@ -427,41 +407,48 @@ trait PullRequestsControllerBase extends ControllerBase {
redirect(s"/${forkedRepository.owner}/${forkedRepository.name}") redirect(s"/${forkedRepository.owner}/${forkedRepository.name}")
} }
} }
}
} }
}) })
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) {
// when ForkedRepository is the original repository
getForkedRepositories(forkedRepository.owner, forkedRepository.name)
.find(_.userName == originOwner)
.map(_.repositoryName)
} else if (Some(originOwner) == forkedRepository.repository.originUserName) {
// Original repository
forkedRepository.repository.originRepositoryName
} else {
// Sibling repository
getUserRepositories(originOwner)
.find { x =>
x.repository.originUserName == forkedRepository.repository.originUserName &&
x.repository.originRepositoryName == forkedRepository.repository.originRepositoryName
}
.map(_.repository.repositoryName)
}
}
get("/:owner/:repository/compare/*...*")(referrersOnly { forkedRepository => get("/:owner/:repository/compare/*...*")(referrersOnly { forkedRepository =>
val Seq(origin, forked) = multiParams("splat") val Seq(origin, forked) = multiParams("splat")
val (originOwner, originId) = parseCompareIdentifier(origin, forkedRepository.owner) val (originOwner, originId) = parseCompareIdentifier(origin, forkedRepository.owner)
val (forkedOwner, forkedId) = parseCompareIdentifier(forked, forkedRepository.owner) val (forkedOwner, forkedId) = parseCompareIdentifier(forked, forkedRepository.owner)
(for (originRepositoryName <- if (originOwner == forkedOwner) { (for (originRepositoryName <- getOriginRepositoryName(originOwner, forkedOwner, forkedRepository);
// Self repository
Some(forkedRepository.name)
} else if (forkedRepository.repository.originUserName.isEmpty) {
// when ForkedRepository is the original repository
getForkedRepositories(forkedRepository.owner, forkedRepository.name)
.find(_.userName == originOwner)
.map(_.repositoryName)
} else if (Some(originOwner) == forkedRepository.repository.originUserName) {
// Original repository
forkedRepository.repository.originRepositoryName
} else {
// Sibling repository
getUserRepositories(originOwner)
.find { x =>
x.repository.originUserName == forkedRepository.repository.originUserName &&
x.repository.originRepositoryName == forkedRepository.repository.originRepositoryName
}
.map(_.repository.repositoryName)
};
originRepository <- getRepository(originOwner, originRepositoryName)) yield { originRepository <- getRepository(originOwner, originRepositoryName)) yield {
val (oldId, newId) = val (oldId, newId) =
getPullRequestCommitFromTo(originRepository, forkedRepository, originId, forkedId) getPullRequestCommitFromTo(originRepository, forkedRepository, originId, forkedId)
(oldId, newId) match { (oldId, newId) match {
case (Some(oldId), Some(newId)) => { case (Some(oldId), Some(newId)) =>
val (commits, diffs) = getRequestCompareInfo( val (commits, diffs) = getRequestCompareInfo(
originRepository.owner, originRepository.owner,
originRepository.name, originRepository.name,
@@ -512,7 +499,6 @@ trait PullRequestsControllerBase extends ControllerBase {
getLabels(originRepository.owner, originRepository.name), getLabels(originRepository.owner, originRepository.name),
getCustomFields(originRepository.owner, originRepository.name).filter(_.enableForPullRequests) getCustomFields(originRepository.owner, originRepository.name).filter(_.enableForPullRequests)
) )
}
case (oldId, newId) => case (oldId, newId) =>
redirect( redirect(
s"/${forkedRepository.owner}/${forkedRepository.name}/compare/" + s"/${forkedRepository.owner}/${forkedRepository.name}/compare/" +
@@ -524,6 +510,54 @@ trait PullRequestsControllerBase extends ControllerBase {
}) getOrElse NotFound() }) 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 => ajaxGet("/:owner/:repository/compare/*...*/mergecheck")(readableUsersOnly { forkedRepository =>
val Seq(origin, forked) = multiParams("splat") val Seq(origin, forked) = multiParams("splat")
val (originOwner, tmpOriginBranch) = parseCompareIdentifier(origin, forkedRepository.owner) val (originOwner, tmpOriginBranch) = parseCompareIdentifier(origin, forkedRepository.owner)
@@ -593,7 +627,7 @@ trait PullRequestsControllerBase extends ControllerBase {
if (manageable) { if (manageable) {
// insert assignees // insert assignees
form.assignedUserNames.foreach { value => form.assigneeUserNames.foreach { value =>
value.split(",").foreach { userName => value.split(",").foreach { userName =>
registerIssueAssignee(repository.owner, repository.name, issueId, userName) registerIssueAssignee(repository.owner, repository.name, issueId, userName)
} }

View File

@@ -331,15 +331,12 @@ trait RepositoryViewerControllerBase extends ControllerBase {
post("/:owner/:repository/upload", uploadForm)(writableUsersOnly { (form, repository) => post("/:owner/:repository/upload", uploadForm)(writableUsersOnly { (form, repository) =>
def _commit( def _commit(
branchName: String, branchName: String,
//files: Seq[CommitFile],
newFiles: Seq[CommitFile], newFiles: Seq[CommitFile],
loginAccount: Account loginAccount: Account
): Either[String, ObjectId] = { ): Either[String, ObjectId] = {
commitFiles( commitFiles(
repository = repository, repository = repository,
branch = branchName, branch = branchName,
//path = form.path,
//files = files.toIndexedSeq,
message = form.message.getOrElse("Add files via upload"), message = form.message.getOrElse("Add files via upload"),
loginAccount = loginAccount, loginAccount = loginAccount,
settings = context.settings settings = context.settings
@@ -614,7 +611,7 @@ trait RepositoryViewerControllerBase extends ControllerBase {
} else { } else {
_commit(form.branch, loginAccount) match { _commit(form.branch, loginAccount) match {
case Right(_) => case Right(_) =>
if (form.path.length == 0) { if (form.path.isEmpty) {
redirect(s"/${repository.owner}/${repository.name}/tree/${encodeRefName(form.branch)}") redirect(s"/${repository.owner}/${repository.name}/tree/${encodeRefName(form.branch)}")
} else { } else {
redirect( redirect(

View File

@@ -242,14 +242,17 @@ trait IssuesService {
case (issue, commentCount, _, _, _, milestone, priority, commitId, _) => case (issue, commentCount, _, _, _, milestone, priority, commitId, _) =>
IssueInfo( IssueInfo(
issue, issue,
issues.flatMap { t => issues
t._3.map(Label(issue.userName, issue.repositoryName, _, t._4.get, t._5.get)) .flatMap { t =>
} toList, t._3.map(Label(issue.userName, issue.repositoryName, _, t._4.get, t._5.get))
}
.distinct
.toList,
milestone, milestone,
priority, priority,
commentCount, commentCount,
commitId, commitId,
issues.flatMap(_._9) issues.flatMap(_._9).distinct
) )
} }
} toList } toList

View File

@@ -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( def getRequestCompareInfo(
userName: String, userName: String,
repositoryName: String, repositoryName: String,

View File

@@ -37,7 +37,7 @@ object JGitUtil {
private val logger = LoggerFactory.getLogger(JGitUtil.getClass) private val logger = LoggerFactory.getLogger(JGitUtil.getClass)
implicit val objectDatabaseReleasable: Releasable[ObjectDatabase] = private implicit val objectDatabaseReleasable: Releasable[ObjectDatabase] =
_.close() _.close()
/** /**
@@ -690,7 +690,7 @@ object JGitUtil {
val toCommit = revWalk.parseCommit(git.getRepository.resolve(to)) val toCommit = revWalk.parseCommit(git.getRepository.resolve(to))
(from match { (from match {
case None => { case None =>
toCommit.getParentCount match { toCommit.getParentCount match {
case 0 => case 0 =>
df.scan( df.scan(
@@ -700,11 +700,9 @@ object JGitUtil {
.asScala .asScala
case _ => df.scan(toCommit.getParent(0), toCommit.getTree).asScala case _ => df.scan(toCommit.getParent(0), toCommit.getTree).asScala
} }
} case Some(from) =>
case Some(from) => {
val fromCommit = revWalk.parseCommit(git.getRepository.resolve(from)) val fromCommit = revWalk.parseCommit(git.getRepository.resolve(from))
df.scan(fromCommit.getTree, toCommit.getTree).asScala df.scan(fromCommit.getTree, toCommit.getTree).asScala
}
}).toSeq }).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( def getDiffs(
git: Git, git: Git,
from: Option[String], from: Option[String],
@@ -728,7 +749,7 @@ object JGitUtil {
): List[DiffInfo] = { ): List[DiffInfo] = {
val diffs = getDiffEntries(git, from, to) val diffs = getDiffEntries(git, from, to)
diffs.map { diff => diffs.map { diff =>
if (diffs.size > 100) { if (diffs.size > 100) { // Don't show diff if there are more than 100 files
DiffInfo( DiffInfo(
changeType = diff.getChangeType, changeType = diff.getChangeType,
oldPath = diff.getOldPath, oldPath = diff.getOldPath,
@@ -747,49 +768,35 @@ object JGitUtil {
} else { } else {
val oldIsImage = FileUtil.isImage(diff.getOldPath) val oldIsImage = FileUtil.isImage(diff.getOldPath)
val newIsImage = FileUtil.isImage(diff.getNewPath) val newIsImage = FileUtil.isImage(diff.getNewPath)
if (!fetchContent || oldIsImage || newIsImage) { val patch = if (oldIsImage || newIsImage) None else Some(makePatchFromDiffEntry(git, diff)) // TODO use DiffFormatter
DiffInfo( val tooLarge = patch.exists(_.count(_ == '\n') > 1000) // Don't show diff if the file has more than 1000 lines diff
changeType = diff.getChangeType, val includeContent = tooLarge || !fetchContent || oldIsImage || newIsImage
oldPath = diff.getOldPath, DiffInfo(
newPath = diff.getNewPath, changeType = diff.getChangeType,
oldContent = None, oldPath = diff.getOldPath,
newContent = None, newPath = diff.getNewPath,
oldIsImage = oldIsImage, oldContent = if (includeContent) None else getTextContent(git, diff.getOldId.toObjectId),
newIsImage = newIsImage, newContent = if (includeContent) None else getTextContent(git, diff.getNewId.toObjectId),
oldObjectId = Option(diff.getOldId).map(_.name), oldIsImage = oldIsImage,
newObjectId = Option(diff.getNewId).map(_.name), newIsImage = newIsImage,
oldMode = diff.getOldMode.toString, oldObjectId = Option(diff.getOldId).map(_.name),
newMode = diff.getNewMode.toString, newObjectId = Option(diff.getNewId).map(_.name),
tooLarge = false, oldMode = diff.getOldMode.toString,
patch = (if (makePatch) Some(makePatchFromDiffEntry(git, diff)) else None) // TODO use DiffFormatter newMode = diff.getNewMode.toString,
) tooLarge = tooLarge,
} else { patch = if (makePatch) patch else None
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 }.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 = { private def makePatchFromDiffEntry(git: Git, diff: DiffEntry): String = {
val out = new ByteArrayOutputStream() val out = new ByteArrayOutputStream()
Using.resource(new DiffFormatter(out)) { formatter => Using.resource(new DiffFormatter(out)) { formatter =>

View File

@@ -100,38 +100,48 @@
</tr> </tr>
<tr class="diff-collapse-@i collapse in"> <tr class="diff-collapse-@i collapse in">
<td style="padding: 0;"> <td style="padding: 0;">
@if(diff.oldObjectId == diff.newObjectId){ @if(diff.tooLarge) {
@if(diff.oldPath != diff.newPath){ <div style="padding: 12px;" id="show-diff-@i">
<div class="diff-same">File renamed without changes</div> @if(oldCommitId.isEmpty && newCommitId.isDefined) {
} else { Too large (<a href="javascript:showDiff(@i, '', '@newCommitId', '@diff.newPath')">Show diff</a>)
<div class="diff-same">File mode changed</div> }
} @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 { } else {
@if(diff.newContent != None || diff.oldContent != None){ @if(diff.oldObjectId == diff.newObjectId) {
<div id="diffText-@i" class="diffText"></div> @if(diff.oldPath != diff.newPath) {
<input type="hidden" id="newText-@i" data-file-name="@diff.newPath" data-val="@diff.newContent"> <div class="diff-same">File renamed without changes</div>
<input type="hidden" id="oldText-@i" data-file-name="@diff.oldPath" data-val="@diff.oldContent">
} else {
@if(diff.newIsImage || diff.oldIsImage){
<div class="diff-image-render diff2up">
@if(oldCommitId.isDefined && diff.oldIsImage){
<div class="diff-image-frame diff-old"><img src="@helpers.url(repository)/raw/@oldCommitId.get/@diff.oldPath" class="diff-image" onload="onLoadedDiffImages(this)" style="display:none" /></div>
} else {
@if(diff.changeType != ChangeType.ADD){
<div style="padding: 12px;">Not supported</div>
}
}
@if(newCommitId.isDefined && diff.newIsImage){
<div class="diff-image-frame diff-new"><img src="@helpers.url(repository)/raw/@newCommitId.get/@diff.newPath" class="diff-image" onload="onLoadedDiffImages(this)" style="display:none" /></div>
} else {
@if(diff.changeType != ChangeType.DELETE){
<div style="padding: 12px;">Not supported</div>
}
}
</div>
} else { } else {
@if(diff.tooLarge){ <div class="diff-same">File mode changed</div>
<div style="padding: 12px;">Too large</div> }
} else {
@if(diff.newContent != None || diff.oldContent != None){
<div id="diffText-@i" class="diffText"></div>
<input type="hidden" id="newText-@i" data-file-name="@diff.newPath" data-val="@diff.newContent">
<input type="hidden" id="oldText-@i" data-file-name="@diff.oldPath" data-val="@diff.oldContent">
} else {
@if(diff.newIsImage || diff.oldIsImage){
<div class="diff-image-render diff2up">
@if(oldCommitId.isDefined && diff.oldIsImage){
<div class="diff-image-frame diff-old"><img src="@helpers.url(repository)/raw/@oldCommitId.get/@diff.oldPath" class="diff-image" onload="onLoadedDiffImages(this)" style="display:none" /></div>
} else {
@if(diff.changeType != ChangeType.ADD){
<div style="padding: 12px;">Not supported</div>
}
}
@if(newCommitId.isDefined && diff.newIsImage){
<div class="diff-image-frame diff-new"><img src="@helpers.url(repository)/raw/@newCommitId.get/@diff.newPath" class="diff-image" onload="onLoadedDiffImages(this)" style="display:none" /></div>
} else {
@if(diff.changeType != ChangeType.DELETE){
<div style="padding: 12px;">Not supported</div>
}
}
</div>
} else { } else {
<div style="padding: 12px;">Not supported</div> <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); 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) { if (typeof $('#show-notes')[0] !== 'undefined' && !$('#show-notes')[0].checked) {
$('#comment-list').children('.inline-comment').hide(); $('#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 // Add comment button
$('.diff-outside').on('click','table.diff .add-comment',function() { $('.diff-outside').on('click','table.diff .add-comment',function() {
const $this = $(this); const $this = $(this);
@@ -302,11 +269,156 @@ $(function(){
getSelection().empty(); getSelection().empty();
updateHighlighting(); 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');
const oldline = $v.attr('oldline');
const newline = $v.attr('newline');
let tmp;
if (typeof oldline !== 'undefined') {
if (typeof newline !== 'undefined') {
tmp = getInlineContainer();
} else {
tmp = getInlineContainer('old');
}
tmp.children('td:first').html($v.clone().show());
diff.find('table.diff').find('.oldline[line-number=' + oldline + ']').parent().nextAll(':not(.not-diff):first').before(tmp);
} else {
tmp = getInlineContainer('new');
tmp.children('td:last').html($v.clone().show());
diff.find('table.diff').find('.newline[line-number=' + newline + ']').parent().nextAll(':not(.not-diff):first').before(tmp);
}
if (!diff.find('.toggle-notes').prop('checked')) {
tmp.hide();
}
}
function renderStatBar(add, del){
if(add + del > 5){
if(add){
if(add < del){
add = Math.floor(1 + (add * 4 / (add + del)));
} else {
add = Math.ceil(1 + (add * 4 / (add + del)));
}
}
del = 5 - add;
}
const ret = $('<div class="diffstat-bar">');
for(let i = 0; i < 5; i++){
if(add){
ret.append('<span class="text-diff-added">■</span>');
add--;
} else if(del){
ret.append('<span class="text-diff-deleted">■</span>');
del--;
} else {
ret.append('■');
}
}
return ret;
}
function renderOneDiff(diffText, viewType, fileHash){
const table = diffText.closest("table[data-diff-id]");
const i = table.data("diff-id");
const ignoreWhiteSpace = table.find('.ignore-whitespace').prop('checked');
diffUsingJS('oldText-' + i, 'newText-' + i, diffText.attr('id'), viewType, ignoreWhiteSpace, fileHash);
const add = diffText.find("table").attr("add") * 1;
const del = diffText.find("table").attr("del") * 1;
table.find(".diffstat").text(add + del + " ").append(renderStatBar(add, del)).attr("title", add + " additions & " + del + " deletions").tooltip();
$('span.diffstat[data-diff-id="' + i + '"]')
.html('<span class="text-diff-added">+' + add + '</span><span class="text-diff-deleted">-' + del + '</span>')
.append(renderStatBar(add, del).attr('title', (add + del) + " lines changed").tooltip());
@if(hasWritePermission) {
diffText.find('.body').filter(function(i, e) {
return $(e).has('span').length > 0;
}).each(function(){
$('<b class="add-comment">+</b>').prependTo(this);
});
}
@if(showLineNotes){
const fileName = table.attr('filename');
$('.inline-comment').each(function(i, v) {
if($(this).attr('filename') == fileName){
renderOneCommitCommentIntoDiff($(this), table);
}
});
}
return table;
}
function renderReplyComment($table){
const elements = {};
let filename, newline, oldline;
$table.find('.comment-box-container .inline-comment').each(function(i, e){
filename = $(e).attr('filename');
newline = $(e).attr('newline');
oldline = $(e).attr('oldline');
const key = filename + '-' + newline + '-' + oldline;
elements[key] = {
element: $(e),
filename: filename,
newline: newline,
oldline: oldline
};
});
for(const key in elements){
filename = elements[key]['filename'];
oldline = elements[key]['oldline']; //? elements[key]['oldline'] : '';
newline = elements[key]['newline']; //? elements[key]['newline'] : '';
const $v = $('<div class="commit-comment-box reply-comment-box">')
.append($('<input type="text" class="form-control reply-comment" placeholder="Reply..." '
+ 'data-filename="' + filename + '" '
+ 'data-newline="' + newline + '" '
+ 'data-oldline="' + oldline + '">'));
function renderOneCommitCommentIntoDiff($v, diff){
//var filename = $v.attr('filename');
const oldline = $v.attr('oldline');
const newline = $v.attr('newline');
let tmp; let tmp;
if (typeof oldline !== 'undefined') { if (typeof oldline !== 'undefined') {
if (typeof newline !== 'undefined') { if (typeof newline !== 'undefined') {
@@ -314,134 +426,51 @@ $(function(){
} else { } else {
tmp = getInlineContainer('old'); tmp = getInlineContainer('old');
} }
tmp.children('td:first').html($v.clone().show()); tmp.children('td:first').html($v);
diff.find('table.diff').find('.oldline[line-number=' + oldline + ']').parent().nextAll(':not(.not-diff):first').before(tmp);
} else { } else {
tmp = getInlineContainer('new'); tmp = getInlineContainer('new');
tmp.children('td:last').html($v.clone().show()); tmp.children('td:last').html($v);
diff.find('table.diff').find('.newline[line-number=' + newline + ']').parent().nextAll(':not(.not-diff):first').before(tmp);
}
if (!diff.find('.toggle-notes').prop('checked')) {
tmp.hide();
} }
elements[key]['element'].closest('.not-diff').after(tmp);
} }
}
function renderStatBar(add, del){ function renderDiffs() {
if(add + del > 5){ const diffs = $('.diffText');
if(add){ let i = 0;
if(add < del){ function render(){
add = Math.floor(1 + (add * 4 / (add + del))); if (diffs[i]) {
} else { const $table = renderOneDiff($(diffs[i]), window.viewType, $('.file-hash')[i].id);
add = Math.ceil(1 + (add * 4 / (add + del))); @if(hasWritePermission) {
} renderReplyComment($table);
} }
del = 5 - add; i++;
} setTimeout(render);
const ret = $('<div class="diffstat-bar">'); } else {
for(let i = 0; i < 5; i++){ updateHighlighting();
if(add){
ret.append('<span class="text-diff-added">■</span>');
add--;
} else if(del){
ret.append('<span class="text-diff-deleted">■</span>');
del--;
} else {
ret.append('■');
}
}
return ret;
}
function renderOneDiff(diffText, viewType, fileHash){
const table = diffText.closest("table[data-diff-id]");
const i = table.data("diff-id");
const ignoreWhiteSpace = table.find('.ignore-whitespace').prop('checked');
diffUsingJS('oldText-' + i, 'newText-' + i, diffText.attr('id'), viewType, ignoreWhiteSpace, fileHash);
const add = diffText.find("table").attr("add") * 1;
const del = diffText.find("table").attr("del") * 1;
table.find(".diffstat").text(add + del + " ").append(renderStatBar(add, del)).attr("title", add + " additions & " + del + " deletions").tooltip();
$('span.diffstat[data-diff-id="' + i + '"]')
.html('<span class="text-diff-added">+' + add + '</span><span class="text-diff-deleted">-' + del + '</span>')
.append(renderStatBar(add, del).attr('title', (add + del) + " lines changed").tooltip());
@if(hasWritePermission) {
diffText.find('.body').filter(function(i, e) {
return $(e).has('span').length > 0;
}).each(function(){
$('<b class="add-comment">+</b>').prependTo(this);
});
}
@if(showLineNotes){
const fileName = table.attr('filename');
$('.inline-comment').each(function(i, v) {
if($(this).attr('filename') == fileName){
renderOneCommitCommentIntoDiff($(this), table);
}
});
}
return table;
}
function renderReplyComment($table){
const elements = {};
let filename, newline, oldline;
$table.find('.comment-box-container .inline-comment').each(function(i, e){
filename = $(e).attr('filename');
newline = $(e).attr('newline');
oldline = $(e).attr('oldline');
const key = filename + '-' + newline + '-' + oldline;
elements[key] = {
element: $(e),
filename: filename,
newline: newline,
oldline: oldline
};
});
for(const key in elements){
filename = elements[key]['filename'];
oldline = elements[key]['oldline']; //? elements[key]['oldline'] : '';
newline = elements[key]['newline']; //? elements[key]['newline'] : '';
const $v = $('<div class="commit-comment-box reply-comment-box">')
.append($('<input type="text" class="form-control reply-comment" placeholder="Reply..." '
+ 'data-filename="' + filename + '" '
+ 'data-newline="' + newline + '" '
+ 'data-oldline="' + oldline + '">'));
let tmp;
if (typeof oldline !== 'undefined') {
if (typeof newline !== 'undefined') {
tmp = getInlineContainer();
} else {
tmp = getInlineContainer('old');
}
tmp.children('td:first').html($v);
} else {
tmp = getInlineContainer('new');
tmp.children('td:last').html($v);
}
elements[key]['element'].closest('.not-diff').after(tmp);
} }
} }
render();
}
function renderDiffs() { 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 diffs = $('.diffText');
let i = 0; const $table = renderOneDiff($(diffs[index]), window.viewType, $('.file-hash')[index].id);
function render(){ @if(hasWritePermission) {
if (diffs[i]) { renderReplyComment($table);
const $table = renderOneDiff($(diffs[i]), window.viewType, $('.file-hash')[i].id);
@if(hasWritePermission) {
renderReplyComment($table);
}
i++;
setTimeout(render);
} else {
updateHighlighting();
}
} }
render(); $('#show-diff-' + index).hide();
} });
}); }
function changeDisplaySetting(key, value){ function changeDisplaySetting(key, value){
let url = ''; let url = '';

View File

@@ -4,7 +4,7 @@
comments: Seq[gitbucket.core.model.Comment], comments: Seq[gitbucket.core.model.Comment],
changedFileSize: Int, changedFileSize: Int,
issueLabels: List[gitbucket.core.model.Label], issueLabels: List[gitbucket.core.model.Label],
issueAsignees: List[gitbucket.core.model.IssueAssignee], issueAssignees: List[gitbucket.core.model.IssueAssignee],
collaborators: List[String], collaborators: List[String],
milestones: List[(gitbucket.core.model.Milestone, Int, Int)], milestones: List[(gitbucket.core.model.Milestone, Int, Int)],
priorities: List[gitbucket.core.model.Priority], priorities: List[gitbucket.core.model.Priority],
@@ -56,7 +56,7 @@
Some(issue), Some(issue),
comments.toList, comments.toList,
issueLabels, issueLabels,
issueAsignees, issueAssignees,
collaborators, collaborators,
milestones, milestones,
priorities, priorities,

Binary file not shown.

Before

Width:  |  Height:  |  Size: 949 B

After

Width:  |  Height:  |  Size: 85 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 691 B

After

Width:  |  Height:  |  Size: 625 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 15 KiB

After

Width:  |  Height:  |  Size: 6.9 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 7.5 KiB

After

Width:  |  Height:  |  Size: 4.8 KiB