diff --git a/src/main/scala/gitbucket/core/controller/RepositoryViewerController.scala b/src/main/scala/gitbucket/core/controller/RepositoryViewerController.scala index da2b5ba..2c75be6 100644 --- a/src/main/scala/gitbucket/core/controller/RepositoryViewerController.scala +++ b/src/main/scala/gitbucket/core/controller/RepositoryViewerController.scala @@ -931,7 +931,14 @@ 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 diff --git a/src/main/scala/gitbucket/core/controller/SystemSettingsController.scala b/src/main/scala/gitbucket/core/controller/SystemSettingsController.scala index a6e8561..ef0b723 100644 --- a/src/main/scala/gitbucket/core/controller/SystemSettingsController.scala +++ b/src/main/scala/gitbucket/core/controller/SystemSettingsController.scala @@ -108,7 +108,10 @@ "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) { diff --git a/src/main/scala/gitbucket/core/controller/api/ApiRepositoryContentsControllerBase.scala b/src/main/scala/gitbucket/core/controller/api/ApiRepositoryContentsControllerBase.scala index 6021793..98dc8b6 100644 --- a/src/main/scala/gitbucket/core/controller/api/ApiRepositoryContentsControllerBase.scala +++ b/src/main/scala/gitbucket/core/controller/api/ApiRepositoryContentsControllerBase.scala @@ -42,11 +42,12 @@ 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 => diff --git a/src/main/scala/gitbucket/core/service/RepositoryService.scala b/src/main/scala/gitbucket/core/service/RepositoryService.scala index 8cd61ea..0e18f95 100644 --- a/src/main/scala/gitbucket/core/service/RepositoryService.scala +++ b/src/main/scala/gitbucket/core/service/RepositoryService.scala @@ -740,9 +740,10 @@ // 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 { diff --git a/src/main/scala/gitbucket/core/service/SystemSettingsService.scala b/src/main/scala/gitbucket/core/service/SystemSettingsService.scala index 95577d3..5e7b0dc 100644 --- a/src/main/scala/gitbucket/core/service/SystemSettingsService.scala +++ b/src/main/scala/gitbucket/core/service/SystemSettingsService.scala @@ -82,6 +82,7 @@ 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 @@ 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 @@ userDefinedCss: Option[String], showMailAddress: Boolean, webHook: WebHook, - upload: Upload + upload: Upload, + repositoryViewer: RepositoryViewerSettings ) { def baseUrl(request: HttpServletRequest): String = @@ -300,6 +305,8 @@ 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 @@ 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 { diff --git a/src/main/scala/gitbucket/core/util/JGitUtil.scala b/src/main/scala/gitbucket/core/util/JGitUtil.scala index fc1663e..e6836c8 100644 --- a/src/main/scala/gitbucket/core/util/JGitUtil.scala +++ b/src/main/scala/gitbucket/core/util/JGitUtil.scala @@ -374,6 +374,7 @@ * @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 @@ 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 @@ ): 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) diff --git a/src/main/twirl/gitbucket/core/admin/settings_system.scala.html b/src/main/twirl/gitbucket/core/admin/settings_system.scala.html index b072362..f728a0c 100644 --- a/src/main/twirl/gitbucket/core/admin/settings_system.scala.html +++ b/src/main/twirl/gitbucket/core/admin/settings_system.scala.html @@ -280,6 +280,25 @@ Limited - Show only owned repositories in sidebar. + + + +