diff --git a/src/main/kotlin/me/msoucy/gbat/Analyze.kt b/src/main/kotlin/me/msoucy/gbat/Analyze.kt index 6721d44..eb15141 100644 --- a/src/main/kotlin/me/msoucy/gbat/Analyze.kt +++ b/src/main/kotlin/me/msoucy/gbat/Analyze.kt @@ -17,34 +17,36 @@ fun analyze( verbose : Boolean = false ) : CondensedAnalysis { val lineModel = LineModel() - val db = Database.connect("jdbc:sqlite:memory:", "org.sqlite.JDBC") - val knowledgeModel = KnowledgeModel(db, createdConstant, riskModel) - var changesProcessed = 0 + val db = Database.connect("jdbc:sqlite::memory:", "org.sqlite.JDBC") + return transaction(db) { + val knowledgeModel = KnowledgeModel(db, createdConstant, riskModel) + var changesProcessed = 0 - historyItem.authorDiffs.forEach { (author, changes) -> - changes.forEach { change -> - changesProcessed++ - if(changesProcessed % 1000 == 0 && verbose) { - System.err.println("Analyzer applied change #${changesProcessed}") + historyItem.authorDiffs.forEach { (author, changes) -> + changes.forEach { change -> + changesProcessed++ + if(changesProcessed % 1000 == 0 && verbose) { + System.err.println("Analyzer applied change #${changesProcessed}") + } + lineModel.apply(change.eventType, change.lineNum, change.lineVal ?: "") + knowledgeModel.apply(change.eventType, author, change.lineNum) } - lineModel.apply(change.eventType, change.lineNum, change.lineVal ?: "") - knowledgeModel.apply(change.eventType, author, change.lineNum) } - } - return condenseAnalysis( - historyItem.repoRoot.path, - historyItem.projectRoot.path, - historyItem.fname.path, - lineModel, - knowledgeModel, - riskModel) + condenseAnalysis( + historyItem.repoRoot, + historyItem.projectRoot, + historyItem.fname, + lineModel, + knowledgeModel, + riskModel) + } } private fun condenseAnalysis( - repoRoot : String, - projectRoot : String, - fname : String, + repoRoot : File, + projectRoot : File, + fname : File, lineModel : LineModel, knowledgeModel : KnowledgeModel, riskModel : RiskModel diff --git a/src/main/kotlin/me/msoucy/gbat/Main.kt b/src/main/kotlin/me/msoucy/gbat/Main.kt index bc99c0b..cde888a 100644 --- a/src/main/kotlin/me/msoucy/gbat/Main.kt +++ b/src/main/kotlin/me/msoucy/gbat/Main.kt @@ -136,7 +136,7 @@ fun main(args: Array) = mainBody { val riskModel = RiskModel(riskThresh, default_bus_risk, risk_file, departed) val dbFname = File(outDir, "summary.db") - val summaryDb = Database.connect(dbFname.absolutePath, "org.sqlite.JDBC") + val summaryDb = Database.connect("jdbc:sqlite:${dbFname.absolutePath}", driver="org.sqlite.JDBC") transaction(summaryDb) { exec("PRAGMA journal_mode = OFF") exec("PRAGMA synchronous = OFF") diff --git a/src/main/kotlin/me/msoucy/gbat/Repo.kt b/src/main/kotlin/me/msoucy/gbat/Repo.kt index 7d6c691..d90d6d2 100644 --- a/src/main/kotlin/me/msoucy/gbat/Repo.kt +++ b/src/main/kotlin/me/msoucy/gbat/Repo.kt @@ -27,12 +27,13 @@ class GitRepo(val projectRoot : File, val git_exe : String) { "--show-toplevel" ) val (out, _) = cmd.runCommand(projectRoot) - return File(out) + return File((out ?: "").trim()) } fun log(fname : File) : List> { val cmd = listOf( git_exe, + "--no-pager", "log", "-z", // Null byte separate log entries "-w", // Ignore all whitespace @@ -58,7 +59,7 @@ class GitRepo(val projectRoot : File, val git_exe : String) { } private fun parseAuthor(header : List) : String { - val segs = header.getOrNull(1)?.trim()?.split("\\s+")?: listOf() + val segs = header.getOrNull(1)?.trim()?.split("\\s+".toRegex())?: listOf() return segs.subList(1, segs.size - 2).joinToString(" ") } diff --git a/src/main/kotlin/me/msoucy/gbat/Util.kt b/src/main/kotlin/me/msoucy/gbat/Util.kt index abc8b34..5127b28 100644 --- a/src/main/kotlin/me/msoucy/gbat/Util.kt +++ b/src/main/kotlin/me/msoucy/gbat/Util.kt @@ -15,7 +15,7 @@ fun List.runCommand(workingDir: File): Pair { .redirectError(ProcessBuilder.Redirect.PIPE) .start() - proc.waitFor(60, TimeUnit.MINUTES) + proc.waitFor(5, TimeUnit.SECONDS) return Pair(proc.inputStream.bufferedReader().readText(), proc.errorStream.bufferedReader().readText()) } catch(e: IOException) { diff --git a/src/main/kotlin/me/msoucy/gbat/models/KnowledgeModel.kt b/src/main/kotlin/me/msoucy/gbat/models/KnowledgeModel.kt index f3d34f2..97dbd84 100644 --- a/src/main/kotlin/me/msoucy/gbat/models/KnowledgeModel.kt +++ b/src/main/kotlin/me/msoucy/gbat/models/KnowledgeModel.kt @@ -80,8 +80,8 @@ class KnowledgeModel(val db : Database, val constant : Double, val riskModel : R LineKnowledge.select { LineKnowledge.linenum eq lineNum }.map { - Pair(getKnowledgeAcct(it[LineKnowledge.knowledgeacctid]).authors, - it[LineKnowledge.knowledge]) + val acct = getKnowledgeAcct(it[LineKnowledge.knowledgeacctid]) + Pair(acct.authors, it[LineKnowledge.knowledge]) }.sortedBy { it.first.joinToString("\n") }.copyOf() @@ -95,7 +95,7 @@ class KnowledgeModel(val db : Database, val constant : Double, val riskModel : R } } - private fun getKnowledgeAcct(knowledgeAcctId : Int) = transaction(db) { + private fun getKnowledgeAcct(knowledgeAcctId : Int) : KnowledgeAcct = transaction(db) { KnowledgeAcctsTable.select { KnowledgeAcctsTable.id eq knowledgeAcctId }.map { @@ -104,7 +104,7 @@ class KnowledgeModel(val db : Database, val constant : Double, val riskModel : R it[KnowledgeAcctsTable.authors].split("\n"), it[KnowledgeAcctsTable.authors] ) - }.first() + }.firstOrNull() ?: KnowledgeAcct(-1, listOf(), "") } private fun destroyLineKnowledge(knowledgeId : Int, lineNum : Int) = transaction(db) { @@ -194,9 +194,9 @@ class KnowledgeModel(val db : Database, val constant : Double, val riskModel : R val authorStr = authors.sorted().joinToString("\n") var newId = KnowledgeAcctsTable.select { KnowledgeAcctsTable.authors eq authorStr - }.first().let { + }.map { it[KnowledgeAcctsTable.id] - } + }.firstOrNull() ?: -1 if (newId != -1) { KnowledgeAcctsTable.insert { it[KnowledgeAcctsTable.authors] = authorStr @@ -231,12 +231,14 @@ class KnowledgeModel(val db : Database, val constant : Double, val riskModel : R private fun totalLineKnowledge(linenum : Int) = transaction(db) { LineKnowledge.select { LineKnowledge.linenum eq linenum - }.first().let { + }.map { it[LineKnowledge.knowledge] - } + }.firstOrNull() ?: 0.0 } private fun createTables() = transaction(db) { + println ("-- In create tables") + SchemaUtils.dropDatabase() SchemaUtils.createMissingTablesAndColumns(AuthorsTable, KnowledgeAcctsTable, KnowledgeAuthorsTable, LineKnowledge) AuthorsTable.insertIgnore { it[id] = 1 diff --git a/src/main/kotlin/me/msoucy/gbat/models/Models.kt b/src/main/kotlin/me/msoucy/gbat/models/Models.kt index 7fdee05..5f42f82 100644 --- a/src/main/kotlin/me/msoucy/gbat/models/Models.kt +++ b/src/main/kotlin/me/msoucy/gbat/models/Models.kt @@ -1,5 +1,7 @@ package me.msoucy.gbat.models +import java.io.File + enum class ChangeType { Add, Change, Remove } @@ -34,8 +36,8 @@ data class Condensation( } class CondensedAnalysis( - var repoRoot : String = "", - var projectRoot : String = "", - var fileName : String = "", + var repoRoot : File, + var projectRoot : File, + var fileName : File, var lineSummaries : MutableList>> = mutableListOf() ) \ No newline at end of file diff --git a/src/main/kotlin/me/msoucy/gbat/models/RiskModel.kt b/src/main/kotlin/me/msoucy/gbat/models/RiskModel.kt index 679bbe7..42a1233 100644 --- a/src/main/kotlin/me/msoucy/gbat/models/RiskModel.kt +++ b/src/main/kotlin/me/msoucy/gbat/models/RiskModel.kt @@ -26,7 +26,7 @@ class RiskModel(val threshold : Double, fun isDeparted(author : String) = author.trim() in departed fun jointBusProb(authors : List) = - authors.map { this[it] }.reduce { a, b -> a * b } + (authors.map { this[it] } + 1.0).reduce { a, b -> a * b } fun jointBusProbBelowThreshold(authors : List) = jointBusProb(authors) <= threshold diff --git a/src/main/kotlin/me/msoucy/gbat/models/SummaryModel.kt b/src/main/kotlin/me/msoucy/gbat/models/SummaryModel.kt index 878d10f..0b810c3 100644 --- a/src/main/kotlin/me/msoucy/gbat/models/SummaryModel.kt +++ b/src/main/kotlin/me/msoucy/gbat/models/SummaryModel.kt @@ -97,8 +97,10 @@ class SummaryModel(val db : Database) { private val allJoined = (manyJoined leftJoin AuthorsGroupsTable) fun summarize(ca : CondensedAnalysis) { - val fname = adjustFname(File(ca.repoRoot), File(ca.projectRoot), File(ca.fileName)) - val projectId = findOrCreateProject(ca.projectRoot) + val fname = adjustFname(ca.repoRoot.absoluteFile, + ca.projectRoot.absoluteFile, + ca.fileName.absoluteFile) + val projectId = findOrCreateProject(ca.projectRoot.absolutePath) var parentDirId = 0 splitAllDirs(fname.parentFile).forEach { @@ -404,7 +406,11 @@ class SummaryModel(val db : Database) { private fun splitAllDirs(dirname : File) = dirname.toPath().iterator().asSequence().toList() private fun adjustFname(repoRoot : File, projectRoot : File, fname : File) : File { - var rootDiff = projectRoot.relativeTo(repoRoot) + val rootDiff = if(projectRoot.canonicalPath != repoRoot.canonicalPath) { + projectRoot.relativeTo(repoRoot) + } else { + repoRoot + } return if(rootDiff.toString().length != 0) { fname.relativeTo(rootDiff) } else {