GetVersionedFiles.kt
package com.sebastmar.module.report.internal.domain
import com.sebastmar.module.report.info.VersionedFile
import com.sebastmar.module.report.info.VersionedFile.Status
import com.sebastmar.module.report.internal.ShowLineIndicators
import com.sebastmar.module.report.internal.system.SystemCommandLine
import com.sebastmar.module.report.internal.system.SystemWrapper
import java.nio.file.Path
import kotlin.io.path.pathString
/**
* Maps a list of file paths to a list of [VersionedFile] objects.
*/
internal interface GetVersionedFiles {
operator fun invoke(
files: List<String>,
status: Status,
): List<VersionedFile>
}
internal class GetVersionedFilesImpl(
private val systemCommandLine: SystemCommandLine,
private val getProjectRoot: GetProjectRoot,
private val showLineIndicators: ShowLineIndicators,
private val systemWrapper: SystemWrapper,
) : GetVersionedFiles {
private val regex by lazy {
"""1 file changed, (?:(\d+)\s+insertions\(\+\))?(?:,\s*)?(?:(\d+)\s+deletions\(-\))?""".toRegex()
}
private val projectRoot: Path by lazy { getProjectRoot() }
override operator fun invoke(
files: List<String>,
status: Status,
): List<VersionedFile> {
return files.map { filePath ->
val fullPath = filePath.removePrefix("'a/' --dst-prefix='b/'")
val fileName = fullPath.substringAfterLast("/")
var insertions: Int? = null
var deletions: Int? = null
if (showLineIndicators.value) {
val diffShortStat = runDiffStat(fullPath)
val diffResult = regex.find(diffShortStat)
if (diffResult != null) {
insertions = diffResult.groups[1]?.value?.toIntOrNull()
deletions = diffResult.groups[2]?.value?.toIntOrNull()
}
}
VersionedFile(
name = fileName,
fullPath = fullPath,
insertions = insertions,
deletions = deletions,
status = status,
)
}
}
/**
* Executes a git diff command to get the short statistics for a specific file.
*
* The command compares the current state of the file against the target branch,
* returning information about insertions and deletions.
*
* @param fullPath The path to the file relative to the project root.
* @return A string containing the git diff shortstat output, which includes the number
* of insertions and deletions in the format:
* "1 file changed, X insertions(+), Y deletions(-)"
*/
private fun runDiffStat(fullPath: String): String {
val targetSHA = systemWrapper.targetSHA()
return systemCommandLine.exec("git diff --shortstat $targetSHA -- ${projectRoot.pathString}/$fullPath")
}
}