Skip to content

Instantly share code, notes, and snippets.

@gerin98
Last active August 19, 2024 16:10
Show Gist options
  • Save gerin98/bf22ebcef8db77d7440fe557896f86ac to your computer and use it in GitHub Desktop.
Save gerin98/bf22ebcef8db77d7440fe557896f86ac to your computer and use it in GitHub Desktop.
[Blogpost] Files changed component
class FilesChangedComponent(project: Project) {
private val git: Git by lazy {
Git.open(File("${project.rootDir}/.git"))
}
private val repository: Repository by lazy {
git.repository
}
private val head: ObjectId
get() = repository.resolve(Constants.HEAD)
private val master: ObjectId
get() = repository.resolve("origin/master")
@Throws(IOException::class)
fun diff(): Set<String> {
Git(repository).use {
val diff = gitDiff(it)
return getChangedFiles(diff)
}
}
@Throws(MissingObjectException::class, IncorrectObjectTypeException::class, IOException::class, IllegalArgumentException::class)
private fun gitDiff(git: Git): MutableList<DiffEntry> {
var newTreeParser: AbstractTreeIterator
var oldTreeParser: AbstractTreeIterator
RevWalk(repository).use { rw ->
val headCommit = rw.parseCommit(head)
val masterCommit = rw.parseCommit(master)
val mergeBase = findMergeBase(rw, headCommit, masterCommit)
newTreeParser = prepareTreeParser(repository, headCommit)
oldTreeParser = prepareTreeParser(repository, mergeBase)
rw.dispose()
}
return git.diff()
.setOldTree(oldTreeParser)
.setNewTree(newTreeParser)
.setPathFilter(getSourceFilesFilter())
.call()
}
@Throws(IncorrectObjectTypeException::class, IOException::class)
private fun prepareTreeParser(repository: Repository, commit: RevCommit): AbstractTreeIterator {
val treeParser = CanonicalTreeParser()
repository.newObjectReader().use { reader ->
treeParser.reset(reader, commit.tree)
}
return treeParser
}
@Throws(MissingObjectException::class, IncorrectObjectTypeException::class, IOException::class)
private fun findMergeBase(rw: RevWalk, commitA: RevCommit, commitB: RevCommit): RevCommit {
rw.markStart(commitA)
rw.markStart(commitB)
rw.revFilter = RevFilter.MERGE_BASE
return rw.parseCommit(rw.next())
}
@Throws(IllegalArgumentException::class)
private fun getSourceFilesFilter(): TreeFilter {
val javaFilter = PathSuffixFilter.create(".java")
val kotlinFilter = PathSuffixFilter.create(".kt")
return OrTreeFilter.create(listOf(javaFilter, kotlinFilter))
}
private fun getChangedFiles(diff: List<DiffEntry>): Set<String> {
val filesChanged = mutableSetOf<String>()
diff.forEach {
when (it.changeType) {
DiffEntry.ChangeType.MODIFY -> filesChanged.add(it.oldPath)
DiffEntry.ChangeType.ADD, DiffEntry.ChangeType.RENAME, DiffEntry.ChangeType.COPY -> filesChanged.add(it.newPath)
DiffEntry.ChangeType.DELETE, null -> {}
}
}
return filesChanged
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment