Max files for getting commit info becomes configurable (#2511)

This commit is contained in:
Naoki Takezoe
2020-08-15 06:05:47 +09:00
committed by GitHub
parent 29357ae170
commit 36989c38d4
9 changed files with 67 additions and 13 deletions

View File

@@ -931,7 +931,14 @@ trait RepositoryViewerControllerBase extends ControllerBase {
if (path == ".") revCommit else JGitUtil.getLastModifiedCommit(git, revCommit, path)
val commitCount = JGitUtil.getCommitCount(git, lastModifiedCommit.getName)
// get files
val files = JGitUtil.getFileList(git, revision, path, context.settings.baseUrl, commitCount)
val files = JGitUtil.getFileList(
git,
revision,
path,
context.settings.baseUrl,
commitCount,
context.settings.repositoryViewer.maxFiles
)
val parentPath = if (path == ".") Nil else path.split("/").toList
// process README.md or README.markdown
val readme = files

View File

@@ -108,7 +108,10 @@ trait SystemSettingsControllerBase extends AccountManagementControllerBase {
"timeout" -> trim(label("Timeout", long(required))),
"largeMaxFileSize" -> trim(label("Max file size for large file", long(required))),
"largeTimeout" -> trim(label("Timeout for large file", long(required)))
)(Upload.apply)
)(Upload.apply),
"repositoryViewer" -> mapping(
"maxFiles" -> trim(label("Max files", number(required)))
)(RepositoryViewerSettings.apply)
)(SystemSettings.apply).verifying { settings =>
Vector(
if (settings.ssh.enabled && settings.baseUrl.isEmpty) {

View File

@@ -42,11 +42,12 @@ trait ApiRepositoryContentsControllerBase extends ControllerBase {
case n =>
(pathStr.take(n), pathStr.drop(n + 1))
}
getFileList(git, revision, dirName).find(f => f.name.equals(fileName))
getFileList(git, revision, dirName, maxFiles = context.settings.repositoryViewer.maxFiles)
.find(_.name.equals(fileName))
}
Using.resource(Git.open(getRepositoryDir(params("owner"), params("repository")))) { git =>
val fileList = getFileList(git, refStr, path)
val fileList = getFileList(git, refStr, path, maxFiles = context.settings.repositoryViewer.maxFiles)
if (fileList.isEmpty) { // file or NotFound
getFileInfo(git, refStr, path)
.flatMap { f =>

View File

@@ -740,9 +740,10 @@ trait RepositoryService {
// Get template file from project root. When didn't find, will lookup default folder.
Using.resource(Git.open(Directory.getRepositoryDir(repository.owner, repository.name))) { git =>
choiceTemplate(JGitUtil.getFileList(git, repository.repository.defaultBranch, "."))
// maxFiles = 1 means not get commit info because the only objectId and filename are necessary here
choiceTemplate(JGitUtil.getFileList(git, repository.repository.defaultBranch, ".", maxFiles = 1))
.orElse {
choiceTemplate(JGitUtil.getFileList(git, repository.repository.defaultBranch, ".gitbucket"))
choiceTemplate(JGitUtil.getFileList(git, repository.repository.defaultBranch, ".gitbucket", maxFiles = 1))
}
.map { file =>
JGitUtil.getContentFromId(git, file.id, true).collect {

View File

@@ -82,6 +82,7 @@ trait SystemSettingsService {
props.setProperty(UploadTimeout, settings.upload.timeout.toString)
props.setProperty(UploadLargeMaxFileSize, settings.upload.largeMaxFileSize.toString)
props.setProperty(UploadLargeTimeout, settings.upload.largeTimeout.toString)
props.setProperty(RepositoryViewerMaxFiles, settings.repositoryViewer.maxFiles.toString)
Using.resource(new java.io.FileOutputStream(GitBucketConf)) { out =>
props.store(out, null)
@@ -177,6 +178,9 @@ trait SystemSettingsService {
getValue(props, UploadTimeout, 3 * 10000),
getValue(props, UploadLargeMaxFileSize, 3 * 1024 * 1024),
getValue(props, UploadLargeTimeout, 3 * 10000)
),
RepositoryViewerSettings(
getValue(props, RepositoryViewerMaxFiles, 0)
)
)
}
@@ -210,7 +214,8 @@ object SystemSettingsService {
userDefinedCss: Option[String],
showMailAddress: Boolean,
webHook: WebHook,
upload: Upload
upload: Upload,
repositoryViewer: RepositoryViewerSettings
) {
def baseUrl(request: HttpServletRequest): String =
@@ -300,6 +305,8 @@ object SystemSettingsService {
case class Upload(maxFileSize: Long, timeout: Long, largeMaxFileSize: Long, largeTimeout: Long)
case class RepositoryViewerSettings(maxFiles: Int)
val DefaultSshPort = 29418
val DefaultSmtpPort = 25
val DefaultLdapPort = 389
@@ -357,6 +364,7 @@ object SystemSettingsService {
private val UploadTimeout = "upload.timeout"
private val UploadLargeMaxFileSize = "upload.largeMaxFileSize"
private val UploadLargeTimeout = "upload.largeTimeout"
private val RepositoryViewerMaxFiles = "repository_viewer_max_files"
private def getValue[A: ClassTag](props: java.util.Properties, key: String, default: A): A = {
getConfigValue(key).getOrElse {

View File

@@ -374,6 +374,7 @@ object JGitUtil {
* @param path the directory path (optional)
* @param baseUrl the base url of GitBucket instance. This parameter is used to generate links of submodules (optional)
* @param commitCount the number of commit of this repository (optional). If this number is greater than threshold, the commit info is cached in memory.
* @param maxFiles don't fetch commit info if the number of files in the directory is bigger than this number.
* @return The list of files in the specified directory. If the number of files are greater than threshold, the returned file list won't include the commit info.
*/
def getFileList(
@@ -381,7 +382,8 @@ object JGitUtil {
revision: String,
path: String = ".",
baseUrl: Option[String] = None,
commitCount: Int = 0
commitCount: Int = 0,
maxFiles: Int = 100
): List[FileInfo] = {
Using.resource(new RevWalk(git.getRepository)) { revWalk =>
val objectId = git.getRepository.resolve(revision)
@@ -436,13 +438,13 @@ object JGitUtil {
): List[(ObjectId, FileMode, String, String, Option[String], Option[RevCommit])] = {
fileList.map {
case (id, mode, name, path, opt) =>
// Don't attempt to get the last commit if the number of files is very large.
if (fileList.size >= 100) {
if (maxFiles > 0 && fileList.size >= maxFiles) {
// Don't attempt to get the last commit if the number of files is very large.
(id, mode, name, path, opt, None)
} else if (commitCount < 10000) {
val i = git
(id, mode, name, path, opt, Some(getCommit(path)))
} else {
// Use in-memory cache if the commit count is too big.
val cached = objectCommitCache.getEntry(id)
if (cached == null) {
val commit = getCommit(path)

View File

@@ -280,6 +280,25 @@
<span class="strong">Limited</span> <span class="normal">- Show only owned repositories in sidebar.</span>
</label>
</fieldset>
<!--====================================================================-->
<!-- Repository viewer -->
<!--====================================================================-->
<hr>
<label><span class="strong">Repository viewer</span></label>
<fieldset>
<div class="form-group">
<label class="control-label col-md-2" for="repositoryViewerMaxFiles">Max files in directory</label>
<div class="col-md-10">
<input type="text" name="repositoryViewer.maxFiles" id="repositoryViewerMaxFiles" class="form-control" value="@context.settings.repositoryViewer.maxFiles"/>
<span id="error-repositoryViewerMaxFiles" class="error"></span>
<p class="muted">
If the number of files in the directory is bigger than this number, GitBucket doesn't show detailed commit info on the repository viewer
because it can make the entire system quite heavy. 0 or negative number means no limitation.
</p>
</div>
</div>
</fieldset>
<script>
$(function(){
$('#skinName').change(function(evt) {

View File

@@ -12,7 +12,7 @@ import java.sql.DriverManager
import java.io.File
import gitbucket.core.controller.Context
import gitbucket.core.service.SystemSettingsService.{RepositoryOperation, Ssh, SystemSettings}
import gitbucket.core.service.SystemSettingsService.{RepositoryOperation, RepositoryViewerSettings, Ssh, SystemSettings}
import javax.servlet.http.{HttpServletRequest, HttpSession}
import org.mockito.Mockito._
@@ -68,6 +68,9 @@ trait ServiceSpecBase {
timeout = 30 * 10000,
largeMaxFileSize = 3 * 1024 * 1024,
largeTimeout = 30 * 10000
),
repositoryViewer = RepositoryViewerSettings(
maxFiles = 0
)
)

View File

@@ -7,7 +7,14 @@ import javax.servlet.http.{HttpServletRequest, HttpSession}
import gitbucket.core.controller.Context
import gitbucket.core.model.Account
import gitbucket.core.service.RequestCache
import gitbucket.core.service.SystemSettingsService.{RepositoryOperation, Ssh, SystemSettings, Upload, WebHook}
import gitbucket.core.service.SystemSettingsService.{
RepositoryOperation,
RepositoryViewerSettings,
Ssh,
SystemSettings,
Upload,
WebHook
}
import org.mockito.Mockito._
import org.scalatest.funspec.AnyFunSpec
import play.twirl.api.Html
@@ -154,6 +161,9 @@ class AvatarImageProviderSpec extends AnyFunSpec {
timeout = 30 * 10000,
largeMaxFileSize = 3 * 1024 * 1024,
largeTimeout = 30 * 10000
),
repositoryViewer = RepositoryViewerSettings(
maxFiles = 0
)
)