diff --git a/src/main/scala/gitbucket/core/servlet/GitAuthenticationFilter.scala b/src/main/scala/gitbucket/core/servlet/GitAuthenticationFilter.scala index f542230..71d8144 100644 --- a/src/main/scala/gitbucket/core/servlet/GitAuthenticationFilter.scala +++ b/src/main/scala/gitbucket/core/servlet/GitAuthenticationFilter.scala @@ -106,6 +106,7 @@ if (isUpdating) { if (hasDeveloperRole(repository.owner, repository.name, Some(account))) { request.setAttribute(Keys.Request.UserName, account.userName) + request.setAttribute(Keys.Request.RepositoryLockKey, s"${repository.owner}/${repository.name}") true } else false } else if (repository.repository.isPrivate) { diff --git a/src/main/scala/gitbucket/core/servlet/GitRepositoryServlet.scala b/src/main/scala/gitbucket/core/servlet/GitRepositoryServlet.scala index c9595c6..2c9e43f 100644 --- a/src/main/scala/gitbucket/core/servlet/GitRepositoryServlet.scala +++ b/src/main/scala/gitbucket/core/servlet/GitRepositoryServlet.scala @@ -22,8 +22,8 @@ import org.slf4j.LoggerFactory import javax.servlet.ServletConfig import javax.servlet.http.{HttpServletRequest, HttpServletResponse} - import org.eclipse.jgit.diff.DiffEntry.ChangeType +import org.eclipse.jgit.internal.storage.file.FileRepository import org.json4s.jackson.Serialization._ /** @@ -41,7 +41,7 @@ setReceivePackFactory(new GitBucketReceivePackFactory()) val root: File = new File(Directory.RepositoryHome) - setRepositoryResolver(new GitBucketRepositoryResolver(new FileResolver[HttpServletRequest](root, true))) + setRepositoryResolver(new GitBucketRepositoryResolver) super.init(config) } @@ -55,11 +55,24 @@ res.sendRedirect(baseUrl(req) + "/" + paths.dropRight(1).last + "/" + paths.last) } else if (req.getMethod.toUpperCase == "POST" && req.getRequestURI.endsWith("/info/lfs/objects/batch")) { - serviceGitLfsBatchAPI(req, res) - + withLockRepository(req) { + serviceGitLfsBatchAPI(req, res) + } } else { // response for git client - super.service(req, res) + withLockRepository(req) { + super.service(req, res) + } + } + } + + private def withLockRepository[T](req: HttpServletRequest)(f: => T): T = { + if (req.hasAttribute(Keys.Request.RepositoryLockKey)) { + LockUtil.lock(req.getAttribute(Keys.Request.RepositoryLockKey).asInstanceOf[String]) { + f + } + } else { + f } } @@ -138,10 +151,7 @@ } } -class GitBucketRepositoryResolver(parent: FileResolver[HttpServletRequest]) - extends RepositoryResolver[HttpServletRequest] { - - private val resolver = new FileResolver[HttpServletRequest](new File(Directory.GitBucketHome), true) +class GitBucketRepositoryResolver extends RepositoryResolver[HttpServletRequest] { override def open(req: HttpServletRequest, name: String): Repository = { // Rewrite repository path if routing is marched @@ -150,10 +160,10 @@ .map { case GitRepositoryRouting(urlPattern, localPath, _) => val path = urlPattern.r.replaceFirstIn(name, localPath) - resolver.open(req, path) + new FileRepository(new File(Directory.GitBucketHome, path)) } .getOrElse { - parent.open(req, name) + new FileRepository(new File(Directory.RepositoryHome, name)) } } diff --git a/src/main/scala/gitbucket/core/util/Keys.scala b/src/main/scala/gitbucket/core/util/Keys.scala index cf3135c..cf24913 100644 --- a/src/main/scala/gitbucket/core/util/Keys.scala +++ b/src/main/scala/gitbucket/core/util/Keys.scala @@ -87,6 +87,11 @@ val UserName = "USER_NAME" /** + * Request key for the Lock key which is used during Git repository write access. + */ + val RepositoryLockKey = "REPOSITORY_LOCK_KEY" + + /** * Generate request key for the request cache. */ def Cache(key: String) = s"cache.${key}"