Removed repository & remotes managers in favor of use cases

This commit is contained in:
Abdelilah El Aissaoui 2022-09-03 17:15:44 +02:00
parent 32b2c1df11
commit 7148e59eeb
11 changed files with 123 additions and 80 deletions

View File

@ -1,48 +0,0 @@
package app.git
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.withContext
import org.eclipse.jgit.api.Git
import org.eclipse.jgit.api.RemoteSetUrlCommand
import org.eclipse.jgit.lib.Ref
import org.eclipse.jgit.transport.RemoteConfig
import org.eclipse.jgit.transport.URIish
import javax.inject.Inject
class RemotesManager @Inject constructor() {
suspend fun loadRemotes(git: Git, allRemoteBranches: List<Ref>) = withContext(Dispatchers.IO) {
val remotes = git.remoteList()
.call()
return@withContext remotes.map { remoteConfig ->
val remoteBranches = allRemoteBranches.filter { branch ->
branch.name.startsWith("refs/remotes/${remoteConfig.name}")
}
RemoteInfo(remoteConfig, remoteBranches)
}
}
suspend fun deleteRemote(git: Git, remoteName: String) = withContext(Dispatchers.IO) {
git.remoteRemove()
.setRemoteName(remoteName)
.call()
}
suspend fun addRemote(git: Git, remoteName: String, fetchUri: String) = withContext(Dispatchers.IO) {
git.remoteAdd()
.setName(remoteName)
.setUri(URIish(fetchUri))
.call()
}
suspend fun updateRemote(git: Git, remoteName: String, uri: String, uriType: RemoteSetUrlCommand.UriType) =
withContext(Dispatchers.IO) {
git.remoteSetUrl()
.setRemoteName(remoteName)
.setRemoteUri(URIish(uri))
.setUriType(uriType)
.call()
}
}
data class RemoteInfo(val remoteConfig: RemoteConfig, val branchesList: List<Ref>)

View File

@ -5,7 +5,7 @@ import kotlinx.coroutines.withContext
import org.eclipse.jgit.api.Git
import javax.inject.Inject
class DeleteLocallyRemoteBranches @Inject constructor() {
class DeleteLocallyRemoteBranchesUseCase @Inject constructor() {
suspend operator fun invoke(git: Git, branches: List<String>): List<String> = withContext(Dispatchers.IO) {
git
.branchDelete()

View File

@ -0,0 +1,16 @@
package app.git.remotes
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.withContext
import org.eclipse.jgit.api.Git
import org.eclipse.jgit.transport.URIish
import javax.inject.Inject
class AddRemoteUseCase @Inject constructor() {
suspend operator fun invoke(git: Git, remoteName: String, fetchUri: String): Unit = withContext(Dispatchers.IO) {
git.remoteAdd()
.setName(remoteName)
.setUri(URIish(fetchUri))
.call()
}
}

View File

@ -0,0 +1,14 @@
package app.git.remotes
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.withContext
import org.eclipse.jgit.api.Git
import javax.inject.Inject
class DeleteRemoteUseCase @Inject constructor() {
suspend operator fun invoke(git: Git, remoteName: String): Unit = withContext(Dispatchers.IO) {
git.remoteRemove()
.setRemoteName(remoteName)
.call()
}
}

View File

@ -0,0 +1,22 @@
package app.git.remotes
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 GetRemotesUseCase @Inject constructor() {
suspend operator fun invoke(git: Git, allRemoteBranches: List<Ref>): List<RemoteInfo> =
withContext(Dispatchers.IO) {
val remotes = git.remoteList()
.call()
return@withContext remotes.map { remoteConfig ->
val remoteBranches = allRemoteBranches.filter { branch ->
branch.name.startsWith("refs/remotes/${remoteConfig.name}")
}
RemoteInfo(remoteConfig, remoteBranches)
}
}
}

View File

@ -0,0 +1,6 @@
package app.git.remotes
import org.eclipse.jgit.lib.Ref
import org.eclipse.jgit.transport.RemoteConfig
data class RemoteInfo(val remoteConfig: RemoteConfig, val branchesList: List<Ref>)

View File

@ -0,0 +1,19 @@
package app.git.remotes
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.withContext
import org.eclipse.jgit.api.Git
import org.eclipse.jgit.api.RemoteSetUrlCommand
import org.eclipse.jgit.transport.URIish
import javax.inject.Inject
class UpdateRemoteUseCase @Inject constructor() {
suspend operator fun invoke(git: Git, remoteName: String, uri: String, uriType: RemoteSetUrlCommand.UriType): Unit =
withContext(Dispatchers.IO) {
git.remoteSetUrl()
.setRemoteName(remoteName)
.setRemoteUri(URIish(uri))
.setUriType(uriType)
.call()
}
}

View File

@ -0,0 +1,18 @@
package app.git.repository
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.withContext
import org.eclipse.jgit.api.Git
import java.io.File
import javax.inject.Inject
private const val INITIAL_BRANCH_NAME = "main"
class InitLocalRepositoryUseCase @Inject constructor() {
suspend operator fun invoke(repoDir: File): Unit = withContext(Dispatchers.IO) {
Git.init()
.setInitialBranch(INITIAL_BRANCH_NAME)
.setDirectory(repoDir)
.call()
}
}

View File

@ -1,21 +1,14 @@
package app.git
package app.git.repository
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.withContext
import org.eclipse.jgit.api.Git
import org.eclipse.jgit.lib.Repository
import org.eclipse.jgit.storage.file.FileRepositoryBuilder
import java.io.File
import javax.inject.Inject
private const val INITIAL_BRANCH_NAME = "main"
class RepositoryManager @Inject constructor() {
suspend fun getRepositoryState(git: Git) = withContext(Dispatchers.IO) {
return@withContext git.repository.repositoryState
}
fun openRepository(directory: File): Repository {
class OpenRepositoryUseCase @Inject constructor() {
suspend operator fun invoke(directory: File): Repository = withContext(Dispatchers.IO) {
val gitDirectory = if (directory.name == ".git") {
directory
} else {
@ -27,16 +20,9 @@ class RepositoryManager @Inject constructor() {
}
val builder = FileRepositoryBuilder()
return builder.setGitDir(gitDirectory)
return@withContext builder.setGitDir(gitDirectory)
.readEnvironment() // scan environment GIT_* variables
.findGitDir() // scan up the file system tree
.build()
}
suspend fun initLocalRepo(repoDir: File): Unit = withContext(Dispatchers.IO) {
Git.init()
.setInitialBranch(INITIAL_BRANCH_NAME)
.setDirectory(repoDir)
.call()
}
}

View File

@ -2,9 +2,10 @@ package app.viewmodels
import app.exceptions.InvalidRemoteUrlException
import app.git.*
import app.git.branches.DeleteLocallyRemoteBranches
import app.git.branches.DeleteLocallyRemoteBranchesUseCase
import app.git.branches.GetRemoteBranchesUseCase
import app.git.remote_operations.DeleteRemoteBranchUseCase
import app.git.remotes.*
import app.ui.dialogs.RemoteWrapper
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.flow.MutableStateFlow
@ -16,11 +17,14 @@ import org.eclipse.jgit.lib.Ref
import javax.inject.Inject
class RemotesViewModel @Inject constructor(
private val remotesManager: RemotesManager,
private val deleteRemoteBranchUseCase: DeleteRemoteBranchUseCase,
private val tabState: TabState,
private val deleteRemoteBranchUseCase: DeleteRemoteBranchUseCase,
private val getRemoteBranchesUseCase: GetRemoteBranchesUseCase,
private val deleteLocallyRemoteBranchesUseCase: DeleteLocallyRemoteBranches,
private val getRemotesUseCase: GetRemotesUseCase,
private val deleteRemoteUseCase: DeleteRemoteUseCase,
private val addRemoteUseCase: AddRemoteUseCase,
private val updateRemoteUseCase: UpdateRemoteUseCase,
private val deleteLocallyRemoteBranchesUseCase: DeleteLocallyRemoteBranchesUseCase
) : ExpandableViewModel() {
private val _remotes = MutableStateFlow<List<RemoteView>>(listOf())
val remotes: StateFlow<List<RemoteView>>
@ -31,7 +35,8 @@ class RemotesViewModel @Inject constructor(
.call()
val allRemoteBranches = getRemoteBranchesUseCase(git)
remotesManager.loadRemotes(git, allRemoteBranches)
getRemotesUseCase(git, allRemoteBranches)
val remoteInfoList = remotes.map { remoteConfig ->
val remoteBranches = allRemoteBranches.filter { branch ->
branch.name.startsWith("refs/remotes/${remoteConfig.name}")
@ -74,7 +79,7 @@ class RemotesViewModel @Inject constructor(
refreshType = if (isNew) RefreshType.REMOTES else RefreshType.ALL_DATA,
showError = true,
) { git ->
remotesManager.deleteRemote(git, remoteName)
deleteRemoteUseCase(git, remoteName)
val remoteBranches = getRemoteBranchesUseCase(git)
val remoteToDeleteBranchesNames = remoteBranches.filter {
@ -99,7 +104,7 @@ class RemotesViewModel @Inject constructor(
throw InvalidRemoteUrlException("Invalid empty push URI")
}
remotesManager.addRemote(git, selectedRemoteConfig.remoteName, selectedRemoteConfig.fetchUri)
addRemoteUseCase(git, selectedRemoteConfig.remoteName, selectedRemoteConfig.fetchUri)
updateRemote(selectedRemoteConfig) // Sets both, fetch and push uri
}
@ -117,14 +122,14 @@ class RemotesViewModel @Inject constructor(
throw InvalidRemoteUrlException("Invalid empty push URI")
}
remotesManager.updateRemote(
updateRemoteUseCase(
git = git,
remoteName = selectedRemoteConfig.remoteName,
uri = selectedRemoteConfig.fetchUri,
uriType = RemoteSetUrlCommand.UriType.FETCH
)
remotesManager.updateRemote(
updateRemoteUseCase(
git = git,
remoteName = selectedRemoteConfig.remoteName,
uri = selectedRemoteConfig.pushUri,

View File

@ -5,6 +5,9 @@ import app.ErrorsManager
import app.credentials.CredentialsState
import app.credentials.CredentialsStateManager
import app.git.*
import app.git.repository.GetRepositoryStateUseCase
import app.git.repository.InitLocalRepositoryUseCase
import app.git.repository.OpenRepositoryUseCase
import app.logging.printLog
import app.models.AuthorInfoSimple
import app.newErrorNow
@ -43,11 +46,13 @@ class TabViewModel @Inject constructor(
val stashesViewModel: StashesViewModel,
val commitChangesViewModel: CommitChangesViewModel,
val cloneViewModel: CloneViewModel,
private val getRepositoryStateUseCase: GetRepositoryStateUseCase,
private val initLocalRepositoryUseCase: InitLocalRepositoryUseCase,
private val openRepositoryUseCase: OpenRepositoryUseCase,
private val diffViewModelProvider: Provider<DiffViewModel>,
private val rebaseInteractiveViewModelProvider: Provider<RebaseInteractiveViewModel>,
private val historyViewModelProvider: Provider<HistoryViewModel>,
private val authorViewModelProvider: Provider<AuthorViewModel>,
private val repositoryManager: RepositoryManager,
private val tabState: TabState,
val appStateManager: AppStateManager,
private val fileChangesWatcher: FileChangesWatcher,
@ -167,7 +172,7 @@ class TabViewModel @Inject constructor(
_repositorySelectionStatus.value = RepositorySelectionStatus.Opening(directory.absolutePath)
val repository: Repository = repositoryManager.openRepository(directory)
val repository: Repository = openRepositoryUseCase(directory)
try {
repository.workTree // test if repository is valid
@ -188,7 +193,7 @@ class TabViewModel @Inject constructor(
}
private suspend fun loadRepositoryState(git: Git) = withContext(Dispatchers.IO) {
val newRepoState = repositoryManager.getRepositoryState(git)
val newRepoState = getRepositoryStateUseCase(git)
printLog(TAG, "Refreshing repository state $newRepoState")
_repositoryState.value = newRepoState
@ -364,7 +369,7 @@ class TabViewModel @Inject constructor(
showError = true,
) {
val repoDir = File(dir)
repositoryManager.initLocalRepo(repoDir)
initLocalRepositoryUseCase(repoDir)
openRepository(repoDir)
}