Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 1 addition & 5 deletions src/main/kotlin/app/hashers/CodeLongevity.kt
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,6 @@ import app.model.Author
import app.model.Repo
import app.model.Fact
import app.utils.FileHelper
import app.utils.RepoHelper
import io.reactivex.Observable
import org.eclipse.jgit.diff.DiffFormatter
import org.eclipse.jgit.diff.DiffEntry
Expand All @@ -23,15 +22,12 @@ import org.eclipse.jgit.revwalk.RevWalk
import org.eclipse.jgit.treewalk.TreeWalk
import org.eclipse.jgit.util.io.DisabledOutputStream

import java.io.File
import java.io.FileInputStream
import java.io.FileNotFoundException
import java.io.FileOutputStream
import java.io.ObjectOutputStream
import java.io.ObjectInputStream
import java.io.Serializable
import java.nio.file.Files
import java.nio.file.Paths
import java.lang.Exception
import java.text.SimpleDateFormat
import java.util.Date
Expand Down Expand Up @@ -149,7 +145,7 @@ class CodeLongevity(private val serverRepo: Repo,
val repo: Repository = git.repository
val revWalk = RevWalk(repo)
val head: RevCommit =
try { revWalk.parseCommit(repo.resolve(RepoHelper.MASTER_BRANCH)) }
try { revWalk.parseCommit(CommitCrawler.getDefaultBranchHead(git)) }
catch(e: Exception) { throw Exception("No branch") }

val df = DiffFormatter(DisabledOutputStream.INSTANCE)
Expand Down
48 changes: 45 additions & 3 deletions src/main/kotlin/app/hashers/CommitCrawler.kt
Original file line number Diff line number Diff line change
Expand Up @@ -9,27 +9,69 @@ import app.model.DiffContent
import app.model.DiffFile
import app.model.DiffRange
import app.model.Repo
import app.utils.RepoHelper
import io.reactivex.Observable
import org.apache.commons.codec.digest.DigestUtils
import org.eclipse.jgit.api.Git
import org.eclipse.jgit.diff.DiffEntry
import org.eclipse.jgit.diff.DiffFormatter
import org.eclipse.jgit.diff.RawText
import org.eclipse.jgit.errors.MissingObjectException
import org.eclipse.jgit.lib.ObjectId
import org.eclipse.jgit.revwalk.RevCommit
import org.eclipse.jgit.revwalk.RevWalk
import org.eclipse.jgit.util.io.DisabledOutputStream
import java.util.LinkedList

object CommitCrawler {
private val MASTER_BRANCH = "refs/heads/master"
private val REMOTE_HEAD = "refs/remotes/origin/HEAD"

fun getDefaultBranchHead(git: Git): ObjectId {
val remoteHead = git.branchList()?.repository?.allRefs?.filter {
it.key.contains(REMOTE_HEAD)
}?.entries?.firstOrNull()?.value?.target?.objectId
if (remoteHead != null) {
Logger.debug { "Hashing from remote default branch" }
return remoteHead
}
val masterBranch = git.repository.resolve(MASTER_BRANCH)
if (masterBranch != null) {
Logger.debug { "Hashing from local master branch" }
return masterBranch
}
throw Exception("No remote default or local master branch found")
}

fun fetchRehashesAndEmails(git: Git):
Pair<LinkedList<String>, HashSet<String>> {
val head: RevCommit = RevWalk(git.repository)
.parseCommit(getDefaultBranchHead(git))

val revWalk = RevWalk(git.repository)
revWalk.markStart(head)

val commitsRehashes = LinkedList<String>()
val emails = hashSetOf<String>()

var commit: RevCommit? = revWalk.next()
while (commit != null) {
commitsRehashes.add(DigestUtils.sha256Hex(commit.name))
emails.add(commit.authorIdent.emailAddress)
commit.disposeBody()
commit = revWalk.next()
}
revWalk.dispose()

return Pair(commitsRehashes, emails)
}

fun getObservable(git: Git, repo: Repo,
numCommits: Int = 0): Observable<Commit> {
var curNumCommits = 0
return Observable
.create<Commit> { subscriber ->
try {
val revWalk = RevWalk(git.repository)
val commitId = git.repository.resolve(RepoHelper.MASTER_BRANCH)
val commitId = getDefaultBranchHead(git)
revWalk.markStart(revWalk.parseCommit(commitId))
for (revCommit in revWalk) {
subscriber.onNext(Commit(revCommit))
Expand Down
30 changes: 1 addition & 29 deletions src/main/kotlin/app/hashers/RepoHasher.kt
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,6 @@

package app.hashers

import app.BuildConfig
import app.Logger
import app.api.Api
import app.config.Configurator
Expand All @@ -12,13 +11,9 @@ import app.model.LocalRepo
import app.model.Repo
import app.utils.HashingException
import app.utils.RepoHelper
import org.apache.commons.codec.digest.DigestUtils
import org.eclipse.jgit.api.Git
import org.eclipse.jgit.revwalk.RevCommit
import org.eclipse.jgit.revwalk.RevWalk
import java.io.File
import java.io.IOException
import java.util.*
import kotlin.collections.HashSet

class RepoHasher(private val localRepo: LocalRepo, private val api: Api,
Expand All @@ -35,7 +30,7 @@ class RepoHasher(private val localRepo: LocalRepo, private val api: Api,
Logger.info { "Hashing of repo started" }
val git = loadGit(localRepo.path)
try {
val (rehashes, emails) = fetchRehashesAndEmails(git)
val (rehashes, emails) = CommitCrawler.fetchRehashesAndEmails(git)

localRepo.parseGitConfig(git.repository.config)
initServerRepo(rehashes.last)
Expand Down Expand Up @@ -127,29 +122,6 @@ class RepoHasher(private val localRepo: LocalRepo, private val api: Api,
initCommitRehash, localRepo))
}

private fun fetchRehashesAndEmails(git: Git):
Pair<LinkedList<String>, HashSet<String>> {
val head: RevCommit = RevWalk(git.repository)
.parseCommit(git.repository.resolve(RepoHelper.MASTER_BRANCH))

val revWalk = RevWalk(git.repository)
revWalk.markStart(head)

val commitsRehashes = LinkedList<String>()
val emails = hashSetOf<String>()

var commit: RevCommit? = revWalk.next()
while (commit != null) {
commitsRehashes.add(DigestUtils.sha256Hex(commit.name))
emails.add(commit.authorIdent.emailAddress)
commit.disposeBody()
commit = revWalk.next()
}
revWalk.dispose()

return Pair(commitsRehashes, emails)
}

private fun filterEmails(emails: HashSet<String>): HashSet<String> {
if (localRepo.hashAllContributors) {
return emails
Expand Down
45 changes: 43 additions & 2 deletions src/main/kotlin/app/ui/EmailState.kt
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,8 @@ package app.ui
import app.Logger
import app.api.Api
import app.config.Configurator
import app.hashers.CommitCrawler
import app.model.LocalRepo
import app.model.User
import app.model.UserEmail
import app.utils.UiHelper
Expand Down Expand Up @@ -39,16 +41,26 @@ class EmailState constructor(private val context: Context,
// TODO(anatoly): Add user config parsing.

// Add emails from git configs.
val reposEmails = hashMapOf<LocalRepo, HashSet<String>>()
for (repo in configurator.getLocalRepos()) {
var git: Git? = null
try {
val git = Git.open(File(repo.path))
git = Git.open(File(repo.path))
val email = git.repository
.config.getString("user", null, "email") ?: ""
if (!knownEmails.contains(email)) {
configEmails.add(email)
}
// Fetch and save emails from repo for "no-email" warning.
val (_, emails) = CommitCrawler.fetchRehashesAndEmails(git)
reposEmails.put(repo, emails)
} catch (e: Exception) {
Logger.error(e, "Error while parsing git config")
Logger.error(e, "Error while parsing repo")
} finally {
if (git != null) {
git.repository?.close()
git.close()
}
}
}

Expand All @@ -61,6 +73,35 @@ class EmailState constructor(private val context: Context,
}
}

// Show warning if no commits
val reposUserMissing = mutableListOf<LocalRepo>()
for (repo in configurator.getLocalRepos()) {
val presentedEmails = reposEmails.get(repo)
val updatedEmails = knownEmails + newEmails
if (presentedEmails != null) {
var userMissing = true
for (email in presentedEmails) {
if (updatedEmails.contains(email)) {
userMissing = false
break
}
}
if (userMissing) {
reposUserMissing.add(repo)
}
}
}
if (reposUserMissing.isNotEmpty()) {
if (reposUserMissing.size == 1) {
Logger.print("${reposUserMissing.first()} repo does not " +
"contains commits from emails you've specified")
} else {
Logger.print("Following repos do not contain commits from " +
"emails you've specified:")
reposUserMissing.forEach { Logger.print(it) }
}
}

// Ask user to enter his emails.
if (UiHelper.confirm("Do you want to specify additional emails " +
"that you use in repositories?", defaultIsYes = false)) {
Expand Down
5 changes: 2 additions & 3 deletions src/main/kotlin/app/utils/RepoHelper.kt
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@
package app.utils

import app.Logger
import app.hashers.CommitCrawler
import app.model.LocalRepo
import org.apache.commons.codec.digest.DigestUtils
import org.eclipse.jgit.api.Git
Expand All @@ -17,8 +18,6 @@ import java.nio.file.Paths
* Class for utility functions on repos.
*/
object RepoHelper {
val MASTER_BRANCH = "refs/heads/master"

fun isValidRepo(path: String): Boolean {
if (!isDirectory(path)) {
return false
Expand All @@ -30,7 +29,7 @@ object RepoHelper {
try {
git = Git.open(File(path))
repository = git.repository
commitId = repository.resolve(MASTER_BRANCH)
commitId = CommitCrawler.getDefaultBranchHead(git)
} catch (e: Exception) {
Logger.error(e, "Cannot access repository at specified path")
return false
Expand Down