mirror of
https://github.com/gitbucket/gitbucket.git
synced 2025-11-15 18:05:50 +01:00
Make patch from DiffEntry
This commit is contained in:
@@ -5,9 +5,6 @@ import gitbucket.core.util.JGitUtil.{CommitInfo, DiffInfo}
|
|||||||
import gitbucket.core.util.RepositoryName
|
import gitbucket.core.util.RepositoryName
|
||||||
import org.eclipse.jgit.diff.DiffEntry.ChangeType
|
import org.eclipse.jgit.diff.DiffEntry.ChangeType
|
||||||
import ApiCommits._
|
import ApiCommits._
|
||||||
import difflib.{Delta, DiffUtils}
|
|
||||||
|
|
||||||
import scala.collection.JavaConverters._
|
|
||||||
|
|
||||||
case class ApiCommits(
|
case class ApiCommits(
|
||||||
url: ApiPath,
|
url: ApiPath,
|
||||||
@@ -65,35 +62,21 @@ object ApiCommits {
|
|||||||
|
|
||||||
def apply(repositoryName: RepositoryName, commitInfo: CommitInfo, diffs: Seq[DiffInfo], author: Account, committer: Account,
|
def apply(repositoryName: RepositoryName, commitInfo: CommitInfo, diffs: Seq[DiffInfo], author: Account, committer: Account,
|
||||||
commentCount: Int): ApiCommits = {
|
commentCount: Int): ApiCommits = {
|
||||||
|
// Is there better way to get diff status?
|
||||||
val files = diffs.map { diff =>
|
val files = diffs.map { diff =>
|
||||||
var additions = 0
|
var additions = 0
|
||||||
var deletions = 0
|
var deletions = 0
|
||||||
var changes = 0
|
|
||||||
|
|
||||||
diff.changeType match {
|
diff.patch.getOrElse("").split("\n").foreach { line =>
|
||||||
case ChangeType.ADD => {
|
if(line.startsWith("+")) additions = additions + 1
|
||||||
additions = additions + diff.newContent.getOrElse("").replace("\r\n", "\n").split("\n").size
|
if(line.startsWith("-")) deletions = deletions + 1
|
||||||
}
|
|
||||||
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
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
File(
|
File(
|
||||||
filename = if(diff.changeType == ChangeType.DELETE){ diff.oldPath } else { diff.newPath },
|
filename = if(diff.changeType == ChangeType.DELETE){ diff.oldPath } else { diff.newPath },
|
||||||
additions = additions,
|
additions = additions,
|
||||||
deletions = deletions,
|
deletions = deletions,
|
||||||
changes = changes,
|
changes = additions + deletions,
|
||||||
status = diff.changeType match {
|
status = diff.changeType match {
|
||||||
case ChangeType.ADD => "added"
|
case ChangeType.ADD => "added"
|
||||||
case ChangeType.MODIFY => "modified"
|
case ChangeType.MODIFY => "modified"
|
||||||
@@ -111,7 +94,7 @@ object ApiCommits {
|
|||||||
} else {
|
} else {
|
||||||
ApiPath(s"/${repositoryName.fullName}/blob/${commitInfo.id}/${diff.newPath}")
|
ApiPath(s"/${repositoryName.fullName}/blob/${commitInfo.id}/${diff.newPath}")
|
||||||
},
|
},
|
||||||
patch = "" // TODO
|
patch = diff.patch.getOrElse("")
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -630,7 +630,9 @@ trait ApiControllerBase extends ControllerBase {
|
|||||||
}) getOrElse NotFound()
|
}) getOrElse NotFound()
|
||||||
})
|
})
|
||||||
|
|
||||||
|
/**
|
||||||
|
* https://developer.github.com/v3/repos/commits/#get-a-single-commit
|
||||||
|
*/
|
||||||
get("/api/v3/repos/:owner/:repo/commits/:sha")(referrersOnly { repository =>
|
get("/api/v3/repos/:owner/:repo/commits/:sha")(referrersOnly { repository =>
|
||||||
val owner = repository.owner
|
val owner = repository.owner
|
||||||
val name = repository.name
|
val name = repository.name
|
||||||
@@ -646,7 +648,7 @@ trait ApiControllerBase extends ControllerBase {
|
|||||||
JsonFormat(ApiCommits(
|
JsonFormat(ApiCommits(
|
||||||
repositoryName = RepositoryName(repository),
|
repositoryName = RepositoryName(repository),
|
||||||
commitInfo = commitInfo,
|
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),
|
author = getAccount(commitInfo.authorName, commitInfo.authorEmailAddress),
|
||||||
committer = getAccount(commitInfo.committerName, commitInfo.committerEmailAddress),
|
committer = getAccount(commitInfo.committerName, commitInfo.committerEmailAddress),
|
||||||
commentCount = getCommitComment(repository.owner, repository.name, sha).size
|
commentCount = getCommitComment(repository.owner, repository.name, sha).size
|
||||||
|
|||||||
@@ -431,7 +431,7 @@ trait RepositoryViewerControllerBase extends ControllerBase {
|
|||||||
try {
|
try {
|
||||||
using(Git.open(getRepositoryDir(repository.owner, repository.name))) { git =>
|
using(Git.open(getRepositoryDir(repository.owner, repository.name))) { git =>
|
||||||
defining(JGitUtil.getRevCommitFromId(git, git.getRepository.resolve(id))) { revCommit =>
|
defining(JGitUtil.getRevCommitFromId(git, git.getRepository.resolve(id))) { revCommit =>
|
||||||
JGitUtil.getDiffs(git, id) match {
|
JGitUtil.getDiffs(git, id, false) match {
|
||||||
case (diffs, oldCommitId) =>
|
case (diffs, oldCommitId) =>
|
||||||
html.commit(id, new JGitUtil.CommitInfo(revCommit),
|
html.commit(id, new JGitUtil.CommitInfo(revCommit),
|
||||||
JGitUtil.getBranchesOfCommit(git, revCommit.getName),
|
JGitUtil.getBranchesOfCommit(git, revCommit.getName),
|
||||||
|
|||||||
@@ -76,7 +76,7 @@ trait WikiControllerBase extends ControllerBase {
|
|||||||
val Array(from, to) = params("commitId").split("\\.\\.\\.")
|
val Array(from, to) = params("commitId").split("\\.\\.\\.")
|
||||||
|
|
||||||
using(Git.open(getWikiRepositoryDir(repository.owner, repository.name))){ git =>
|
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"))
|
isEditable(repository), flash.get("info"))
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
@@ -85,7 +85,7 @@ trait WikiControllerBase extends ControllerBase {
|
|||||||
val Array(from, to) = params("commitId").split("\\.\\.\\.")
|
val Array(from, to) = params("commitId").split("\\.\\.\\.")
|
||||||
|
|
||||||
using(Git.open(getWikiRepositoryDir(repository.owner, repository.name))){ git =>
|
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"))
|
isEditable(repository), flash.get("info"))
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
|||||||
@@ -230,7 +230,7 @@ trait PullRequestService { self: IssuesService with CommitsService =>
|
|||||||
helpers.date(commit1.commitTime) == view.helpers.date(commit2.commitTime)
|
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)
|
(commits, diffs)
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -347,7 +347,7 @@ class WikiCommitHook(owner: String, repository: String, pusher: String, baseUrl:
|
|||||||
diffs._1.collect { case diff if diff.newPath.toLowerCase.endsWith(".md") =>
|
diffs._1.collect { case diff if diff.newPath.toLowerCase.endsWith(".md") =>
|
||||||
val action = if(diff.changeType == ChangeType.ADD) "created" else "edited"
|
val action = if(diff.changeType == ChangeType.ADD) "created" else "edited"
|
||||||
val fileName = diff.newPath
|
val fileName = diff.newPath
|
||||||
println(action + " - " + fileName + " - " + commit.id)
|
//println(action + " - " + fileName + " - " + commit.id)
|
||||||
(action, fileName, commit.id)
|
(action, fileName, commit.id)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,5 +1,7 @@
|
|||||||
package gitbucket.core.util
|
package gitbucket.core.util
|
||||||
|
|
||||||
|
import java.io.ByteArrayOutputStream
|
||||||
|
|
||||||
import gitbucket.core.service.RepositoryService
|
import gitbucket.core.service.RepositoryService
|
||||||
import org.eclipse.jgit.api.Git
|
import org.eclipse.jgit.api.Git
|
||||||
import Directory._
|
import Directory._
|
||||||
@@ -22,6 +24,7 @@ import java.util.function.Consumer
|
|||||||
|
|
||||||
import org.cache2k.{Cache2kBuilder, CacheEntry}
|
import org.cache2k.{Cache2kBuilder, CacheEntry}
|
||||||
import org.eclipse.jgit.api.errors.{InvalidRefNameException, JGitInternalException, NoHeadException, RefAlreadyExistsException}
|
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.eclipse.jgit.dircache.DirCacheEntry
|
||||||
import org.slf4j.LoggerFactory
|
import org.slf4j.LoggerFactory
|
||||||
|
|
||||||
@@ -114,7 +117,8 @@ object JGitUtil {
|
|||||||
newObjectId: Option[String],
|
newObjectId: Option[String],
|
||||||
oldMode: String,
|
oldMode: String,
|
||||||
newMode: String,
|
newMode: String,
|
||||||
tooLarge: Boolean
|
tooLarge: Boolean,
|
||||||
|
patch: Option[String]
|
||||||
)
|
)
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -515,9 +519,10 @@ object JGitUtil {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 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
|
@scala.annotation.tailrec
|
||||||
def getCommitLog(i: java.util.Iterator[RevCommit], logs: List[RevCommit]): List[RevCommit] =
|
def getCommitLog(i: java.util.Iterator[RevCommit], logs: List[RevCommit]): List[RevCommit] =
|
||||||
i.hasNext match {
|
i.hasNext match {
|
||||||
@@ -538,7 +543,7 @@ object JGitUtil {
|
|||||||
} else {
|
} else {
|
||||||
commits(1)
|
commits(1)
|
||||||
}
|
}
|
||||||
(getDiffs(git, oldCommit.getName, id, fetchContent), Some(oldCommit.getName))
|
(getDiffs(git, oldCommit.getName, id, fetchContent, false), Some(oldCommit.getName))
|
||||||
|
|
||||||
} else {
|
} else {
|
||||||
// initial commit
|
// initial commit
|
||||||
@@ -551,7 +556,7 @@ object JGitUtil {
|
|||||||
buffer.append((if(!fetchContent){
|
buffer.append((if(!fetchContent){
|
||||||
DiffInfo(
|
DiffInfo(
|
||||||
changeType = ChangeType.ADD,
|
changeType = ChangeType.ADD,
|
||||||
oldPath = null,
|
oldPath = "",
|
||||||
newPath = treeWalk.getPathString,
|
newPath = treeWalk.getPathString,
|
||||||
oldContent = None,
|
oldContent = None,
|
||||||
newContent = None,
|
newContent = None,
|
||||||
@@ -561,12 +566,13 @@ object JGitUtil {
|
|||||||
newObjectId = Option(treeWalk.getObjectId(0)).map(_.name),
|
newObjectId = Option(treeWalk.getObjectId(0)).map(_.name),
|
||||||
oldMode = treeWalk.getFileMode(0).toString,
|
oldMode = treeWalk.getFileMode(0).toString,
|
||||||
newMode = treeWalk.getFileMode(0).toString,
|
newMode = treeWalk.getFileMode(0).toString,
|
||||||
tooLarge = false
|
tooLarge = false,
|
||||||
|
patch = None
|
||||||
)
|
)
|
||||||
} else {
|
} else {
|
||||||
DiffInfo(
|
DiffInfo(
|
||||||
changeType = ChangeType.ADD,
|
changeType = ChangeType.ADD,
|
||||||
oldPath = null,
|
oldPath = "",
|
||||||
newPath = treeWalk.getPathString,
|
newPath = treeWalk.getPathString,
|
||||||
oldContent = None,
|
oldContent = None,
|
||||||
newContent = JGitUtil.getContentFromId(git, treeWalk.getObjectId(0), false).filter(FileUtil.isText).map(convertFromByteArray),
|
newContent = JGitUtil.getContentFromId(git, treeWalk.getObjectId(0), false).filter(FileUtil.isText).map(convertFromByteArray),
|
||||||
@@ -576,7 +582,8 @@ object JGitUtil {
|
|||||||
newObjectId = Option(treeWalk.getObjectId(0)).map(_.name),
|
newObjectId = Option(treeWalk.getObjectId(0)).map(_.name),
|
||||||
oldMode = treeWalk.getFileMode(0).toString,
|
oldMode = treeWalk.getFileMode(0).toString,
|
||||||
newMode = treeWalk.getFileMode(0).toString,
|
newMode = treeWalk.getFileMode(0).toString,
|
||||||
tooLarge = false
|
tooLarge = false,
|
||||||
|
patch = None
|
||||||
)
|
)
|
||||||
}))
|
}))
|
||||||
}
|
}
|
||||||
@@ -586,7 +593,7 @@ object JGitUtil {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
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 reader = git.getRepository.newObjectReader
|
||||||
val oldTreeIter = new CanonicalTreeParser
|
val oldTreeIter = new CanonicalTreeParser
|
||||||
oldTreeIter.reset(reader, git.getRepository.resolve(from + "^{tree}"))
|
oldTreeIter.reset(reader, git.getRepository.resolve(from + "^{tree}"))
|
||||||
@@ -612,7 +619,8 @@ object JGitUtil {
|
|||||||
newObjectId = Option(diff.getNewId).map(_.name),
|
newObjectId = Option(diff.getNewId).map(_.name),
|
||||||
oldMode = diff.getOldMode.toString,
|
oldMode = diff.getOldMode.toString,
|
||||||
newMode = diff.getNewMode.toString,
|
newMode = diff.getNewMode.toString,
|
||||||
tooLarge = true
|
tooLarge = true,
|
||||||
|
patch = None
|
||||||
)
|
)
|
||||||
} else {
|
} else {
|
||||||
val oldIsImage = FileUtil.isImage(diff.getOldPath)
|
val oldIsImage = FileUtil.isImage(diff.getOldPath)
|
||||||
@@ -630,7 +638,8 @@ object JGitUtil {
|
|||||||
newObjectId = Option(diff.getNewId).map(_.name),
|
newObjectId = Option(diff.getNewId).map(_.name),
|
||||||
oldMode = diff.getOldMode.toString,
|
oldMode = diff.getOldMode.toString,
|
||||||
newMode = diff.getNewMode.toString,
|
newMode = diff.getNewMode.toString,
|
||||||
tooLarge = false
|
tooLarge = false,
|
||||||
|
patch = (if(makePatch) Some(makePatchFromDiffEntry(git, diff)) else None)
|
||||||
)
|
)
|
||||||
} else {
|
} else {
|
||||||
DiffInfo(
|
DiffInfo(
|
||||||
@@ -645,13 +654,23 @@ object JGitUtil {
|
|||||||
newObjectId = Option(diff.getNewId).map(_.name),
|
newObjectId = Option(diff.getNewId).map(_.name),
|
||||||
oldMode = diff.getOldMode.toString,
|
oldMode = diff.getOldMode.toString,
|
||||||
newMode = diff.getNewMode.toString,
|
newMode = diff.getNewMode.toString,
|
||||||
tooLarge = false
|
tooLarge = false,
|
||||||
|
patch = (if(makePatch) Some(makePatchFromDiffEntry(git, diff)) else None)
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}.toList
|
}.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.
|
* Returns the list of branch names of the specified commit.
|
||||||
|
|||||||
Reference in New Issue
Block a user