diff --git a/src/main/scala/gitbucket/core/controller/RepositoryViewerController.scala b/src/main/scala/gitbucket/core/controller/RepositoryViewerController.scala index a0c4f67..3d59d71 100644 --- a/src/main/scala/gitbucket/core/controller/RepositoryViewerController.scala +++ b/src/main/scala/gitbucket/core/controller/RepositoryViewerController.scala @@ -257,7 +257,7 @@ val revCommit = JGitUtil.getRevCommitFromId(git, git.getRepository.resolve(id)) getPathObjectId(git, path, revCommit).map { objectId => - responseRawFile(git, objectId, path) + responseRawFile(git, objectId, path, repository) } getOrElse NotFound() } }) @@ -273,7 +273,7 @@ getPathObjectId(git, path, revCommit).map { objectId => if(raw){ // Download (This route is left for backword compatibility) - responseRawFile(git, objectId, path) + responseRawFile(git, objectId, path, repository) } else { html.blob(id, repository, path.split("/").toList, JGitUtil.getContentInfo(git, path, objectId), @@ -296,7 +296,8 @@ }.getOrElse(false) } - private def responseRawFile(git: Git, objectId: ObjectId, path: String): Unit = { + private def responseRawFile(git: Git, objectId: ObjectId, path: String, + repository: RepositoryService.RepositoryInfo): Unit = { JGitUtil.getObjectLoaderFromId(git, objectId){ loader => contentType = FileUtil.getMimeType(path) @@ -317,7 +318,7 @@ response.setContentLength(attrs("size").toInt) val oid = attrs("oid").split(":")(1) - using(new FileInputStream(FileUtil.getLfsFilePath(oid))){ in => + using(new FileInputStream(FileUtil.getLfsFilePath(repository.owner, repository.name, oid))){ in => IOUtils.copy(in, response.getOutputStream) } } else { diff --git a/src/main/scala/gitbucket/core/servlet/GitLfsTransferServlet.scala b/src/main/scala/gitbucket/core/servlet/GitLfsTransferServlet.scala index 426b85f..497121d 100644 --- a/src/main/scala/gitbucket/core/servlet/GitLfsTransferServlet.scala +++ b/src/main/scala/gitbucket/core/servlet/GitLfsTransferServlet.scala @@ -22,9 +22,9 @@ override protected def doGet(req: HttpServletRequest, res: HttpServletResponse): Unit = { for { - oid <- getObjectId(req, res) if checkToken(req, oid) + (owner, name, oid) <- getPathInfo(req, res) if checkToken(req, oid) } yield { - val file = new File(FileUtil.getLfsFilePath(oid)) + val file = new File(FileUtil.getLfsFilePath(owner, name, oid)) if(file.exists()){ res.setStatus(HttpStatus.SC_OK) res.setContentType("application/octet-stream") @@ -42,9 +42,9 @@ override protected def doPut(req: HttpServletRequest, res: HttpServletResponse): Unit = { for { - oid <- getObjectId(req, res) if checkToken(req, oid) + (owner, name, oid) <- getPathInfo(req, res) if checkToken(req, oid) } yield { - val file = new File(FileUtil.getLfsFilePath(oid)) + val file = new File(FileUtil.getLfsFilePath(owner, name, oid)) FileUtils.forceMkdir(file.getParentFile) using(req.getInputStream, new FileOutputStream(file)){ (in, out) => IOUtils.copy(in, out) @@ -63,15 +63,10 @@ } } - private def getObjectId(req: HttpServletRequest, rsp: HttpServletResponse): Option[String] = { - val info: String = req.getPathInfo - val length: Int = 1 + LongObjectIdStringLength - if (info.length != length) { - sendError(rsp, HttpStatus.SC_UNPROCESSABLE_ENTITY, - MessageFormat.format("Invalid pathInfo ''{0}'' does not match ''/'{'SHA-256'}'''", info)) - None - } else { - Some(info.substring(1, length)) + private def getPathInfo(req: HttpServletRequest, res: HttpServletResponse): Option[(String, String, String)] = { + req.getRequestURI.substring(1).split("/") match { + case Array(_, owner, name, oid) => Some((owner, name, oid)) + case _ => None } } diff --git a/src/main/scala/gitbucket/core/servlet/GitRepositoryServlet.scala b/src/main/scala/gitbucket/core/servlet/GitRepositoryServlet.scala index f7d232c..0e3ff4d 100644 --- a/src/main/scala/gitbucket/core/servlet/GitRepositoryServlet.scala +++ b/src/main/scala/gitbucket/core/servlet/GitRepositoryServlet.scala @@ -70,43 +70,48 @@ val settings = loadSystemSettings() settings.baseUrl match { - case None => + case None => { throw new IllegalStateException("lfs.server_url is not configured.") + } + case Some(baseUrl) => { + req.getRequestURI.substring(1).replace(".git/", "/").split("/") match { + case Array(_, owner, name, _*) => { + val timeout = System.currentTimeMillis + (60000 * 10) // 10 min. + val batchResponse = batchRequest.operation match { + case "upload" => + GitLfs.BatchUploadResponse("basic", batchRequest.objects.map { requestObject => + GitLfs.BatchResponseObject(requestObject.oid, requestObject.size, true, + GitLfs.Actions( + upload = Some(GitLfs.Action( + href = baseUrl + "/git-lfs/" + owner + "/" + name + "/" + requestObject.oid, + header = Map("Authorization" -> StringUtil.encodeBlowfish(timeout + " " + requestObject.oid)), + expires_at = new Date(timeout) + )) + ) + ) + }) + case "download" => + GitLfs.BatchUploadResponse("basic", batchRequest.objects.map { requestObject => + GitLfs.BatchResponseObject(requestObject.oid, requestObject.size, true, + GitLfs.Actions( + download = Some(GitLfs.Action( + href = baseUrl + "/git-lfs/" + owner + "/" + name + "/" + requestObject.oid, + header = Map("Authorization" -> StringUtil.encodeBlowfish(timeout + " " + requestObject.oid)), + expires_at = new Date(timeout) + )) + ) + ) + }) + } - case Some(baseUrl) => - val timeout = System.currentTimeMillis + (60000 * 10) // 10 min. - val batchResponse = batchRequest.operation match { - case "upload" => - GitLfs.BatchUploadResponse("basic", batchRequest.objects.map { requestObject => - GitLfs.BatchResponseObject(requestObject.oid, requestObject.size, true, - GitLfs.Actions( - upload = Some(GitLfs.Action( - href = baseUrl + "/git-lfs/" + requestObject.oid, - header = Map("Authorization" -> StringUtil.encodeBlowfish(timeout + " " + requestObject.oid)), - expires_at = new Date(timeout) - )) - ) - ) - }) - case "download" => - GitLfs.BatchUploadResponse("basic", batchRequest.objects.map { requestObject => - GitLfs.BatchResponseObject(requestObject.oid, requestObject.size, true, - GitLfs.Actions( - download = Some(GitLfs.Action( - href = baseUrl + "/git-lfs/" + requestObject.oid, - header = Map("Authorization" -> StringUtil.encodeBlowfish(timeout + " " + requestObject.oid)), - expires_at = new Date(timeout) - )) - ) - ) - }) + res.setContentType("application/vnd.git-lfs+json") + using(res.getWriter){ out => + out.print(write(batchResponse)) + out.flush() + } + } } - - res.setContentType("application/vnd.git-lfs+json") - using(res.getWriter){ out => - out.print(write(batchResponse)) - out.flush() - } + } } } } diff --git a/src/main/scala/gitbucket/core/util/Directory.scala b/src/main/scala/gitbucket/core/util/Directory.scala index 6713443..e73bca8 100644 --- a/src/main/scala/gitbucket/core/util/Directory.scala +++ b/src/main/scala/gitbucket/core/util/Directory.scala @@ -36,8 +36,6 @@ val TemporaryHome = s"${GitBucketHome}/tmp" - val LfsHome = s"${GitBucketHome}/lfs" - /** * Substance directory of the repository. */ @@ -51,6 +49,12 @@ new File(s"${RepositoryHome}/${owner}/${repository}/comments") /** + * Directory for files which are attached to issue. + */ + def getLfsDir(owner: String, repository: String): File = + new File(s"${RepositoryHome}/${owner}/${repository}/lfs") + + /** * Directory for uploaded files by the specified user. */ def getUserUploadDir(userName: String): File = new File(s"${GitBucketHome}/data/${userName}/files") diff --git a/src/main/scala/gitbucket/core/util/FileUtil.scala b/src/main/scala/gitbucket/core/util/FileUtil.scala index 9723ad3..9f7a322 100644 --- a/src/main/scala/gitbucket/core/util/FileUtil.scala +++ b/src/main/scala/gitbucket/core/util/FileUtil.scala @@ -63,7 +63,6 @@ "image/png", "text/plain") - def getLfsFilePath(oid: String): String = - Directory.LfsHome + "/" + oid.substring(0, 2) + "/" + oid.substring(2, 4) + "/" + oid + def getLfsFilePath(owner: String, name: String, oid: String): String = Directory.getLfsDir(owner, name) + "/" + oid }