diff --git a/src/main/scala/gitbucket/core/api/ApiCommits.scala b/src/main/scala/gitbucket/core/api/ApiCommits.scala index 22cb4e4..7a7a5ab 100644 --- a/src/main/scala/gitbucket/core/api/ApiCommits.scala +++ b/src/main/scala/gitbucket/core/api/ApiCommits.scala @@ -5,9 +5,6 @@ import gitbucket.core.util.RepositoryName import org.eclipse.jgit.diff.DiffEntry.ChangeType import ApiCommits._ -import difflib.{Delta, DiffUtils} - -import scala.collection.JavaConverters._ case class ApiCommits( url: ApiPath, @@ -65,35 +62,21 @@ def apply(repositoryName: RepositoryName, commitInfo: CommitInfo, diffs: Seq[DiffInfo], author: Account, committer: Account, commentCount: Int): ApiCommits = { - + // Is there better way to get diff status? val files = diffs.map { diff => var additions = 0 var deletions = 0 - var changes = 0 - diff.changeType match { - case ChangeType.ADD => { - additions = additions + diff.newContent.getOrElse("").replace("\r\n", "\n").split("\n").size - } - case ChangeType.MODIFY => { - val oldLines = diff.oldContent.getOrElse("").replace("\r\n", "\n").split("\n") - val newLines = diff.newContent.getOrElse("").replace("\r\n", "\n").split("\n") - val patch = DiffUtils.diff(oldLines.toList.asJava, newLines.toList.asJava) - patch.getDeltas.asScala.map { delta => - additions = additions + delta.getRevised.getLines.size - deletions = deletions + delta.getOriginal.getLines.size - } - } - case ChangeType.DELETE => { - deletions = deletions + diff.oldContent.getOrElse("").replace("\r\n", "\n").split("\n").size - } + diff.patch.getOrElse("").split("\n").foreach { line => + if(line.startsWith("+")) additions = additions + 1 + if(line.startsWith("-")) deletions = deletions + 1 } File( filename = if(diff.changeType == ChangeType.DELETE){ diff.oldPath } else { diff.newPath }, additions = additions, deletions = deletions, - changes = changes, + changes = additions + deletions, status = diff.changeType match { case ChangeType.ADD => "added" case ChangeType.MODIFY => "modified" @@ -111,7 +94,7 @@ } else { ApiPath(s"/${repositoryName.fullName}/blob/${commitInfo.id}/${diff.newPath}") }, - patch = "" // TODO + patch = diff.patch.getOrElse("") ) } diff --git a/src/main/scala/gitbucket/core/controller/ApiController.scala b/src/main/scala/gitbucket/core/controller/ApiController.scala index 384950a..6360847 100644 --- a/src/main/scala/gitbucket/core/controller/ApiController.scala +++ b/src/main/scala/gitbucket/core/controller/ApiController.scala @@ -630,7 +630,9 @@ }) getOrElse NotFound() }) - + /** + * https://developer.github.com/v3/repos/commits/#get-a-single-commit + */ get("/api/v3/repos/:owner/:repo/commits/:sha")(referrersOnly { repository => val owner = repository.owner val name = repository.name @@ -646,7 +648,7 @@ JsonFormat(ApiCommits( repositoryName = RepositoryName(repository), commitInfo = commitInfo, - diffs = JGitUtil.getDiffs(git, commitInfo.parents.head, commitInfo.id, true), + diffs = JGitUtil.getDiffs(git, commitInfo.parents.head, commitInfo.id, false, true), author = getAccount(commitInfo.authorName, commitInfo.authorEmailAddress), committer = getAccount(commitInfo.committerName, commitInfo.committerEmailAddress), commentCount = getCommitComment(repository.owner, repository.name, sha).size diff --git a/src/main/scala/gitbucket/core/controller/RepositoryViewerController.scala b/src/main/scala/gitbucket/core/controller/RepositoryViewerController.scala index df4af27..b13dde1 100644 --- a/src/main/scala/gitbucket/core/controller/RepositoryViewerController.scala +++ b/src/main/scala/gitbucket/core/controller/RepositoryViewerController.scala @@ -431,7 +431,7 @@ try { using(Git.open(getRepositoryDir(repository.owner, repository.name))) { git => defining(JGitUtil.getRevCommitFromId(git, git.getRepository.resolve(id))) { revCommit => - JGitUtil.getDiffs(git, id) match { + JGitUtil.getDiffs(git, id, false) match { case (diffs, oldCommitId) => html.commit(id, new JGitUtil.CommitInfo(revCommit), JGitUtil.getBranchesOfCommit(git, revCommit.getName), diff --git a/src/main/scala/gitbucket/core/controller/WikiController.scala b/src/main/scala/gitbucket/core/controller/WikiController.scala index d3f949f..f034602 100644 --- a/src/main/scala/gitbucket/core/controller/WikiController.scala +++ b/src/main/scala/gitbucket/core/controller/WikiController.scala @@ -76,7 +76,7 @@ val Array(from, to) = params("commitId").split("\\.\\.\\.") using(Git.open(getWikiRepositoryDir(repository.owner, repository.name))){ git => - html.compare(Some(pageName), from, to, JGitUtil.getDiffs(git, from, to, true).filter(_.newPath == pageName + ".md"), repository, + html.compare(Some(pageName), from, to, JGitUtil.getDiffs(git, from, to, true, false).filter(_.newPath == pageName + ".md"), repository, isEditable(repository), flash.get("info")) } }) @@ -85,7 +85,7 @@ val Array(from, to) = params("commitId").split("\\.\\.\\.") using(Git.open(getWikiRepositoryDir(repository.owner, repository.name))){ git => - html.compare(None, from, to, JGitUtil.getDiffs(git, from, to, true), repository, + html.compare(None, from, to, JGitUtil.getDiffs(git, from, to, true, false), repository, isEditable(repository), flash.get("info")) } }) diff --git a/src/main/scala/gitbucket/core/service/PullRequestService.scala b/src/main/scala/gitbucket/core/service/PullRequestService.scala index a368016..d8d419b 100644 --- a/src/main/scala/gitbucket/core/service/PullRequestService.scala +++ b/src/main/scala/gitbucket/core/service/PullRequestService.scala @@ -230,7 +230,7 @@ helpers.date(commit1.commitTime) == view.helpers.date(commit2.commitTime) } - val diffs = JGitUtil.getDiffs(newGit, oldId.getName, newId.getName, true) + val diffs = JGitUtil.getDiffs(newGit, oldId.getName, newId.getName, true, false) (commits, diffs) } diff --git a/src/main/scala/gitbucket/core/servlet/GitRepositoryServlet.scala b/src/main/scala/gitbucket/core/servlet/GitRepositoryServlet.scala index fd22630..6d14d2c 100644 --- a/src/main/scala/gitbucket/core/servlet/GitRepositoryServlet.scala +++ b/src/main/scala/gitbucket/core/servlet/GitRepositoryServlet.scala @@ -347,7 +347,7 @@ diffs._1.collect { case diff if diff.newPath.toLowerCase.endsWith(".md") => val action = if(diff.changeType == ChangeType.ADD) "created" else "edited" val fileName = diff.newPath - println(action + " - " + fileName + " - " + commit.id) + //println(action + " - " + fileName + " - " + commit.id) (action, fileName, commit.id) } } diff --git a/src/main/scala/gitbucket/core/util/JGitUtil.scala b/src/main/scala/gitbucket/core/util/JGitUtil.scala index 6e68bf5..802f9d1 100644 --- a/src/main/scala/gitbucket/core/util/JGitUtil.scala +++ b/src/main/scala/gitbucket/core/util/JGitUtil.scala @@ -1,5 +1,7 @@ package gitbucket.core.util +import java.io.ByteArrayOutputStream + import gitbucket.core.service.RepositoryService import org.eclipse.jgit.api.Git import Directory._ @@ -22,6 +24,7 @@ import org.cache2k.{Cache2kBuilder, CacheEntry} import org.eclipse.jgit.api.errors.{InvalidRefNameException, JGitInternalException, NoHeadException, RefAlreadyExistsException} +import org.eclipse.jgit.diff.{DiffEntry, DiffFormatter} import org.eclipse.jgit.dircache.DirCacheEntry import org.slf4j.LoggerFactory @@ -114,7 +117,8 @@ newObjectId: Option[String], oldMode: String, newMode: String, - tooLarge: Boolean + tooLarge: Boolean, + patch: Option[String] ) /** @@ -515,9 +519,10 @@ } /** - * Returns the tuple of diff of the given commit and the previous commit id. + * Returns the tuple of diff of the given commit and parent commit ids. + * DiffInfos returned from this method don't include the patch property. */ - def getDiffs(git: Git, id: String, fetchContent: Boolean = true): (List[DiffInfo], Option[String]) = { + def getDiffs(git: Git, id: String, fetchContent: Boolean): (List[DiffInfo], Option[String]) = { @scala.annotation.tailrec def getCommitLog(i: java.util.Iterator[RevCommit], logs: List[RevCommit]): List[RevCommit] = i.hasNext match { @@ -538,7 +543,7 @@ } else { commits(1) } - (getDiffs(git, oldCommit.getName, id, fetchContent), Some(oldCommit.getName)) + (getDiffs(git, oldCommit.getName, id, fetchContent, false), Some(oldCommit.getName)) } else { // initial commit @@ -551,7 +556,7 @@ buffer.append((if(!fetchContent){ DiffInfo( changeType = ChangeType.ADD, - oldPath = null, + oldPath = "", newPath = treeWalk.getPathString, oldContent = None, newContent = None, @@ -561,12 +566,13 @@ newObjectId = Option(treeWalk.getObjectId(0)).map(_.name), oldMode = treeWalk.getFileMode(0).toString, newMode = treeWalk.getFileMode(0).toString, - tooLarge = false + tooLarge = false, + patch = None ) } else { DiffInfo( changeType = ChangeType.ADD, - oldPath = null, + oldPath = "", newPath = treeWalk.getPathString, oldContent = None, newContent = JGitUtil.getContentFromId(git, treeWalk.getObjectId(0), false).filter(FileUtil.isText).map(convertFromByteArray), @@ -576,7 +582,8 @@ newObjectId = Option(treeWalk.getObjectId(0)).map(_.name), oldMode = treeWalk.getFileMode(0).toString, newMode = treeWalk.getFileMode(0).toString, - tooLarge = false + tooLarge = false, + patch = None ) })) } @@ -586,7 +593,7 @@ } } - def getDiffs(git: Git, from: String, to: String, fetchContent: Boolean): List[DiffInfo] = { + def getDiffs(git: Git, from: String, to: String, fetchContent: Boolean, makePatch: Boolean): List[DiffInfo] = { val reader = git.getRepository.newObjectReader val oldTreeIter = new CanonicalTreeParser oldTreeIter.reset(reader, git.getRepository.resolve(from + "^{tree}")) @@ -612,7 +619,8 @@ newObjectId = Option(diff.getNewId).map(_.name), oldMode = diff.getOldMode.toString, newMode = diff.getNewMode.toString, - tooLarge = true + tooLarge = true, + patch = None ) } else { val oldIsImage = FileUtil.isImage(diff.getOldPath) @@ -630,7 +638,8 @@ newObjectId = Option(diff.getNewId).map(_.name), oldMode = diff.getOldMode.toString, newMode = diff.getNewMode.toString, - tooLarge = false + tooLarge = false, + patch = (if(makePatch) Some(makePatchFromDiffEntry(git, diff)) else None) ) } else { DiffInfo( @@ -645,13 +654,23 @@ newObjectId = Option(diff.getNewId).map(_.name), oldMode = diff.getOldMode.toString, newMode = diff.getNewMode.toString, - tooLarge = false + tooLarge = false, + patch = (if(makePatch) Some(makePatchFromDiffEntry(git, diff)) else None) ) } } }.toList } + private def makePatchFromDiffEntry(git: Git, diff: DiffEntry): String = { + val out = new ByteArrayOutputStream() + using(new DiffFormatter(out)){ formatter => + formatter.setRepository(git.getRepository) + formatter.format(diff) + val patch = new String(out.toByteArray) + patch.split("\n").drop(4).mkString("\n") + } + } /** * Returns the list of branch names of the specified commit.