Started arch refactor
This commit is contained in:
parent
cbcb13d730
commit
270951fe66
@ -1,61 +0,0 @@
|
||||
package app.git
|
||||
|
||||
import app.models.AuthorInfo
|
||||
import kotlinx.coroutines.Dispatchers
|
||||
import kotlinx.coroutines.withContext
|
||||
import org.eclipse.jgit.api.Git
|
||||
import org.eclipse.jgit.storage.file.FileBasedConfig
|
||||
import javax.inject.Inject
|
||||
|
||||
class AuthorManager @Inject constructor() {
|
||||
suspend fun loadAuthor(git: Git) = withContext(Dispatchers.IO) {
|
||||
val config = git.repository.config
|
||||
val globalConfig = git.repository.config.baseConfig
|
||||
|
||||
val repoConfig = FileBasedConfig((config as FileBasedConfig).file, git.repository.fs)
|
||||
repoConfig.load()
|
||||
|
||||
val globalName = globalConfig.getString("user", null, "name")
|
||||
val globalEmail = globalConfig.getString("user", null, "email")
|
||||
|
||||
val name = repoConfig.getString("user", null, "name")
|
||||
val email = repoConfig.getString("user", null, "email")
|
||||
|
||||
return@withContext AuthorInfo(
|
||||
globalName,
|
||||
globalEmail,
|
||||
name,
|
||||
email,
|
||||
)
|
||||
}
|
||||
|
||||
suspend fun saveAuthorInfo(git: Git, newAuthorInfo: AuthorInfo) = withContext(Dispatchers.IO) {
|
||||
val config = git.repository.config
|
||||
val globalConfig = git.repository.config.baseConfig
|
||||
val repoConfig = FileBasedConfig((config as FileBasedConfig).file, git.repository.fs)
|
||||
repoConfig.load()
|
||||
|
||||
if (globalConfig is FileBasedConfig) {
|
||||
globalConfig.setStringProperty("user", null, "name", newAuthorInfo.globalName)
|
||||
globalConfig.setStringProperty("user", null, "email", newAuthorInfo.globalEmail)
|
||||
globalConfig.save()
|
||||
}
|
||||
|
||||
config.setStringProperty("user", null, "name", newAuthorInfo.name)
|
||||
config.setStringProperty("user", null, "email", newAuthorInfo.email)
|
||||
config.save()
|
||||
}
|
||||
|
||||
private fun FileBasedConfig.setStringProperty(
|
||||
section: String,
|
||||
subsection: String?,
|
||||
name: String,
|
||||
value: String?,
|
||||
) {
|
||||
if (value == null) {
|
||||
unset(section, subsection, name)
|
||||
} else {
|
||||
setString(section, subsection, name, value)
|
||||
}
|
||||
}
|
||||
}
|
@ -1,95 +0,0 @@
|
||||
package app.git
|
||||
|
||||
import app.extensions.isBranch
|
||||
import app.extensions.simpleName
|
||||
import kotlinx.coroutines.Dispatchers
|
||||
import kotlinx.coroutines.withContext
|
||||
import org.eclipse.jgit.api.CreateBranchCommand
|
||||
import org.eclipse.jgit.api.Git
|
||||
import org.eclipse.jgit.api.ListBranchCommand
|
||||
import org.eclipse.jgit.lib.Ref
|
||||
import org.eclipse.jgit.revwalk.RevCommit
|
||||
import javax.inject.Inject
|
||||
|
||||
class BranchesManager @Inject constructor() {
|
||||
/**
|
||||
* Returns the current branch in [Ref]. If the repository is new, the current branch will be null.
|
||||
*/
|
||||
suspend fun currentBranchRef(git: Git): Ref? {
|
||||
val branchList = getBranches(git)
|
||||
val branchName = git
|
||||
.repository
|
||||
.fullBranch
|
||||
|
||||
var branchFound = branchList.firstOrNull {
|
||||
it.name == branchName
|
||||
}
|
||||
|
||||
if (branchFound == null) {
|
||||
branchFound = branchList.firstOrNull {
|
||||
it.objectId.name == branchName // Try to get the HEAD
|
||||
}
|
||||
}
|
||||
|
||||
return branchFound
|
||||
}
|
||||
|
||||
suspend fun getBranches(git: Git) = withContext(Dispatchers.IO) {
|
||||
return@withContext git
|
||||
.branchList()
|
||||
.call()
|
||||
}
|
||||
|
||||
suspend fun createBranch(git: Git, branchName: String) = withContext(Dispatchers.IO) {
|
||||
git
|
||||
.checkout()
|
||||
.setCreateBranch(true)
|
||||
.setName(branchName)
|
||||
.call()
|
||||
}
|
||||
|
||||
suspend fun createBranchOnCommit(git: Git, branch: String, revCommit: RevCommit) = withContext(Dispatchers.IO) {
|
||||
git
|
||||
.checkout()
|
||||
.setCreateBranch(true)
|
||||
.setName(branch)
|
||||
.setStartPoint(revCommit)
|
||||
.call()
|
||||
}
|
||||
|
||||
suspend fun deleteBranch(git: Git, branch: Ref) = withContext(Dispatchers.IO) {
|
||||
git
|
||||
.branchDelete()
|
||||
.setBranchNames(branch.name)
|
||||
.setForce(true) // TODO Should it be forced?
|
||||
.call()
|
||||
}
|
||||
|
||||
suspend fun deleteLocallyRemoteBranches(git: Git, branches: List<String>) = withContext(Dispatchers.IO) {
|
||||
git
|
||||
.branchDelete()
|
||||
.setBranchNames(*branches.toTypedArray())
|
||||
.setForce(true)
|
||||
.call()
|
||||
}
|
||||
|
||||
suspend fun remoteBranches(git: Git) = withContext(Dispatchers.IO) {
|
||||
git
|
||||
.branchList()
|
||||
.setListMode(ListBranchCommand.ListMode.REMOTE)
|
||||
.call()
|
||||
}
|
||||
|
||||
suspend fun checkoutRef(git: Git, ref: Ref) = withContext(Dispatchers.IO) {
|
||||
git.checkout().apply {
|
||||
setName(ref.name)
|
||||
if (ref.isBranch && ref.name.startsWith("refs/remotes/")) {
|
||||
setCreateBranch(true)
|
||||
setName(ref.simpleName)
|
||||
setStartPoint(ref.objectId.name)
|
||||
setUpstreamMode(CreateBranchCommand.SetupUpstreamMode.TRACK)
|
||||
}
|
||||
call()
|
||||
}
|
||||
}
|
||||
}
|
34
src/main/kotlin/app/git/CloneStatus.kt
Normal file
34
src/main/kotlin/app/git/CloneStatus.kt
Normal file
@ -0,0 +1,34 @@
|
||||
package app.git
|
||||
|
||||
import org.eclipse.jgit.transport.RemoteRefUpdate
|
||||
import java.io.File
|
||||
|
||||
sealed class CloneStatus {
|
||||
object None : CloneStatus()
|
||||
data class Cloning(val taskName: String, val progress: Int, val total: Int) : CloneStatus()
|
||||
object Cancelling : CloneStatus()
|
||||
data class Fail(val reason: String) : CloneStatus()
|
||||
data class Completed(val repoDir: File) : CloneStatus()
|
||||
}
|
||||
|
||||
val RemoteRefUpdate.Status.isRejected: Boolean
|
||||
get() {
|
||||
return this == RemoteRefUpdate.Status.REJECTED_NONFASTFORWARD ||
|
||||
this == RemoteRefUpdate.Status.REJECTED_NODELETE ||
|
||||
this == RemoteRefUpdate.Status.REJECTED_REMOTE_CHANGED ||
|
||||
this == RemoteRefUpdate.Status.REJECTED_OTHER_REASON
|
||||
}
|
||||
|
||||
val RemoteRefUpdate.statusMessage: String
|
||||
get() {
|
||||
return when (this.status) {
|
||||
RemoteRefUpdate.Status.REJECTED_NONFASTFORWARD -> "Failed to push some refs to ${this.remoteName}. " +
|
||||
"Updates were rejected because the remote contains work that you do not have locally. Pulling changes from remote may help."
|
||||
|
||||
RemoteRefUpdate.Status.REJECTED_NODELETE -> "Could not delete ref because the remote doesn't support deleting refs."
|
||||
RemoteRefUpdate.Status.REJECTED_REMOTE_CHANGED -> "Ref rejected, old object id in remote has changed."
|
||||
RemoteRefUpdate.Status.REJECTED_OTHER_REASON -> this.message ?: "Push rejected for unknown reasons."
|
||||
else -> ""
|
||||
}
|
||||
|
||||
}
|
@ -5,6 +5,7 @@ import app.di.RawFileManagerFactory
|
||||
import app.exceptions.MissingDiffEntryException
|
||||
import app.extensions.fullData
|
||||
import app.extensions.isMerging
|
||||
import app.git.branches.GetCurrentBranchUseCase
|
||||
import app.git.diff.DiffResult
|
||||
import kotlinx.coroutines.Dispatchers
|
||||
import kotlinx.coroutines.withContext
|
||||
@ -28,7 +29,7 @@ import javax.inject.Inject
|
||||
class DiffManager @Inject constructor(
|
||||
private val rawFileManagerFactory: RawFileManagerFactory,
|
||||
private val hunkDiffGeneratorFactory: HunkDiffGeneratorFactory,
|
||||
private val branchesManager: BranchesManager,
|
||||
private val getCurrentBranchUseCase: GetCurrentBranchUseCase,
|
||||
private val repositoryManager: RepositoryManager,
|
||||
) {
|
||||
suspend fun diffFormat(git: Git, diffEntryType: DiffEntryType): DiffResult = withContext(Dispatchers.IO) {
|
||||
@ -57,7 +58,7 @@ class DiffManager @Inject constructor(
|
||||
.setCached(cached).apply {
|
||||
val repositoryState = repositoryManager.getRepositoryState(git)
|
||||
if (
|
||||
branchesManager.currentBranchRef(git) == null &&
|
||||
getCurrentBranchUseCase(git) == null &&
|
||||
!repositoryState.isMerging &&
|
||||
!repositoryState.isRebasing &&
|
||||
cached
|
||||
|
@ -1,6 +1,7 @@
|
||||
package app.git
|
||||
|
||||
import app.exceptions.UncommitedChangesDetectedException
|
||||
import app.git.branches.GetCurrentBranchUseCase
|
||||
import kotlinx.coroutines.Dispatchers
|
||||
import kotlinx.coroutines.withContext
|
||||
import org.eclipse.jgit.api.Git
|
||||
@ -16,7 +17,7 @@ import org.eclipse.jgit.revwalk.RevWalk
|
||||
import javax.inject.Inject
|
||||
|
||||
class RebaseManager @Inject constructor(
|
||||
private val branchesManager: BranchesManager,
|
||||
private val getCurrentBranchUseCase: GetCurrentBranchUseCase,
|
||||
) {
|
||||
|
||||
suspend fun rebaseBranch(git: Git, ref: Ref) = withContext(Dispatchers.IO) {
|
||||
@ -127,7 +128,7 @@ class RebaseManager @Inject constructor(
|
||||
}
|
||||
|
||||
private suspend fun markCurrentBranchAsStart(revWalk: RevWalk, git: Git) {
|
||||
val currentBranch = branchesManager.currentBranchRef(git) ?: throw Exception("Null current branch")
|
||||
val currentBranch = getCurrentBranchUseCase(git) ?: throw Exception("Null current branch")
|
||||
val refTarget = revWalk.parseAny(currentBranch.leaf.objectId)
|
||||
|
||||
if (refTarget is RevCommit)
|
||||
|
@ -1,297 +0,0 @@
|
||||
package app.git
|
||||
|
||||
import app.credentials.GSessionManager
|
||||
import app.credentials.HttpCredentialsProvider
|
||||
import app.extensions.remoteName
|
||||
import app.extensions.simpleName
|
||||
import kotlinx.coroutines.*
|
||||
import kotlinx.coroutines.channels.awaitClose
|
||||
import kotlinx.coroutines.flow.Flow
|
||||
import kotlinx.coroutines.flow.callbackFlow
|
||||
import org.eclipse.jgit.api.Git
|
||||
import org.eclipse.jgit.api.RebaseResult
|
||||
import org.eclipse.jgit.lib.ProgressMonitor
|
||||
import org.eclipse.jgit.lib.Ref
|
||||
import org.eclipse.jgit.transport.*
|
||||
import java.io.File
|
||||
import javax.inject.Inject
|
||||
import kotlin.coroutines.cancellation.CancellationException
|
||||
|
||||
|
||||
class RemoteOperationsManager @Inject constructor(
|
||||
private val sessionManager: GSessionManager
|
||||
) {
|
||||
suspend fun pull(git: Git, rebase: Boolean) = withContext(Dispatchers.IO) {
|
||||
val pullResult = git
|
||||
.pull()
|
||||
.setTransportConfigCallback {
|
||||
handleTransportCredentials(it)
|
||||
}
|
||||
.setRebase(rebase)
|
||||
.setCredentialsProvider(CredentialsProvider.getDefault())
|
||||
.call()
|
||||
|
||||
if (!pullResult.isSuccessful) {
|
||||
var message = "Pull failed"
|
||||
|
||||
if (rebase) {
|
||||
message = when (pullResult.rebaseResult.status) {
|
||||
RebaseResult.Status.UNCOMMITTED_CHANGES -> "The pull with rebase has failed because you have got uncommited changes"
|
||||
RebaseResult.Status.CONFLICTS -> "Pull with rebase has conflicts, fix them to continue"
|
||||
else -> message
|
||||
}
|
||||
}
|
||||
|
||||
throw Exception(message)
|
||||
}
|
||||
}
|
||||
|
||||
suspend fun pullFromBranch(git: Git, rebase: Boolean, remoteBranch: Ref) = withContext(Dispatchers.IO) {
|
||||
val pullResult = git
|
||||
.pull()
|
||||
.setTransportConfigCallback {
|
||||
handleTransportCredentials(it)
|
||||
}
|
||||
.setRemote(remoteBranch.remoteName)
|
||||
.setRemoteBranchName(remoteBranch.simpleName)
|
||||
.setRebase(rebase)
|
||||
.setCredentialsProvider(CredentialsProvider.getDefault())
|
||||
.call()
|
||||
|
||||
if (!pullResult.isSuccessful) {
|
||||
var message = "Pull failed"
|
||||
|
||||
if (rebase) {
|
||||
message = when (pullResult.rebaseResult.status) {
|
||||
RebaseResult.Status.UNCOMMITTED_CHANGES -> "The pull with rebase has failed because you have got uncommited changes"
|
||||
RebaseResult.Status.CONFLICTS -> "Pull with rebase has conflicts, fix them to continue"
|
||||
else -> message
|
||||
}
|
||||
}
|
||||
|
||||
throw Exception(message)
|
||||
}
|
||||
}
|
||||
|
||||
suspend fun fetchAll(git: Git) = withContext(Dispatchers.IO) {
|
||||
val remotes = git.remoteList().call()
|
||||
|
||||
for (remote in remotes) {
|
||||
git.fetch()
|
||||
.setRemote(remote.name)
|
||||
.setRefSpecs(remote.fetchRefSpecs)
|
||||
.setTransportConfigCallback {
|
||||
handleTransportCredentials(it)
|
||||
}
|
||||
.setCredentialsProvider(CredentialsProvider.getDefault())
|
||||
.call()
|
||||
}
|
||||
}
|
||||
|
||||
suspend fun push(git: Git, force: Boolean, pushTags: Boolean) = withContext(Dispatchers.IO) {
|
||||
val currentBranchRefSpec = git.repository.fullBranch
|
||||
|
||||
val pushResult = git
|
||||
.push()
|
||||
.setRefSpecs(RefSpec(currentBranchRefSpec))
|
||||
.setForce(force)
|
||||
.apply {
|
||||
if (pushTags)
|
||||
setPushTags()
|
||||
}
|
||||
.setTransportConfigCallback {
|
||||
handleTransportCredentials(it)
|
||||
}
|
||||
.call()
|
||||
|
||||
val results =
|
||||
pushResult.map { it.remoteUpdates.filter { remoteRefUpdate -> remoteRefUpdate.status.isRejected } }
|
||||
.flatten()
|
||||
if (results.isNotEmpty()) {
|
||||
val error = StringBuilder()
|
||||
|
||||
results.forEach { result ->
|
||||
error.append(result.statusMessage)
|
||||
error.append("\n")
|
||||
}
|
||||
|
||||
throw Exception(error.toString())
|
||||
}
|
||||
}
|
||||
|
||||
suspend fun pushToBranch(git: Git, force: Boolean, pushTags: Boolean, remoteBranch: Ref) =
|
||||
withContext(Dispatchers.IO) {
|
||||
val currentBranchRefSpec = git.repository.fullBranch
|
||||
|
||||
val pushResult = git
|
||||
.push()
|
||||
.setRefSpecs(RefSpec("$currentBranchRefSpec:${remoteBranch.simpleName}"))
|
||||
.setRemote(remoteBranch.remoteName)
|
||||
.setForce(force)
|
||||
.apply {
|
||||
if (pushTags)
|
||||
setPushTags()
|
||||
}
|
||||
.setTransportConfigCallback {
|
||||
handleTransportCredentials(it)
|
||||
}
|
||||
.call()
|
||||
|
||||
val results =
|
||||
pushResult.map { it.remoteUpdates.filter { remoteRefUpdate -> remoteRefUpdate.status.isRejected } }
|
||||
.flatten()
|
||||
if (results.isNotEmpty()) {
|
||||
val error = StringBuilder()
|
||||
|
||||
results.forEach { result ->
|
||||
error.append(result.statusMessage)
|
||||
error.append("\n")
|
||||
}
|
||||
|
||||
throw Exception(error.toString())
|
||||
}
|
||||
}
|
||||
|
||||
private fun handleTransportCredentials(transport: Transport?) {
|
||||
if (transport is SshTransport) {
|
||||
transport.sshSessionFactory = sessionManager.generateSshSessionFactory()
|
||||
} else if (transport is HttpTransport) {
|
||||
transport.credentialsProvider = HttpCredentialsProvider()
|
||||
}
|
||||
}
|
||||
|
||||
suspend fun deleteBranch(git: Git, ref: Ref) = withContext(Dispatchers.IO) {
|
||||
val branchSplit = ref.name.split("/").toMutableList()
|
||||
val remoteName = branchSplit[2] // Remote name
|
||||
repeat(3) {
|
||||
branchSplit.removeAt(0)
|
||||
}
|
||||
|
||||
val branchName = "refs/heads/${branchSplit.joinToString("/")}"
|
||||
|
||||
val refSpec = RefSpec()
|
||||
.setSource(null)
|
||||
.setDestination(branchName)
|
||||
|
||||
val pushResult = git.push()
|
||||
.setTransportConfigCallback {
|
||||
handleTransportCredentials(it)
|
||||
}
|
||||
.setRefSpecs(refSpec)
|
||||
.setRemote(remoteName)
|
||||
.call()
|
||||
|
||||
val results =
|
||||
pushResult.map { it.remoteUpdates.filter { remoteRefUpdate -> remoteRefUpdate.status.isRejected } }
|
||||
.flatten()
|
||||
if (results.isNotEmpty()) {
|
||||
val error = StringBuilder()
|
||||
|
||||
results.forEach { result ->
|
||||
error.append(result.statusMessage)
|
||||
error.append("\n")
|
||||
}
|
||||
|
||||
throw Exception(error.toString())
|
||||
}
|
||||
|
||||
git
|
||||
.branchDelete()
|
||||
.setBranchNames(ref.name)
|
||||
.call()
|
||||
}
|
||||
|
||||
private val RemoteRefUpdate.Status.isRejected: Boolean
|
||||
get() {
|
||||
return this == RemoteRefUpdate.Status.REJECTED_NONFASTFORWARD ||
|
||||
this == RemoteRefUpdate.Status.REJECTED_NODELETE ||
|
||||
this == RemoteRefUpdate.Status.REJECTED_REMOTE_CHANGED ||
|
||||
this == RemoteRefUpdate.Status.REJECTED_OTHER_REASON
|
||||
}
|
||||
|
||||
private val RemoteRefUpdate.statusMessage: String
|
||||
get() {
|
||||
return when (this.status) {
|
||||
RemoteRefUpdate.Status.REJECTED_NONFASTFORWARD -> "Failed to push some refs to ${this.remoteName}. " +
|
||||
"Updates were rejected because the remote contains work that you do not have locally. Pulling changes from remote may help."
|
||||
RemoteRefUpdate.Status.REJECTED_NODELETE -> "Could not delete ref because the remote doesn't support deleting refs."
|
||||
RemoteRefUpdate.Status.REJECTED_REMOTE_CHANGED -> "Ref rejected, old object id in remote has changed."
|
||||
RemoteRefUpdate.Status.REJECTED_OTHER_REASON -> this.message ?: "Push rejected for unknown reasons."
|
||||
else -> ""
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@OptIn(ExperimentalCoroutinesApi::class)
|
||||
fun clone(directory: File, url: String): Flow<CloneStatus> = callbackFlow {
|
||||
var lastTitle: String = ""
|
||||
var lastTotalWork = 0
|
||||
var progress = 0
|
||||
|
||||
try {
|
||||
ensureActive()
|
||||
trySend(CloneStatus.Cloning("Starting...", progress, lastTotalWork))
|
||||
|
||||
Git.cloneRepository()
|
||||
.setDirectory(directory)
|
||||
.setURI(url)
|
||||
.setProgressMonitor(
|
||||
object : ProgressMonitor {
|
||||
override fun start(totalTasks: Int) {
|
||||
println("ProgressMonitor Start with total tasks of: $totalTasks")
|
||||
}
|
||||
|
||||
override fun beginTask(title: String?, totalWork: Int) {
|
||||
println("ProgressMonitor Begin task with title: $title")
|
||||
lastTitle = title.orEmpty()
|
||||
lastTotalWork = totalWork
|
||||
progress = 0
|
||||
trySend(CloneStatus.Cloning(lastTitle, progress, lastTotalWork))
|
||||
}
|
||||
|
||||
override fun update(completed: Int) {
|
||||
println("ProgressMonitor Update $completed")
|
||||
ensureActive()
|
||||
|
||||
progress += completed
|
||||
trySend(CloneStatus.Cloning(lastTitle, progress, lastTotalWork))
|
||||
}
|
||||
|
||||
override fun endTask() {
|
||||
println("ProgressMonitor End task")
|
||||
}
|
||||
|
||||
override fun isCancelled(): Boolean {
|
||||
return !isActive
|
||||
}
|
||||
}
|
||||
)
|
||||
.setTransportConfigCallback {
|
||||
handleTransportCredentials(it)
|
||||
}
|
||||
.call()
|
||||
|
||||
ensureActive()
|
||||
trySend(CloneStatus.Completed(directory))
|
||||
channel.close()
|
||||
} catch (ex: Exception) {
|
||||
if (ex.cause?.cause is CancellationException) {
|
||||
println("Clone cancelled")
|
||||
} else {
|
||||
trySend(CloneStatus.Fail(ex.localizedMessage))
|
||||
}
|
||||
|
||||
channel.close()
|
||||
}
|
||||
|
||||
awaitClose()
|
||||
}
|
||||
}
|
||||
|
||||
sealed class CloneStatus {
|
||||
object None : CloneStatus()
|
||||
data class Cloning(val taskName: String, val progress: Int, val total: Int) : CloneStatus()
|
||||
object Cancelling : CloneStatus()
|
||||
data class Fail(val reason: String) : CloneStatus()
|
||||
data class Completed(val repoDir: File) : CloneStatus()
|
||||
}
|
31
src/main/kotlin/app/git/author/LoadAuthorUseCase.kt
Normal file
31
src/main/kotlin/app/git/author/LoadAuthorUseCase.kt
Normal file
@ -0,0 +1,31 @@
|
||||
package app.git.author
|
||||
|
||||
import app.models.AuthorInfo
|
||||
import kotlinx.coroutines.Dispatchers
|
||||
import kotlinx.coroutines.withContext
|
||||
import org.eclipse.jgit.api.Git
|
||||
import org.eclipse.jgit.storage.file.FileBasedConfig
|
||||
import javax.inject.Inject
|
||||
|
||||
class LoadAuthorUseCase @Inject constructor() {
|
||||
suspend operator fun invoke(git: Git): AuthorInfo = withContext(Dispatchers.IO) {
|
||||
val config = git.repository.config
|
||||
val globalConfig = git.repository.config.baseConfig
|
||||
|
||||
val repoConfig = FileBasedConfig((config as FileBasedConfig).file, git.repository.fs)
|
||||
repoConfig.load()
|
||||
|
||||
val globalName = globalConfig.getString("user", null, "name")
|
||||
val globalEmail = globalConfig.getString("user", null, "email")
|
||||
|
||||
val name = repoConfig.getString("user", null, "name")
|
||||
val email = repoConfig.getString("user", null, "email")
|
||||
|
||||
return@withContext AuthorInfo(
|
||||
globalName,
|
||||
globalEmail,
|
||||
name,
|
||||
email,
|
||||
)
|
||||
}
|
||||
}
|
40
src/main/kotlin/app/git/author/SaveAuthorUseCase.kt
Normal file
40
src/main/kotlin/app/git/author/SaveAuthorUseCase.kt
Normal file
@ -0,0 +1,40 @@
|
||||
package app.git.author
|
||||
|
||||
import app.models.AuthorInfo
|
||||
import kotlinx.coroutines.Dispatchers
|
||||
import kotlinx.coroutines.withContext
|
||||
import org.eclipse.jgit.api.Git
|
||||
import org.eclipse.jgit.storage.file.FileBasedConfig
|
||||
import javax.inject.Inject
|
||||
|
||||
class SaveAuthorUseCase @Inject constructor() {
|
||||
suspend operator fun invoke(git: Git, newAuthorInfo: AuthorInfo) = withContext(Dispatchers.IO) {
|
||||
val config = git.repository.config
|
||||
val globalConfig = git.repository.config.baseConfig
|
||||
val repoConfig = FileBasedConfig((config as FileBasedConfig).file, git.repository.fs)
|
||||
repoConfig.load()
|
||||
|
||||
if (globalConfig is FileBasedConfig) {
|
||||
globalConfig.setStringProperty("user", null, "name", newAuthorInfo.globalName)
|
||||
globalConfig.setStringProperty("user", null, "email", newAuthorInfo.globalEmail)
|
||||
globalConfig.save()
|
||||
}
|
||||
|
||||
config.setStringProperty("user", null, "name", newAuthorInfo.name)
|
||||
config.setStringProperty("user", null, "email", newAuthorInfo.email)
|
||||
config.save()
|
||||
}
|
||||
}
|
||||
|
||||
private fun FileBasedConfig.setStringProperty(
|
||||
section: String,
|
||||
subsection: String?,
|
||||
name: String,
|
||||
value: String?,
|
||||
) {
|
||||
if (value == null) {
|
||||
unset(section, subsection, name)
|
||||
} else {
|
||||
setString(section, subsection, name, value)
|
||||
}
|
||||
}
|
25
src/main/kotlin/app/git/branches/CheckoutRefUseCase.kt
Normal file
25
src/main/kotlin/app/git/branches/CheckoutRefUseCase.kt
Normal file
@ -0,0 +1,25 @@
|
||||
package app.git.branches
|
||||
|
||||
import app.extensions.isBranch
|
||||
import app.extensions.simpleName
|
||||
import kotlinx.coroutines.Dispatchers
|
||||
import kotlinx.coroutines.withContext
|
||||
import org.eclipse.jgit.api.CreateBranchCommand
|
||||
import org.eclipse.jgit.api.Git
|
||||
import org.eclipse.jgit.lib.Ref
|
||||
import javax.inject.Inject
|
||||
|
||||
class CheckoutRefUseCase @Inject constructor() {
|
||||
suspend operator fun invoke(git: Git, ref: Ref): Unit = withContext(Dispatchers.IO) {
|
||||
git.checkout().apply {
|
||||
setName(ref.name)
|
||||
if (ref.isBranch && ref.name.startsWith("refs/remotes/")) {
|
||||
setCreateBranch(true)
|
||||
setName(ref.simpleName)
|
||||
setStartPoint(ref.objectId.name)
|
||||
setUpstreamMode(CreateBranchCommand.SetupUpstreamMode.TRACK)
|
||||
}
|
||||
call()
|
||||
}
|
||||
}
|
||||
}
|
@ -0,0 +1,19 @@
|
||||
package app.git.branches
|
||||
|
||||
import kotlinx.coroutines.Dispatchers
|
||||
import kotlinx.coroutines.withContext
|
||||
import org.eclipse.jgit.api.Git
|
||||
import org.eclipse.jgit.lib.Ref
|
||||
import org.eclipse.jgit.revwalk.RevCommit
|
||||
import javax.inject.Inject
|
||||
|
||||
class CreateBranchOnCommitUseCase @Inject constructor() {
|
||||
suspend operator fun invoke(git: Git, branch: String, revCommit: RevCommit): Ref = withContext(Dispatchers.IO) {
|
||||
git
|
||||
.checkout()
|
||||
.setCreateBranch(true)
|
||||
.setName(branch)
|
||||
.setStartPoint(revCommit)
|
||||
.call()
|
||||
}
|
||||
}
|
17
src/main/kotlin/app/git/branches/CreateBranchUseCase.kt
Normal file
17
src/main/kotlin/app/git/branches/CreateBranchUseCase.kt
Normal file
@ -0,0 +1,17 @@
|
||||
package app.git.branches
|
||||
|
||||
import kotlinx.coroutines.Dispatchers
|
||||
import kotlinx.coroutines.withContext
|
||||
import org.eclipse.jgit.api.Git
|
||||
import org.eclipse.jgit.lib.Ref
|
||||
import javax.inject.Inject
|
||||
|
||||
class CreateBranchUseCase @Inject constructor() {
|
||||
suspend operator fun invoke(git: Git, branchName: String): Ref = withContext(Dispatchers.IO) {
|
||||
git
|
||||
.checkout()
|
||||
.setCreateBranch(true)
|
||||
.setName(branchName)
|
||||
.call()
|
||||
}
|
||||
}
|
17
src/main/kotlin/app/git/branches/DeleteBranchUseCase.kt
Normal file
17
src/main/kotlin/app/git/branches/DeleteBranchUseCase.kt
Normal file
@ -0,0 +1,17 @@
|
||||
package app.git.branches
|
||||
|
||||
import kotlinx.coroutines.Dispatchers
|
||||
import kotlinx.coroutines.withContext
|
||||
import org.eclipse.jgit.api.Git
|
||||
import org.eclipse.jgit.lib.Ref
|
||||
import javax.inject.Inject
|
||||
|
||||
class DeleteBranchUseCase @Inject constructor() {
|
||||
suspend operator fun invoke(git: Git, branch: Ref): List<String> = withContext(Dispatchers.IO) {
|
||||
git
|
||||
.branchDelete()
|
||||
.setBranchNames(branch.name)
|
||||
.setForce(true) // TODO Should it be forced?
|
||||
.call()
|
||||
}
|
||||
}
|
@ -0,0 +1,16 @@
|
||||
package app.git.branches
|
||||
|
||||
import kotlinx.coroutines.Dispatchers
|
||||
import kotlinx.coroutines.withContext
|
||||
import org.eclipse.jgit.api.Git
|
||||
import javax.inject.Inject
|
||||
|
||||
class DeleteLocallyRemoteBranches @Inject constructor() {
|
||||
suspend operator fun invoke(git: Git, branches: List<String>): List<String> = withContext(Dispatchers.IO) {
|
||||
git
|
||||
.branchDelete()
|
||||
.setBranchNames(*branches.toTypedArray())
|
||||
.setForce(true)
|
||||
.call()
|
||||
}
|
||||
}
|
15
src/main/kotlin/app/git/branches/GetBranchesUseCase.kt
Normal file
15
src/main/kotlin/app/git/branches/GetBranchesUseCase.kt
Normal file
@ -0,0 +1,15 @@
|
||||
package app.git.branches
|
||||
|
||||
import kotlinx.coroutines.Dispatchers
|
||||
import kotlinx.coroutines.withContext
|
||||
import org.eclipse.jgit.api.Git
|
||||
import org.eclipse.jgit.lib.Ref
|
||||
import javax.inject.Inject
|
||||
|
||||
class GetBranchesUseCase @Inject constructor() {
|
||||
suspend operator fun invoke(git: Git): List<Ref> = withContext(Dispatchers.IO) {
|
||||
return@withContext git
|
||||
.branchList()
|
||||
.call()
|
||||
}
|
||||
}
|
31
src/main/kotlin/app/git/branches/GetCurrentBranchUseCase.kt
Normal file
31
src/main/kotlin/app/git/branches/GetCurrentBranchUseCase.kt
Normal file
@ -0,0 +1,31 @@
|
||||
package app.git.branches
|
||||
|
||||
import org.eclipse.jgit.api.Git
|
||||
import org.eclipse.jgit.lib.Ref
|
||||
import javax.inject.Inject
|
||||
|
||||
/**
|
||||
* Returns the current branch in [Ref]. If the repository is new, the current branch will be null.
|
||||
*/
|
||||
class GetCurrentBranchUseCase @Inject constructor(
|
||||
private val getBranchesUseCase: GetBranchesUseCase,
|
||||
) {
|
||||
suspend operator fun invoke(git: Git): Ref? {
|
||||
val branchList = getBranchesUseCase(git)
|
||||
val branchName = git
|
||||
.repository
|
||||
.fullBranch
|
||||
|
||||
var branchFound = branchList.firstOrNull {
|
||||
it.name == branchName
|
||||
}
|
||||
|
||||
if (branchFound == null) {
|
||||
branchFound = branchList.firstOrNull {
|
||||
it.objectId.name == branchName // Try to get the HEAD
|
||||
}
|
||||
}
|
||||
|
||||
return branchFound
|
||||
}
|
||||
}
|
17
src/main/kotlin/app/git/branches/GetRemoteBranchesUseCase.kt
Normal file
17
src/main/kotlin/app/git/branches/GetRemoteBranchesUseCase.kt
Normal file
@ -0,0 +1,17 @@
|
||||
package app.git.branches
|
||||
|
||||
import kotlinx.coroutines.Dispatchers
|
||||
import kotlinx.coroutines.withContext
|
||||
import org.eclipse.jgit.api.Git
|
||||
import org.eclipse.jgit.api.ListBranchCommand
|
||||
import org.eclipse.jgit.lib.Ref
|
||||
import javax.inject.Inject
|
||||
|
||||
class GetRemoteBranchesUseCase @Inject constructor() {
|
||||
suspend operator fun invoke(git: Git): List<Ref> = withContext(Dispatchers.IO) {
|
||||
git
|
||||
.branchList()
|
||||
.setListMode(ListBranchCommand.ListMode.REMOTE)
|
||||
.call()
|
||||
}
|
||||
}
|
@ -0,0 +1,81 @@
|
||||
package app.git.remote_operations
|
||||
|
||||
import app.git.CloneStatus
|
||||
import kotlinx.coroutines.CancellationException
|
||||
import kotlinx.coroutines.ExperimentalCoroutinesApi
|
||||
import kotlinx.coroutines.channels.awaitClose
|
||||
import kotlinx.coroutines.ensureActive
|
||||
import kotlinx.coroutines.flow.Flow
|
||||
import kotlinx.coroutines.flow.callbackFlow
|
||||
import kotlinx.coroutines.isActive
|
||||
import org.eclipse.jgit.api.Git
|
||||
import org.eclipse.jgit.lib.ProgressMonitor
|
||||
import java.io.File
|
||||
import javax.inject.Inject
|
||||
|
||||
class CloneRepositoryUseCase @Inject constructor(
|
||||
private val handleTransportUseCase: HandleTransportUseCase,
|
||||
) {
|
||||
@OptIn(ExperimentalCoroutinesApi::class)
|
||||
operator fun invoke(directory: File, url: String): Flow<CloneStatus> = callbackFlow {
|
||||
var lastTitle: String = ""
|
||||
var lastTotalWork = 0
|
||||
var progress = 0
|
||||
|
||||
try {
|
||||
ensureActive()
|
||||
trySend(CloneStatus.Cloning("Starting...", progress, lastTotalWork))
|
||||
|
||||
Git.cloneRepository()
|
||||
.setDirectory(directory)
|
||||
.setURI(url)
|
||||
.setProgressMonitor(
|
||||
object : ProgressMonitor {
|
||||
override fun start(totalTasks: Int) {
|
||||
println("ProgressMonitor Start with total tasks of: $totalTasks")
|
||||
}
|
||||
|
||||
override fun beginTask(title: String?, totalWork: Int) {
|
||||
println("ProgressMonitor Begin task with title: $title")
|
||||
lastTitle = title.orEmpty()
|
||||
lastTotalWork = totalWork
|
||||
progress = 0
|
||||
trySend(CloneStatus.Cloning(lastTitle, progress, lastTotalWork))
|
||||
}
|
||||
|
||||
override fun update(completed: Int) {
|
||||
println("ProgressMonitor Update $completed")
|
||||
ensureActive()
|
||||
|
||||
progress += completed
|
||||
trySend(CloneStatus.Cloning(lastTitle, progress, lastTotalWork))
|
||||
}
|
||||
|
||||
override fun endTask() {
|
||||
println("ProgressMonitor End task")
|
||||
}
|
||||
|
||||
override fun isCancelled(): Boolean {
|
||||
return !isActive
|
||||
}
|
||||
}
|
||||
)
|
||||
.setTransportConfigCallback { handleTransportUseCase(it) }
|
||||
.call()
|
||||
|
||||
ensureActive()
|
||||
trySend(CloneStatus.Completed(directory))
|
||||
channel.close()
|
||||
} catch (ex: Exception) {
|
||||
if (ex.cause?.cause is CancellationException) {
|
||||
println("Clone cancelled")
|
||||
} else {
|
||||
trySend(CloneStatus.Fail(ex.localizedMessage))
|
||||
}
|
||||
|
||||
channel.close()
|
||||
}
|
||||
|
||||
awaitClose()
|
||||
}
|
||||
}
|
@ -0,0 +1,59 @@
|
||||
package app.git.remote_operations
|
||||
|
||||
import app.git.branches.DeleteBranchUseCase
|
||||
import app.git.isRejected
|
||||
import app.git.statusMessage
|
||||
import org.eclipse.jgit.api.Git
|
||||
import org.eclipse.jgit.lib.Ref
|
||||
import org.eclipse.jgit.transport.RefSpec
|
||||
import javax.inject.Inject
|
||||
|
||||
class DeleteRemoteBranchUseCase @Inject constructor(
|
||||
private val handleTransportUseCase: HandleTransportUseCase,
|
||||
private val deleteBranchUseCase: DeleteBranchUseCase,
|
||||
) {
|
||||
suspend operator fun invoke(git: Git, ref: Ref) {
|
||||
val branchSplit = ref.name.split("/").toMutableList()
|
||||
val remoteName = branchSplit[2] // Remote name
|
||||
repeat(3) {
|
||||
branchSplit.removeAt(0)
|
||||
}
|
||||
|
||||
val branchName = "refs/heads/${branchSplit.joinToString("/")}"
|
||||
|
||||
val refSpec = RefSpec()
|
||||
.setSource(null)
|
||||
.setDestination(branchName)
|
||||
|
||||
val pushResults = git.push()
|
||||
.setTransportConfigCallback {
|
||||
handleTransportUseCase(it)
|
||||
}
|
||||
.setRefSpecs(refSpec)
|
||||
.setRemote(remoteName)
|
||||
.call()
|
||||
|
||||
val results = pushResults.map { pushResult ->
|
||||
pushResult.remoteUpdates.filter { remoteRefUpdate ->
|
||||
remoteRefUpdate.status.isRejected
|
||||
}
|
||||
}.flatten()
|
||||
|
||||
if (results.isNotEmpty()) {
|
||||
val error = StringBuilder()
|
||||
|
||||
results.forEach { result ->
|
||||
error.append(result.statusMessage)
|
||||
error.append("\n")
|
||||
}
|
||||
|
||||
throw Exception(error.toString())
|
||||
}
|
||||
|
||||
deleteBranchUseCase(git, ref)
|
||||
// git
|
||||
// .branchDelete()
|
||||
// .setBranchNames(ref.name)
|
||||
// .call()
|
||||
}
|
||||
}
|
@ -0,0 +1,24 @@
|
||||
package app.git.remote_operations
|
||||
|
||||
import kotlinx.coroutines.Dispatchers
|
||||
import kotlinx.coroutines.withContext
|
||||
import org.eclipse.jgit.api.Git
|
||||
import org.eclipse.jgit.transport.CredentialsProvider
|
||||
import javax.inject.Inject
|
||||
|
||||
class FetchAllBranchesUseCase @Inject constructor(
|
||||
private val handleTransportUseCase: HandleTransportUseCase,
|
||||
) {
|
||||
suspend operator fun invoke(git: Git) = withContext(Dispatchers.IO) {
|
||||
val remotes = git.remoteList().call()
|
||||
|
||||
for (remote in remotes) {
|
||||
git.fetch()
|
||||
.setRemote(remote.name)
|
||||
.setRefSpecs(remote.fetchRefSpecs)
|
||||
.setTransportConfigCallback { handleTransportUseCase(it) }
|
||||
.setCredentialsProvider(CredentialsProvider.getDefault())
|
||||
.call()
|
||||
}
|
||||
}
|
||||
}
|
@ -0,0 +1,20 @@
|
||||
package app.git.remote_operations
|
||||
|
||||
import app.credentials.GSessionManager
|
||||
import app.credentials.HttpCredentialsProvider
|
||||
import org.eclipse.jgit.transport.HttpTransport
|
||||
import org.eclipse.jgit.transport.SshTransport
|
||||
import org.eclipse.jgit.transport.Transport
|
||||
import javax.inject.Inject
|
||||
|
||||
class HandleTransportUseCase @Inject constructor(
|
||||
private val sessionManager: GSessionManager
|
||||
) {
|
||||
operator fun invoke(transport: Transport?) {
|
||||
if (transport is SshTransport) {
|
||||
transport.sshSessionFactory = sessionManager.generateSshSessionFactory()
|
||||
} else if (transport is HttpTransport) {
|
||||
transport.credentialsProvider = HttpCredentialsProvider()
|
||||
}
|
||||
}
|
||||
}
|
@ -0,0 +1,35 @@
|
||||
package app.git.remote_operations
|
||||
|
||||
import kotlinx.coroutines.Dispatchers
|
||||
import kotlinx.coroutines.withContext
|
||||
import org.eclipse.jgit.api.Git
|
||||
import org.eclipse.jgit.api.RebaseResult
|
||||
import org.eclipse.jgit.transport.CredentialsProvider
|
||||
import javax.inject.Inject
|
||||
|
||||
class PullBranchUseCase @Inject constructor(
|
||||
private val handleTransportUseCase: HandleTransportUseCase,
|
||||
) {
|
||||
suspend operator fun invoke(git: Git, rebase: Boolean) = withContext(Dispatchers.IO) {
|
||||
val pullResult = git
|
||||
.pull()
|
||||
.setTransportConfigCallback { handleTransportUseCase(it) }
|
||||
.setRebase(rebase)
|
||||
.setCredentialsProvider(CredentialsProvider.getDefault())
|
||||
.call()
|
||||
|
||||
if (!pullResult.isSuccessful) {
|
||||
var message = "Pull failed"
|
||||
|
||||
if (rebase) {
|
||||
message = when (pullResult.rebaseResult.status) {
|
||||
RebaseResult.Status.UNCOMMITTED_CHANGES -> "The pull with rebase has failed because you have got uncommited changes"
|
||||
RebaseResult.Status.CONFLICTS -> "Pull with rebase has conflicts, fix them to continue"
|
||||
else -> message
|
||||
}
|
||||
}
|
||||
|
||||
throw Exception(message)
|
||||
}
|
||||
}
|
||||
}
|
@ -0,0 +1,40 @@
|
||||
package app.git.remote_operations
|
||||
|
||||
import app.extensions.remoteName
|
||||
import app.extensions.simpleName
|
||||
import kotlinx.coroutines.Dispatchers
|
||||
import kotlinx.coroutines.withContext
|
||||
import org.eclipse.jgit.api.Git
|
||||
import org.eclipse.jgit.api.RebaseResult
|
||||
import org.eclipse.jgit.lib.Ref
|
||||
import org.eclipse.jgit.transport.CredentialsProvider
|
||||
import javax.inject.Inject
|
||||
|
||||
class PullFromSpecificBranchUseCase @Inject constructor(
|
||||
private val handleTransportUseCase: HandleTransportUseCase,
|
||||
) {
|
||||
suspend operator fun invoke(git: Git, rebase: Boolean, remoteBranch: Ref) = withContext(Dispatchers.IO) {
|
||||
val pullResult = git
|
||||
.pull()
|
||||
.setTransportConfigCallback { handleTransportUseCase(it) }
|
||||
.setRemote(remoteBranch.remoteName)
|
||||
.setRemoteBranchName(remoteBranch.simpleName)
|
||||
.setRebase(rebase)
|
||||
.setCredentialsProvider(CredentialsProvider.getDefault())
|
||||
.call()
|
||||
|
||||
if (!pullResult.isSuccessful) {
|
||||
var message = "Pull failed" // TODO Remove messages from here and pass the result to a custom exception type
|
||||
|
||||
if (rebase) {
|
||||
message = when (pullResult.rebaseResult.status) {
|
||||
RebaseResult.Status.UNCOMMITTED_CHANGES -> "The pull with rebase has failed because you have got uncommited changes"
|
||||
RebaseResult.Status.CONFLICTS -> "Pull with rebase has conflicts, fix them to continue"
|
||||
else -> message
|
||||
}
|
||||
}
|
||||
|
||||
throw Exception(message)
|
||||
}
|
||||
}
|
||||
}
|
@ -0,0 +1,43 @@
|
||||
package app.git.remote_operations
|
||||
|
||||
import app.git.isRejected
|
||||
import app.git.statusMessage
|
||||
import kotlinx.coroutines.Dispatchers
|
||||
import kotlinx.coroutines.withContext
|
||||
import org.eclipse.jgit.api.Git
|
||||
import org.eclipse.jgit.transport.RefSpec
|
||||
import javax.inject.Inject
|
||||
|
||||
class PushBranchUseCase @Inject constructor(
|
||||
private val handleTransportUseCase: HandleTransportUseCase,
|
||||
) {
|
||||
suspend operator fun invoke(git: Git, force: Boolean, pushTags: Boolean) = withContext(Dispatchers.IO) {
|
||||
val currentBranchRefSpec = git.repository.fullBranch
|
||||
|
||||
val pushResult = git
|
||||
.push()
|
||||
.setRefSpecs(RefSpec(currentBranchRefSpec))
|
||||
.setForce(force)
|
||||
.apply {
|
||||
if (pushTags)
|
||||
setPushTags()
|
||||
}
|
||||
.setTransportConfigCallback { handleTransportUseCase(it) }
|
||||
.call()
|
||||
|
||||
val results =
|
||||
pushResult.map { it.remoteUpdates.filter { remoteRefUpdate -> remoteRefUpdate.status.isRejected } }
|
||||
.flatten()
|
||||
if (results.isNotEmpty()) {
|
||||
val error = StringBuilder()
|
||||
|
||||
results.forEach { result ->
|
||||
error.append(result.statusMessage)
|
||||
error.append("\n")
|
||||
}
|
||||
|
||||
throw Exception(error.toString())
|
||||
}
|
||||
}
|
||||
|
||||
}
|
@ -0,0 +1,47 @@
|
||||
package app.git.remote_operations
|
||||
|
||||
import app.extensions.remoteName
|
||||
import app.extensions.simpleName
|
||||
import app.git.isRejected
|
||||
import app.git.statusMessage
|
||||
import kotlinx.coroutines.Dispatchers
|
||||
import kotlinx.coroutines.withContext
|
||||
import org.eclipse.jgit.api.Git
|
||||
import org.eclipse.jgit.lib.Ref
|
||||
import org.eclipse.jgit.transport.RefSpec
|
||||
import javax.inject.Inject
|
||||
|
||||
class PushToSpecificBranchUseCase @Inject constructor(
|
||||
private val handleTransportUseCase: HandleTransportUseCase,
|
||||
) {
|
||||
suspend operator fun invoke(git: Git, force: Boolean, pushTags: Boolean, remoteBranch: Ref) =
|
||||
withContext(Dispatchers.IO) {
|
||||
val currentBranchRefSpec = git.repository.fullBranch
|
||||
|
||||
val pushResult = git
|
||||
.push()
|
||||
.setRefSpecs(RefSpec("$currentBranchRefSpec:${remoteBranch.simpleName}"))
|
||||
.setRemote(remoteBranch.remoteName)
|
||||
.setForce(force)
|
||||
.apply {
|
||||
if (pushTags)
|
||||
setPushTags()
|
||||
}
|
||||
.setTransportConfigCallback { handleTransportUseCase(it) }
|
||||
.call()
|
||||
|
||||
val results =
|
||||
pushResult.map { it.remoteUpdates.filter { remoteRefUpdate -> remoteRefUpdate.status.isRejected } }
|
||||
.flatten()
|
||||
if (results.isNotEmpty()) {
|
||||
val error = StringBuilder()
|
||||
|
||||
results.forEach { result ->
|
||||
error.append(result.statusMessage)
|
||||
error.append("\n")
|
||||
}
|
||||
|
||||
throw Exception(error.toString())
|
||||
}
|
||||
}
|
||||
}
|
@ -1,9 +1,10 @@
|
||||
package app.viewmodels
|
||||
|
||||
import app.extensions.nullIfEmpty
|
||||
import app.git.AuthorManager
|
||||
import app.git.RefreshType
|
||||
import app.git.TabState
|
||||
import app.git.author.LoadAuthorUseCase
|
||||
import app.git.author.SaveAuthorUseCase
|
||||
import app.models.AuthorInfo
|
||||
import kotlinx.coroutines.flow.MutableStateFlow
|
||||
import kotlinx.coroutines.flow.StateFlow
|
||||
@ -11,7 +12,8 @@ import javax.inject.Inject
|
||||
|
||||
class AuthorViewModel @Inject constructor(
|
||||
private val tabState: TabState,
|
||||
private val authorManager: AuthorManager,
|
||||
private val saveAuthorUseCase: SaveAuthorUseCase,
|
||||
private val loadAuthorUseCase: LoadAuthorUseCase,
|
||||
) {
|
||||
|
||||
private val _authorInfo = MutableStateFlow(AuthorInfo(null, null, null, null))
|
||||
@ -21,7 +23,7 @@ class AuthorViewModel @Inject constructor(
|
||||
refreshType = RefreshType.NONE,
|
||||
showError = true,
|
||||
) { git ->
|
||||
_authorInfo.value = authorManager.loadAuthor(git)
|
||||
_authorInfo.value = loadAuthorUseCase(git)
|
||||
}
|
||||
|
||||
fun saveAuthorInfo(globalName: String, globalEmail: String, name: String, email: String) = tabState.runOperation(
|
||||
@ -35,6 +37,6 @@ class AuthorViewModel @Inject constructor(
|
||||
email.nullIfEmpty,
|
||||
)
|
||||
|
||||
authorManager.saveAuthorInfo(git, newAuthorInfo)
|
||||
saveAuthorUseCase(git, newAuthorInfo)
|
||||
}
|
||||
}
|
||||
|
@ -1,6 +1,9 @@
|
||||
package app.viewmodels
|
||||
|
||||
import app.git.*
|
||||
import app.git.branches.*
|
||||
import app.git.remote_operations.PullFromSpecificBranchUseCase
|
||||
import app.git.remote_operations.PushToSpecificBranchUseCase
|
||||
import app.preferences.AppSettings
|
||||
import kotlinx.coroutines.flow.MutableStateFlow
|
||||
import kotlinx.coroutines.flow.StateFlow
|
||||
@ -9,12 +12,17 @@ import org.eclipse.jgit.lib.Ref
|
||||
import javax.inject.Inject
|
||||
|
||||
class BranchesViewModel @Inject constructor(
|
||||
private val branchesManager: BranchesManager,
|
||||
private val rebaseManager: RebaseManager,
|
||||
private val mergeManager: MergeManager,
|
||||
private val remoteOperationsManager: RemoteOperationsManager,
|
||||
private val pushToSpecificBranchUseCase: PushToSpecificBranchUseCase,
|
||||
private val pullFromSpecificBranchUseCase: PullFromSpecificBranchUseCase,
|
||||
private val tabState: TabState,
|
||||
private val appSettings: AppSettings,
|
||||
private val getCurrentBranchUseCase: GetCurrentBranchUseCase,
|
||||
private val getBranchesUseCase: GetBranchesUseCase,
|
||||
private val createBranchUseCase: CreateBranchUseCase,
|
||||
private val deleteBranchUseCase: DeleteBranchUseCase,
|
||||
private val checkoutRefUseCase: CheckoutRefUseCase,
|
||||
) : ExpandableViewModel(true) {
|
||||
private val _branches = MutableStateFlow<List<Ref>>(listOf())
|
||||
val branches: StateFlow<List<Ref>>
|
||||
@ -25,9 +33,9 @@ class BranchesViewModel @Inject constructor(
|
||||
get() = _currentBranch
|
||||
|
||||
suspend fun loadBranches(git: Git) {
|
||||
_currentBranch.value = branchesManager.currentBranchRef(git)
|
||||
_currentBranch.value = getCurrentBranchUseCase(git)
|
||||
|
||||
val branchesList = branchesManager.getBranches(git)
|
||||
val branchesList = getBranchesUseCase(git).toMutableList()
|
||||
|
||||
// set selected branch as the first one always
|
||||
val selectedBranch = branchesList.find { it.name == _currentBranch.value?.name }
|
||||
@ -44,7 +52,7 @@ class BranchesViewModel @Inject constructor(
|
||||
refreshType = RefreshType.ONLY_LOG,
|
||||
refreshEvenIfCrashes = true,
|
||||
) { git ->
|
||||
branchesManager.createBranch(git, branchName)
|
||||
createBranchUseCase(git, branchName)
|
||||
this.loadBranches(git)
|
||||
}
|
||||
|
||||
@ -57,13 +65,13 @@ class BranchesViewModel @Inject constructor(
|
||||
fun deleteBranch(branch: Ref) = tabState.safeProcessing(
|
||||
refreshType = RefreshType.ALL_DATA,
|
||||
) { git ->
|
||||
branchesManager.deleteBranch(git, branch)
|
||||
deleteBranchUseCase(git, branch)
|
||||
}
|
||||
|
||||
fun checkoutRef(ref: Ref) = tabState.safeProcessing(
|
||||
refreshType = RefreshType.ALL_DATA,
|
||||
) { git ->
|
||||
branchesManager.checkoutRef(git, ref)
|
||||
checkoutRefUseCase(git, ref)
|
||||
}
|
||||
|
||||
suspend fun refresh(git: Git) {
|
||||
@ -83,7 +91,7 @@ class BranchesViewModel @Inject constructor(
|
||||
fun pushToRemoteBranch(branch: Ref) = tabState.safeProcessing(
|
||||
refreshType = RefreshType.ALL_DATA,
|
||||
) { git ->
|
||||
remoteOperationsManager.pushToBranch(
|
||||
pushToSpecificBranchUseCase(
|
||||
git = git,
|
||||
force = false,
|
||||
pushTags = false,
|
||||
@ -94,7 +102,7 @@ class BranchesViewModel @Inject constructor(
|
||||
fun pullFromRemoteBranch(branch: Ref) = tabState.safeProcessing(
|
||||
refreshType = RefreshType.ALL_DATA,
|
||||
) { git ->
|
||||
remoteOperationsManager.pullFromBranch(
|
||||
pullFromSpecificBranchUseCase(
|
||||
git = git,
|
||||
rebase = false,
|
||||
remoteBranch = branch,
|
||||
|
@ -1,8 +1,8 @@
|
||||
package app.viewmodels
|
||||
|
||||
import app.git.CloneStatus
|
||||
import app.git.RemoteOperationsManager
|
||||
import app.git.TabState
|
||||
import app.git.remote_operations.CloneRepositoryUseCase
|
||||
import kotlinx.coroutines.Dispatchers
|
||||
import kotlinx.coroutines.Job
|
||||
import kotlinx.coroutines.flow.MutableStateFlow
|
||||
@ -14,7 +14,7 @@ import javax.inject.Inject
|
||||
|
||||
class CloneViewModel @Inject constructor(
|
||||
private val tabState: TabState,
|
||||
private val remoteOperationsManager: RemoteOperationsManager,
|
||||
private val cloneRepositoryUseCase: CloneRepositoryUseCase,
|
||||
) {
|
||||
|
||||
private val _cloneStatus = MutableStateFlow<CloneStatus>(CloneStatus.None)
|
||||
@ -69,7 +69,7 @@ class CloneViewModel @Inject constructor(
|
||||
repoDir.mkdir()
|
||||
}
|
||||
|
||||
remoteOperationsManager.clone(repoDir, url)
|
||||
cloneRepositoryUseCase(repoDir, url)
|
||||
.flowOn(Dispatchers.IO)
|
||||
.collect { newCloneStatus ->
|
||||
_cloneStatus.value = newCloneStatus
|
||||
|
@ -4,8 +4,12 @@ import androidx.compose.foundation.ScrollState
|
||||
import androidx.compose.foundation.lazy.LazyListState
|
||||
import app.extensions.delayedStateChange
|
||||
import app.git.*
|
||||
import app.git.branches.*
|
||||
import app.git.graph.GraphCommitList
|
||||
import app.git.graph.GraphNode
|
||||
import app.git.remote_operations.DeleteRemoteBranchUseCase
|
||||
import app.git.remote_operations.PullFromSpecificBranchUseCase
|
||||
import app.git.remote_operations.PushToSpecificBranchUseCase
|
||||
import app.preferences.AppSettings
|
||||
import app.ui.SelectedItem
|
||||
import app.ui.log.LogDialog
|
||||
@ -34,11 +38,16 @@ private const val LOG_MIN_TIME_IN_MS_TO_SHOW_LOAD = 500L
|
||||
class LogViewModel @Inject constructor(
|
||||
private val logManager: LogManager,
|
||||
private val statusManager: StatusManager,
|
||||
private val branchesManager: BranchesManager,
|
||||
private val getCurrentBranchUseCase: GetCurrentBranchUseCase,
|
||||
private val checkoutRefUseCase: CheckoutRefUseCase,
|
||||
private val createBranchOnCommitUseCase: CreateBranchOnCommitUseCase,
|
||||
private val deleteBranchUseCase: DeleteBranchUseCase,
|
||||
private val pushToSpecificBranchUseCase: PushToSpecificBranchUseCase,
|
||||
private val pullFromSpecificBranchUseCase: PullFromSpecificBranchUseCase,
|
||||
private val deleteRemoteBranchUseCase: DeleteRemoteBranchUseCase,
|
||||
private val rebaseManager: RebaseManager,
|
||||
private val tagsManager: TagsManager,
|
||||
private val mergeManager: MergeManager,
|
||||
private val remoteOperationsManager: RemoteOperationsManager,
|
||||
private val tabState: TabState,
|
||||
private val appSettings: AppSettings,
|
||||
) {
|
||||
@ -83,7 +92,7 @@ class LogViewModel @Inject constructor(
|
||||
_logStatus.value = LogStatus.Loading
|
||||
}
|
||||
) {
|
||||
val currentBranch = branchesManager.currentBranchRef(git)
|
||||
val currentBranch = getCurrentBranchUseCase(git)
|
||||
|
||||
val statusSummary = statusManager.getStatusSummary(
|
||||
git = git,
|
||||
@ -113,7 +122,7 @@ class LogViewModel @Inject constructor(
|
||||
fun pushToRemoteBranch(branch: Ref) = tabState.safeProcessing(
|
||||
refreshType = RefreshType.ALL_DATA,
|
||||
) { git ->
|
||||
remoteOperationsManager.pushToBranch(
|
||||
pushToSpecificBranchUseCase(
|
||||
git = git,
|
||||
force = false,
|
||||
pushTags = false,
|
||||
@ -124,7 +133,7 @@ class LogViewModel @Inject constructor(
|
||||
fun pullFromRemoteBranch(branch: Ref) = tabState.safeProcessing(
|
||||
refreshType = RefreshType.ALL_DATA,
|
||||
) { git ->
|
||||
remoteOperationsManager.pullFromBranch(
|
||||
pullFromSpecificBranchUseCase(
|
||||
git = git,
|
||||
rebase = false,
|
||||
remoteBranch = branch,
|
||||
@ -152,7 +161,7 @@ class LogViewModel @Inject constructor(
|
||||
fun checkoutRef(ref: Ref) = tabState.safeProcessing(
|
||||
refreshType = RefreshType.ALL_DATA,
|
||||
) { git ->
|
||||
branchesManager.checkoutRef(git, ref)
|
||||
checkoutRefUseCase(git, ref)
|
||||
}
|
||||
|
||||
fun cherrypickCommit(revCommit: RevCommit) = tabState.safeProcessing(
|
||||
@ -164,7 +173,7 @@ class LogViewModel @Inject constructor(
|
||||
fun createBranchOnCommit(branch: String, revCommit: RevCommit) = tabState.safeProcessing(
|
||||
refreshType = RefreshType.ALL_DATA,
|
||||
) { git ->
|
||||
branchesManager.createBranchOnCommit(git, branch, revCommit)
|
||||
createBranchOnCommitUseCase(git, branch, revCommit)
|
||||
}
|
||||
|
||||
fun createTagOnCommit(tag: String, revCommit: RevCommit) = tabState.safeProcessing(
|
||||
@ -182,7 +191,7 @@ class LogViewModel @Inject constructor(
|
||||
fun deleteBranch(branch: Ref) = tabState.safeProcessing(
|
||||
refreshType = RefreshType.ALL_DATA,
|
||||
) { git ->
|
||||
branchesManager.deleteBranch(git, branch)
|
||||
deleteBranchUseCase(git, branch)
|
||||
}
|
||||
|
||||
fun deleteTag(tag: Ref) = tabState.safeProcessing(
|
||||
@ -196,7 +205,7 @@ class LogViewModel @Inject constructor(
|
||||
}
|
||||
|
||||
private suspend fun uncommitedChangesLoadLog(git: Git) {
|
||||
val currentBranch = branchesManager.currentBranchRef(git)
|
||||
val currentBranch = getCurrentBranchUseCase(git)
|
||||
val hasUncommitedChanges = statusManager.hasUncommitedChanges(git)
|
||||
|
||||
val statsSummary = if (hasUncommitedChanges) {
|
||||
@ -357,7 +366,7 @@ class LogViewModel @Inject constructor(
|
||||
fun deleteRemoteBranch(branch: Ref) = tabState.safeProcessing(
|
||||
refreshType = RefreshType.ALL_DATA,
|
||||
) { git ->
|
||||
remoteOperationsManager.deleteBranch(git, branch)
|
||||
deleteRemoteBranchUseCase(git, branch)
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1,12 +1,18 @@
|
||||
package app.viewmodels
|
||||
|
||||
import app.git.*
|
||||
import app.git.remote_operations.DeleteRemoteBranchUseCase
|
||||
import app.git.remote_operations.FetchAllBranchesUseCase
|
||||
import app.git.remote_operations.PullBranchUseCase
|
||||
import app.git.remote_operations.PushBranchUseCase
|
||||
import java.awt.Desktop
|
||||
import javax.inject.Inject
|
||||
|
||||
class MenuViewModel @Inject constructor(
|
||||
private val tabState: TabState,
|
||||
private val remoteOperationsManager: RemoteOperationsManager,
|
||||
private val pullBranchUseCase: PullBranchUseCase,
|
||||
private val pushBranchUseCase: PushBranchUseCase,
|
||||
private val fetchAllBranchesUseCase: FetchAllBranchesUseCase,
|
||||
private val stashManager: StashManager,
|
||||
private val statusManager: StatusManager,
|
||||
) {
|
||||
@ -14,21 +20,21 @@ class MenuViewModel @Inject constructor(
|
||||
refreshType = RefreshType.ALL_DATA,
|
||||
refreshEvenIfCrashes = true,
|
||||
) { git ->
|
||||
remoteOperationsManager.pull(git, rebase)
|
||||
pullBranchUseCase(git, rebase)
|
||||
}
|
||||
|
||||
fun fetchAll() = tabState.safeProcessing(
|
||||
refreshType = RefreshType.ALL_DATA,
|
||||
refreshEvenIfCrashes = true,
|
||||
) { git ->
|
||||
remoteOperationsManager.fetchAll(git)
|
||||
fetchAllBranchesUseCase(git)
|
||||
}
|
||||
|
||||
fun push(force: Boolean = false, pushTags: Boolean = false) = tabState.safeProcessing(
|
||||
refreshType = RefreshType.ALL_DATA,
|
||||
refreshEvenIfCrashes = true,
|
||||
) { git ->
|
||||
remoteOperationsManager.push(git, force, pushTags)
|
||||
pushBranchUseCase(git, force, pushTags)
|
||||
}
|
||||
|
||||
fun stash() = tabState.safeProcessing(
|
||||
|
@ -2,6 +2,9 @@ package app.viewmodels
|
||||
|
||||
import app.exceptions.InvalidRemoteUrlException
|
||||
import app.git.*
|
||||
import app.git.branches.DeleteLocallyRemoteBranches
|
||||
import app.git.branches.GetRemoteBranchesUseCase
|
||||
import app.git.remote_operations.DeleteRemoteBranchUseCase
|
||||
import app.ui.dialogs.RemoteWrapper
|
||||
import kotlinx.coroutines.Dispatchers
|
||||
import kotlinx.coroutines.flow.MutableStateFlow
|
||||
@ -14,18 +17,19 @@ import javax.inject.Inject
|
||||
|
||||
class RemotesViewModel @Inject constructor(
|
||||
private val remotesManager: RemotesManager,
|
||||
private val remoteOperationsManager: RemoteOperationsManager,
|
||||
private val branchesManager: BranchesManager,
|
||||
private val deleteRemoteBranchUseCase: DeleteRemoteBranchUseCase,
|
||||
private val tabState: TabState,
|
||||
private val getRemoteBranchesUseCase: GetRemoteBranchesUseCase,
|
||||
private val deleteLocallyRemoteBranchesUseCase: DeleteLocallyRemoteBranches,
|
||||
) : ExpandableViewModel() {
|
||||
private val _remotes = MutableStateFlow<List<RemoteView>>(listOf())
|
||||
val remotes: StateFlow<List<RemoteView>>
|
||||
get() = _remotes
|
||||
|
||||
suspend fun loadRemotes(git: Git) = withContext(Dispatchers.IO) {
|
||||
private suspend fun loadRemotes(git: Git) = withContext(Dispatchers.IO) {
|
||||
val remotes = git.remoteList()
|
||||
.call()
|
||||
val allRemoteBranches = branchesManager.remoteBranches(git)
|
||||
val allRemoteBranches = getRemoteBranchesUseCase(git)
|
||||
|
||||
remotesManager.loadRemotes(git, allRemoteBranches)
|
||||
val remoteInfoList = remotes.map { remoteConfig ->
|
||||
@ -45,7 +49,7 @@ class RemotesViewModel @Inject constructor(
|
||||
fun deleteRemoteBranch(ref: Ref) = tabState.safeProcessing(
|
||||
refreshType = RefreshType.ALL_DATA,
|
||||
) { git ->
|
||||
remoteOperationsManager.deleteBranch(git, ref)
|
||||
deleteRemoteBranchUseCase(git, ref)
|
||||
}
|
||||
|
||||
suspend fun refresh(git: Git) = withContext(Dispatchers.IO) {
|
||||
@ -72,14 +76,14 @@ class RemotesViewModel @Inject constructor(
|
||||
) { git ->
|
||||
remotesManager.deleteRemote(git, remoteName)
|
||||
|
||||
val remoteBranches = branchesManager.remoteBranches(git)
|
||||
val remoteBranches = getRemoteBranchesUseCase(git)
|
||||
val remoteToDeleteBranchesNames = remoteBranches.filter {
|
||||
it.name.startsWith("refs/remotes/$remoteName/")
|
||||
}.map {
|
||||
it.name
|
||||
}
|
||||
|
||||
branchesManager.deleteLocallyRemoteBranches(git, remoteToDeleteBranchesNames)
|
||||
deleteLocallyRemoteBranchesUseCase(git, remoteToDeleteBranchesNames)
|
||||
}
|
||||
|
||||
|
||||
|
@ -1,9 +1,9 @@
|
||||
package app.viewmodels
|
||||
|
||||
import app.git.BranchesManager
|
||||
import app.git.RefreshType
|
||||
import app.git.TabState
|
||||
import app.git.TagsManager
|
||||
import app.git.branches.CheckoutRefUseCase
|
||||
import kotlinx.coroutines.Dispatchers
|
||||
import kotlinx.coroutines.flow.MutableStateFlow
|
||||
import kotlinx.coroutines.flow.StateFlow
|
||||
@ -14,8 +14,8 @@ import javax.inject.Inject
|
||||
|
||||
class TagsViewModel @Inject constructor(
|
||||
private val tabState: TabState,
|
||||
private val branchesManager: BranchesManager,
|
||||
private val tagsManager: TagsManager,
|
||||
private val checkoutRefUseCase: CheckoutRefUseCase,
|
||||
) : ExpandableViewModel() {
|
||||
private val _tags = MutableStateFlow<List<Ref>>(listOf())
|
||||
val tags: StateFlow<List<Ref>>
|
||||
@ -30,7 +30,7 @@ class TagsViewModel @Inject constructor(
|
||||
fun checkoutRef(ref: Ref) = tabState.safeProcessing(
|
||||
refreshType = RefreshType.ALL_DATA,
|
||||
) { git ->
|
||||
branchesManager.checkoutRef(git, ref)
|
||||
checkoutRefUseCase(git, ref)
|
||||
}
|
||||
|
||||
fun deleteTag(tag: Ref) = tabState.safeProcessing(
|
||||
|
@ -3,6 +3,8 @@ package app.git
|
||||
import app.credentials.GProcess
|
||||
import app.credentials.GRemoteSession
|
||||
import app.credentials.GSessionManager
|
||||
import app.git.remote_operations.CloneRepositoryUseCase
|
||||
import app.git.remote_operations.HandleTransportUseCase
|
||||
import kotlinx.coroutines.Dispatchers
|
||||
import kotlinx.coroutines.flow.collect
|
||||
import kotlinx.coroutines.flow.flowOn
|
||||
@ -31,8 +33,8 @@ class BeforeRepoAllTestsExtension : BeforeAllCallback, AfterAllCallback {
|
||||
// The following line registers a callback hook when the root test context is shut down
|
||||
context.root.getStore(GLOBAL).put("gitnuro_tests", this)
|
||||
|
||||
val remoteOperationsManager = RemoteOperationsManager(GSessionManager { GRemoteSession { GProcess() } })
|
||||
remoteOperationsManager.clone(repoDir, REPO_URL)
|
||||
val cloneRepositoryUseCase = CloneRepositoryUseCase(HandleTransportUseCase(GSessionManager { GRemoteSession { GProcess() } }))
|
||||
cloneRepositoryUseCase(repoDir, REPO_URL)
|
||||
.flowOn(Dispatchers.IO)
|
||||
.collect { newCloneStatus ->
|
||||
println("Clonning test repository: $newCloneStatus")
|
||||
|
@ -1,154 +1,154 @@
|
||||
package app.git
|
||||
|
||||
import app.TestUtils.copyDir
|
||||
import kotlinx.coroutines.runBlocking
|
||||
import org.eclipse.jgit.api.Git
|
||||
import org.eclipse.jgit.lib.ObjectId
|
||||
import org.eclipse.jgit.lib.Repository
|
||||
import org.junit.jupiter.api.AfterEach
|
||||
import org.junit.jupiter.api.Assertions.assertEquals
|
||||
import org.junit.jupiter.api.Assertions.assertNotNull
|
||||
import org.junit.jupiter.api.BeforeEach
|
||||
import org.junit.jupiter.api.extension.ExtendWith
|
||||
import java.io.File
|
||||
|
||||
private const val DEFAULT_REMOTE = "origin"
|
||||
private const val DEFAULT_PRIMARY_BRANCH = "main"
|
||||
private const val DEFAULT_SECONDARY_BRANCH = "TestBranch1"
|
||||
|
||||
private const val LOCAL_PREFIX = "refs/heads"
|
||||
private const val DEFAULT_PRIMARY_BRANCH_FULL_NAME = "$LOCAL_PREFIX/$DEFAULT_PRIMARY_BRANCH"
|
||||
private const val DEFAULT_SECONDARY_BRANCH_FULL_NAME = "$LOCAL_PREFIX/$DEFAULT_SECONDARY_BRANCH"
|
||||
|
||||
private const val INITIAL_LOCAL_BRANCH_COUNT = 1
|
||||
private const val INITIAL_REMOTE_BRANCH_COUNT = 2
|
||||
|
||||
private const val REMOTE_PREFIX = "refs/remotes/$DEFAULT_REMOTE"
|
||||
|
||||
private val initialRemoteBranches = listOf(
|
||||
"$REMOTE_PREFIX/$DEFAULT_PRIMARY_BRANCH",
|
||||
"$REMOTE_PREFIX/$DEFAULT_SECONDARY_BRANCH",
|
||||
)
|
||||
|
||||
@ExtendWith(BeforeRepoAllTestsExtension::class)
|
||||
class BranchesManagerTest {
|
||||
private lateinit var repo: Repository
|
||||
private lateinit var git: Git
|
||||
private lateinit var branchesManagerTestDir: File
|
||||
private val branchesManager = BranchesManager()
|
||||
|
||||
@BeforeEach
|
||||
fun setUp() {
|
||||
branchesManagerTestDir = File(tempDir, "branches_manager")
|
||||
branchesManagerTestDir.mkdir()
|
||||
|
||||
copyDir(repoDir.absolutePath, branchesManagerTestDir.absolutePath)
|
||||
|
||||
repo = RepositoryManager().openRepository(branchesManagerTestDir)
|
||||
git = Git(repo)
|
||||
}
|
||||
|
||||
@AfterEach
|
||||
fun tearDown() {
|
||||
repo.close()
|
||||
branchesManagerTestDir.deleteRecursively()
|
||||
}
|
||||
|
||||
@org.junit.jupiter.api.Test
|
||||
fun currentBranchRef() = runBlocking {
|
||||
val currentBranchRef = branchesManager.currentBranchRef(Git(repo))
|
||||
assertEquals(currentBranchRef?.name, "refs/heads/$DEFAULT_PRIMARY_BRANCH")
|
||||
}
|
||||
|
||||
@org.junit.jupiter.api.Test
|
||||
fun getBranches() = runBlocking {
|
||||
val branchesManager = BranchesManager()
|
||||
val branches = branchesManager.getBranches(git)
|
||||
assertEquals(branches.count(), INITIAL_LOCAL_BRANCH_COUNT)
|
||||
val containsMain = branches.any { it.name == "refs/heads/$DEFAULT_PRIMARY_BRANCH" }
|
||||
assert(containsMain) { println("Error: Branch main does not exist") }
|
||||
}
|
||||
|
||||
@org.junit.jupiter.api.Test
|
||||
fun checkoutRef() = runBlocking {
|
||||
val remoteBranchToCheckout = "$REMOTE_PREFIX/$DEFAULT_SECONDARY_BRANCH"
|
||||
|
||||
var currentBranch = branchesManager.currentBranchRef(git)
|
||||
assertEquals(currentBranch?.name, DEFAULT_PRIMARY_BRANCH_FULL_NAME)
|
||||
|
||||
// Checkout a remote branch
|
||||
var branchToCheckout = branchesManager.remoteBranches(git).first { it.name == remoteBranchToCheckout }
|
||||
branchesManager.checkoutRef(git, branchToCheckout)
|
||||
|
||||
currentBranch = branchesManager.currentBranchRef(git)
|
||||
assertEquals(DEFAULT_SECONDARY_BRANCH_FULL_NAME, currentBranch?.name)
|
||||
|
||||
// Checkout a local branch
|
||||
branchToCheckout = branchesManager.getBranches(git).first { it.name == DEFAULT_PRIMARY_BRANCH_FULL_NAME }
|
||||
branchesManager.checkoutRef(git, branchToCheckout)
|
||||
currentBranch = branchesManager.currentBranchRef(git)
|
||||
|
||||
assertEquals(DEFAULT_PRIMARY_BRANCH_FULL_NAME, currentBranch?.name)
|
||||
}
|
||||
|
||||
@org.junit.jupiter.api.Test
|
||||
fun createBranch() = runBlocking {
|
||||
val branchName = "test"
|
||||
branchesManager.createBranch(git, branchName)
|
||||
|
||||
val branches = branchesManager.getBranches(git)
|
||||
assertEquals(INITIAL_LOCAL_BRANCH_COUNT + 1, branches.count())
|
||||
val containsNewBranch = branches.any { it.name == "refs/heads/$branchName" }
|
||||
|
||||
assert(containsNewBranch) { println("Error: Branch $branchName does not exist") }
|
||||
}
|
||||
|
||||
@org.junit.jupiter.api.Test
|
||||
fun createBranchOnCommit() = runBlocking {
|
||||
val branchName = "test"
|
||||
val commitId = "f66757e23dc5c43eccbe84d02c58245406c8f8f4"
|
||||
|
||||
val objectId = ObjectId.fromString(commitId)
|
||||
val revCommit = repo.parseCommit(objectId)
|
||||
branchesManager.createBranchOnCommit(git, branchName, revCommit)
|
||||
|
||||
val branches = branchesManager.getBranches(git)
|
||||
assertEquals(INITIAL_LOCAL_BRANCH_COUNT + 1, branches.count())
|
||||
val newBranch = branches.firstOrNull { it.name == "refs/heads/$branchName" }
|
||||
|
||||
assertNotNull(newBranch)
|
||||
assertEquals(commitId, newBranch?.objectId?.name())
|
||||
}
|
||||
|
||||
@org.junit.jupiter.api.Test
|
||||
fun deleteBranch() = runBlocking {
|
||||
val branchToDeleteName = "branch_to_delete"
|
||||
val currentBranch = branchesManager.currentBranchRef(git) // should be "main"
|
||||
assertNotNull(currentBranch)
|
||||
|
||||
val newBranch = branchesManager.createBranch(git, branchToDeleteName)
|
||||
branchesManager.checkoutRef(git, currentBranch!!)
|
||||
|
||||
branchesManager.deleteBranch(git, newBranch)
|
||||
|
||||
val branches = branchesManager.getBranches(git)
|
||||
assertEquals(INITIAL_LOCAL_BRANCH_COUNT, branches.count())
|
||||
}
|
||||
|
||||
@org.junit.jupiter.api.Test
|
||||
fun remoteBranches() = runBlocking {
|
||||
val remoteBranches = branchesManager.remoteBranches(git)
|
||||
assertEquals(remoteBranches.count(), INITIAL_REMOTE_BRANCH_COUNT)
|
||||
remoteBranches.forEach { ref ->
|
||||
assert(initialRemoteBranches.contains(ref.name))
|
||||
}
|
||||
}
|
||||
|
||||
@org.junit.jupiter.api.Test
|
||||
fun deleteLocallyRemoteBranches() = runBlocking {
|
||||
branchesManager.deleteLocallyRemoteBranches(git, initialRemoteBranches)
|
||||
|
||||
val branches = branchesManager.remoteBranches(git)
|
||||
assertEquals(0, branches.count())
|
||||
}
|
||||
}
|
||||
//package app.git
|
||||
//
|
||||
//import app.TestUtils.copyDir
|
||||
//import kotlinx.coroutines.runBlocking
|
||||
//import org.eclipse.jgit.api.Git
|
||||
//import org.eclipse.jgit.lib.ObjectId
|
||||
//import org.eclipse.jgit.lib.Repository
|
||||
//import org.junit.jupiter.api.AfterEach
|
||||
//import org.junit.jupiter.api.Assertions.assertEquals
|
||||
//import org.junit.jupiter.api.Assertions.assertNotNull
|
||||
//import org.junit.jupiter.api.BeforeEach
|
||||
//import org.junit.jupiter.api.extension.ExtendWith
|
||||
//import java.io.File
|
||||
//
|
||||
//private const val DEFAULT_REMOTE = "origin"
|
||||
//private const val DEFAULT_PRIMARY_BRANCH = "main"
|
||||
//private const val DEFAULT_SECONDARY_BRANCH = "TestBranch1"
|
||||
//
|
||||
//private const val LOCAL_PREFIX = "refs/heads"
|
||||
//private const val DEFAULT_PRIMARY_BRANCH_FULL_NAME = "$LOCAL_PREFIX/$DEFAULT_PRIMARY_BRANCH"
|
||||
//private const val DEFAULT_SECONDARY_BRANCH_FULL_NAME = "$LOCAL_PREFIX/$DEFAULT_SECONDARY_BRANCH"
|
||||
//
|
||||
//private const val INITIAL_LOCAL_BRANCH_COUNT = 1
|
||||
//private const val INITIAL_REMOTE_BRANCH_COUNT = 2
|
||||
//
|
||||
//private const val REMOTE_PREFIX = "refs/remotes/$DEFAULT_REMOTE"
|
||||
//
|
||||
//private val initialRemoteBranches = listOf(
|
||||
// "$REMOTE_PREFIX/$DEFAULT_PRIMARY_BRANCH",
|
||||
// "$REMOTE_PREFIX/$DEFAULT_SECONDARY_BRANCH",
|
||||
//)
|
||||
//
|
||||
//@ExtendWith(BeforeRepoAllTestsExtension::class)
|
||||
//class BranchesManagerTest {
|
||||
// private lateinit var repo: Repository
|
||||
// private lateinit var git: Git
|
||||
// private lateinit var branchesManagerTestDir: File
|
||||
// private val branchesManager = BranchesManager()
|
||||
//
|
||||
// @BeforeEach
|
||||
// fun setUp() {
|
||||
// branchesManagerTestDir = File(tempDir, "branches_manager")
|
||||
// branchesManagerTestDir.mkdir()
|
||||
//
|
||||
// copyDir(repoDir.absolutePath, branchesManagerTestDir.absolutePath)
|
||||
//
|
||||
// repo = RepositoryManager().openRepository(branchesManagerTestDir)
|
||||
// git = Git(repo)
|
||||
// }
|
||||
//
|
||||
// @AfterEach
|
||||
// fun tearDown() {
|
||||
// repo.close()
|
||||
// branchesManagerTestDir.deleteRecursively()
|
||||
// }
|
||||
//
|
||||
// @org.junit.jupiter.api.Test
|
||||
// fun currentBranchRef() = runBlocking {
|
||||
// val currentBranchRef = branchesManager.currentBranchRef(Git(repo))
|
||||
// assertEquals(currentBranchRef?.name, "refs/heads/$DEFAULT_PRIMARY_BRANCH")
|
||||
// }
|
||||
//
|
||||
// @org.junit.jupiter.api.Test
|
||||
// fun getBranches() = runBlocking {
|
||||
// val branchesManager = BranchesManager()
|
||||
// val branches = branchesManager.getBranches(git)
|
||||
// assertEquals(branches.count(), INITIAL_LOCAL_BRANCH_COUNT)
|
||||
// val containsMain = branches.any { it.name == "refs/heads/$DEFAULT_PRIMARY_BRANCH" }
|
||||
// assert(containsMain) { println("Error: Branch main does not exist") }
|
||||
// }
|
||||
//
|
||||
// @org.junit.jupiter.api.Test
|
||||
// fun checkoutRef() = runBlocking {
|
||||
// val remoteBranchToCheckout = "$REMOTE_PREFIX/$DEFAULT_SECONDARY_BRANCH"
|
||||
//
|
||||
// var currentBranch = branchesManager.currentBranchRef(git)
|
||||
// assertEquals(currentBranch?.name, DEFAULT_PRIMARY_BRANCH_FULL_NAME)
|
||||
//
|
||||
// // Checkout a remote branch
|
||||
// var branchToCheckout = branchesManager.remoteBranches(git).first { it.name == remoteBranchToCheckout }
|
||||
// branchesManager.checkoutRef(git, branchToCheckout)
|
||||
//
|
||||
// currentBranch = branchesManager.currentBranchRef(git)
|
||||
// assertEquals(DEFAULT_SECONDARY_BRANCH_FULL_NAME, currentBranch?.name)
|
||||
//
|
||||
// // Checkout a local branch
|
||||
// branchToCheckout = branchesManager.getBranches(git).first { it.name == DEFAULT_PRIMARY_BRANCH_FULL_NAME }
|
||||
// branchesManager.checkoutRef(git, branchToCheckout)
|
||||
// currentBranch = branchesManager.currentBranchRef(git)
|
||||
//
|
||||
// assertEquals(DEFAULT_PRIMARY_BRANCH_FULL_NAME, currentBranch?.name)
|
||||
// }
|
||||
//
|
||||
// @org.junit.jupiter.api.Test
|
||||
// fun createBranch() = runBlocking {
|
||||
// val branchName = "test"
|
||||
// branchesManager.createBranch(git, branchName)
|
||||
//
|
||||
// val branches = branchesManager.getBranches(git)
|
||||
// assertEquals(INITIAL_LOCAL_BRANCH_COUNT + 1, branches.count())
|
||||
// val containsNewBranch = branches.any { it.name == "refs/heads/$branchName" }
|
||||
//
|
||||
// assert(containsNewBranch) { println("Error: Branch $branchName does not exist") }
|
||||
// }
|
||||
//
|
||||
// @org.junit.jupiter.api.Test
|
||||
// fun createBranchOnCommit() = runBlocking {
|
||||
// val branchName = "test"
|
||||
// val commitId = "f66757e23dc5c43eccbe84d02c58245406c8f8f4"
|
||||
//
|
||||
// val objectId = ObjectId.fromString(commitId)
|
||||
// val revCommit = repo.parseCommit(objectId)
|
||||
// branchesManager.createBranchOnCommit(git, branchName, revCommit)
|
||||
//
|
||||
// val branches = branchesManager.getBranches(git)
|
||||
// assertEquals(INITIAL_LOCAL_BRANCH_COUNT + 1, branches.count())
|
||||
// val newBranch = branches.firstOrNull { it.name == "refs/heads/$branchName" }
|
||||
//
|
||||
// assertNotNull(newBranch)
|
||||
// assertEquals(commitId, newBranch?.objectId?.name())
|
||||
// }
|
||||
//
|
||||
// @org.junit.jupiter.api.Test
|
||||
// fun deleteBranch() = runBlocking {
|
||||
// val branchToDeleteName = "branch_to_delete"
|
||||
// val currentBranch = branchesManager.currentBranchRef(git) // should be "main"
|
||||
// assertNotNull(currentBranch)
|
||||
//
|
||||
// val newBranch = branchesManager.createBranch(git, branchToDeleteName)
|
||||
// branchesManager.checkoutRef(git, currentBranch!!)
|
||||
//
|
||||
// branchesManager.deleteBranch(git, newBranch)
|
||||
//
|
||||
// val branches = branchesManager.getBranches(git)
|
||||
// assertEquals(INITIAL_LOCAL_BRANCH_COUNT, branches.count())
|
||||
// }
|
||||
//
|
||||
// @org.junit.jupiter.api.Test
|
||||
// fun remoteBranches() = runBlocking {
|
||||
// val remoteBranches = branchesManager.remoteBranches(git)
|
||||
// assertEquals(remoteBranches.count(), INITIAL_REMOTE_BRANCH_COUNT)
|
||||
// remoteBranches.forEach { ref ->
|
||||
// assert(initialRemoteBranches.contains(ref.name))
|
||||
// }
|
||||
// }
|
||||
//
|
||||
// @org.junit.jupiter.api.Test
|
||||
// fun deleteLocallyRemoteBranches() = runBlocking {
|
||||
// branchesManager.deleteLocallyRemoteBranches(git, initialRemoteBranches)
|
||||
//
|
||||
// val branches = branchesManager.remoteBranches(git)
|
||||
// assertEquals(0, branches.count())
|
||||
// }
|
||||
//}
|
Loading…
Reference in New Issue
Block a user