Compare commits
7 Commits
Author | SHA1 | Date | |
---|---|---|---|
|
edcefd7a38 | ||
|
01b0827057 | ||
|
db1467c354 | ||
|
07e98dae10 | ||
|
644f33ff2c | ||
|
3128341b93 | ||
|
1ef596ad3c |
@ -12,17 +12,17 @@ plugins {
|
|||||||
kotlin("jvm") version "2.0.0"
|
kotlin("jvm") version "2.0.0"
|
||||||
kotlin("plugin.serialization") version "2.0.20"
|
kotlin("plugin.serialization") version "2.0.20"
|
||||||
id("com.google.devtools.ksp") version "2.0.20-1.0.24"
|
id("com.google.devtools.ksp") version "2.0.20-1.0.24"
|
||||||
id("org.jetbrains.compose") version "1.7.0-beta02"
|
id("org.jetbrains.compose") version "1.7.0"
|
||||||
id("org.jetbrains.kotlin.plugin.compose") version "2.0.20"
|
id("org.jetbrains.kotlin.plugin.compose") version "2.0.20"
|
||||||
}
|
}
|
||||||
|
|
||||||
// Remember to update Constants.APP_VERSION when changing this version
|
// Remember to update Constants.APP_VERSION when changing this version
|
||||||
val projectVersion = "1.4.0"
|
val projectVersion = "1.4.1"
|
||||||
|
|
||||||
val projectName = "Gitnuro"
|
val projectName = "Gitnuro"
|
||||||
|
|
||||||
// Required for JPackage, as it doesn't accept additional suffixes after the version.
|
// Required for JPackage, as it doesn't accept additional suffixes after the version.
|
||||||
val projectVersionSimplified = "1.4.0"
|
val projectVersionSimplified = "1.4.1"
|
||||||
|
|
||||||
val rustGeneratedSource = "${layout.buildDirectory.get()}/generated/source/uniffi/main/com/jetpackduba/gitnuro/java"
|
val rustGeneratedSource = "${layout.buildDirectory.get()}/generated/source/uniffi/main/com/jetpackduba/gitnuro/java"
|
||||||
|
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
{
|
{
|
||||||
"appVersion": "1.3.1",
|
"appVersion": "1.4.0",
|
||||||
"appCode": 11,
|
"appCode": 14,
|
||||||
"downloadUrl": "https://github.com/JetpackDuba/Gitnuro/releases/tag/v1.3.1"
|
"downloadUrl": "https://github.com/JetpackDuba/Gitnuro/releases/tag/v1.4.0"
|
||||||
}
|
}
|
||||||
|
@ -22,8 +22,8 @@ object AppConstants {
|
|||||||
const val APP_NAME = "Gitnuro"
|
const val APP_NAME = "Gitnuro"
|
||||||
const val APP_DESCRIPTION =
|
const val APP_DESCRIPTION =
|
||||||
"Gitnuro is a Git client that allows you to manage multiple repositories with a modern experience and live visual representation of your repositories' state."
|
"Gitnuro is a Git client that allows you to manage multiple repositories with a modern experience and live visual representation of your repositories' state."
|
||||||
const val APP_VERSION = "1.4.0"
|
const val APP_VERSION = "1.4.1"
|
||||||
const val APP_VERSION_CODE = 14
|
const val APP_VERSION_CODE = 15
|
||||||
const val VERSION_CHECK_URL = "https://raw.githubusercontent.com/JetpackDuba/Gitnuro/main/latest.json"
|
const val VERSION_CHECK_URL = "https://raw.githubusercontent.com/JetpackDuba/Gitnuro/main/latest.json"
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -2,6 +2,7 @@ package com.jetpackduba.gitnuro.credentials
|
|||||||
|
|
||||||
import com.jetpackduba.gitnuro.exceptions.NotSupportedHelper
|
import com.jetpackduba.gitnuro.exceptions.NotSupportedHelper
|
||||||
import com.jetpackduba.gitnuro.git.remote_operations.CredentialsCache
|
import com.jetpackduba.gitnuro.git.remote_operations.CredentialsCache
|
||||||
|
import com.jetpackduba.gitnuro.logging.printError
|
||||||
import com.jetpackduba.gitnuro.logging.printLog
|
import com.jetpackduba.gitnuro.logging.printLog
|
||||||
import com.jetpackduba.gitnuro.managers.IShellManager
|
import com.jetpackduba.gitnuro.managers.IShellManager
|
||||||
import com.jetpackduba.gitnuro.repositories.AppSettingsRepository
|
import com.jetpackduba.gitnuro.repositories.AppSettingsRepository
|
||||||
@ -259,7 +260,8 @@ class HttpCredentialsProvider @AssistedInject constructor(
|
|||||||
val credentialHelperPath = uriSpecificCredentialHelper ?: genericCredentialHelper ?: return null
|
val credentialHelperPath = uriSpecificCredentialHelper ?: genericCredentialHelper ?: return null
|
||||||
|
|
||||||
if (credentialHelperPath == "cache" || credentialHelperPath == "store") {
|
if (credentialHelperPath == "cache" || credentialHelperPath == "store") {
|
||||||
throw NotSupportedHelper("Invalid credentials helper: \"$credentialHelperPath\" is not yet supported")
|
printError(TAG, "Invalid credentials helper: \"$credentialHelperPath\" is not yet supported")
|
||||||
|
return null
|
||||||
}
|
}
|
||||||
|
|
||||||
// TODO Try to use "git-credential-manager-core" when "manager-core" is detected. Works for linux but requires testing for mac/windows
|
// TODO Try to use "git-credential-manager-core" when "manager-core" is detected. Works for linux but requires testing for mac/windows
|
||||||
|
@ -1,11 +1,6 @@
|
|||||||
package com.jetpackduba.gitnuro.exceptions
|
package com.jetpackduba.gitnuro.exceptions
|
||||||
|
|
||||||
class WatcherInitException(
|
fun codeToMessage(code: Int): String {
|
||||||
code: Int,
|
|
||||||
message: String = codeToMessage(code),
|
|
||||||
) : GitnuroException(message)
|
|
||||||
|
|
||||||
private fun codeToMessage(code: Int): String {
|
|
||||||
return when (code) {
|
return when (code) {
|
||||||
1 /*is WatcherInitException.Generic*/, 2 /*is WatcherInitException.Io*/ -> "Could not watch directory. Check if it exists and you have read permissions."
|
1 /*is WatcherInitException.Generic*/, 2 /*is WatcherInitException.Io*/ -> "Could not watch directory. Check if it exists and you have read permissions."
|
||||||
3 /*is WatcherInitException.PathNotFound*/ -> "Path not found, check if your repository still exists"
|
3 /*is WatcherInitException.PathNotFound*/ -> "Path not found, check if your repository still exists"
|
||||||
|
@ -3,7 +3,6 @@ package com.jetpackduba.gitnuro.git
|
|||||||
import FileWatcher
|
import FileWatcher
|
||||||
import WatchDirectoryNotifier
|
import WatchDirectoryNotifier
|
||||||
import com.jetpackduba.gitnuro.di.TabScope
|
import com.jetpackduba.gitnuro.di.TabScope
|
||||||
import com.jetpackduba.gitnuro.exceptions.WatcherInitException
|
|
||||||
import com.jetpackduba.gitnuro.git.workspace.GetIgnoreRulesUseCase
|
import com.jetpackduba.gitnuro.git.workspace.GetIgnoreRulesUseCase
|
||||||
import com.jetpackduba.gitnuro.system.systemSeparator
|
import com.jetpackduba.gitnuro.system.systemSeparator
|
||||||
import kotlinx.coroutines.CoroutineScope
|
import kotlinx.coroutines.CoroutineScope
|
||||||
@ -25,8 +24,8 @@ class FileChangesWatcher @Inject constructor(
|
|||||||
private val getIgnoreRulesUseCase: GetIgnoreRulesUseCase,
|
private val getIgnoreRulesUseCase: GetIgnoreRulesUseCase,
|
||||||
private val tabScope: CoroutineScope,
|
private val tabScope: CoroutineScope,
|
||||||
) : AutoCloseable {
|
) : AutoCloseable {
|
||||||
private val _changesNotifier = MutableSharedFlow<Boolean>()
|
private val _changesNotifier = MutableSharedFlow<WatcherEvent>()
|
||||||
val changesNotifier: SharedFlow<Boolean> = _changesNotifier
|
val changesNotifier: SharedFlow<WatcherEvent> = _changesNotifier
|
||||||
private val fileWatcher = FileWatcher.new()
|
private val fileWatcher = FileWatcher.new()
|
||||||
private var shouldKeepLooping = true
|
private var shouldKeepLooping = true
|
||||||
|
|
||||||
@ -71,14 +70,16 @@ class FileChangesWatcher @Inject constructor(
|
|||||||
|
|
||||||
if (!areAllPathsIgnored) {
|
if (!areAllPathsIgnored) {
|
||||||
println("Emitting changes $hasGitIgnoreChanged")
|
println("Emitting changes $hasGitIgnoreChanged")
|
||||||
_changesNotifier.emit(hasGitDirChanged)
|
_changesNotifier.emit(WatcherEvent.RepositoryChanged(hasGitDirChanged))
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun onError(code: Int) {
|
override fun onError(code: Int) {
|
||||||
throw WatcherInitException(code)
|
tabScope.launch {
|
||||||
|
_changesNotifier.emit(WatcherEvent.WatchInitError(code))
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -91,3 +92,8 @@ class FileChangesWatcher @Inject constructor(
|
|||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
sealed interface WatcherEvent {
|
||||||
|
data class RepositoryChanged(val hasGitDirChanged: Boolean) : WatcherEvent
|
||||||
|
data class WatchInitError(val code: Int) : WatcherEvent
|
||||||
|
}
|
@ -15,9 +15,12 @@ class SaveAuthorUseCase @Inject constructor() {
|
|||||||
repoConfig.load()
|
repoConfig.load()
|
||||||
|
|
||||||
if (globalConfig is FileBasedConfig) {
|
if (globalConfig is FileBasedConfig) {
|
||||||
globalConfig.setStringProperty("user", null, "name", newAuthorInfo.globalName)
|
val canonicalConfigFile = globalConfig.file.canonicalFile
|
||||||
globalConfig.setStringProperty("user", null, "email", newAuthorInfo.globalEmail)
|
val globalRepoConfig = FileBasedConfig(canonicalConfigFile, git.repository.fs)
|
||||||
globalConfig.save()
|
|
||||||
|
globalRepoConfig.setStringProperty("user", null, "name", newAuthorInfo.globalName)
|
||||||
|
globalRepoConfig.setStringProperty("user", null, "email", newAuthorInfo.globalEmail)
|
||||||
|
globalRepoConfig.save()
|
||||||
}
|
}
|
||||||
|
|
||||||
config.setStringProperty("user", null, "name", newAuthorInfo.name)
|
config.setStringProperty("user", null, "name", newAuthorInfo.name)
|
||||||
|
@ -89,7 +89,6 @@ fun UncommittedChanges(
|
|||||||
val doCommit = {
|
val doCommit = {
|
||||||
statusViewModel.commit(commitMessage)
|
statusViewModel.commit(commitMessage)
|
||||||
onStagedDiffEntrySelected(null)
|
onStagedDiffEntrySelected(null)
|
||||||
setCommitMessage("")
|
|
||||||
}
|
}
|
||||||
|
|
||||||
val canCommit = commitMessage.isNotEmpty() && stageStateUi.hasStagedFiles
|
val canCommit = commitMessage.isNotEmpty() && stageStateUi.hasStagedFiles
|
||||||
|
@ -32,7 +32,9 @@ fun ErrorDialog(
|
|||||||
val clipboard = LocalClipboardManager.current
|
val clipboard = LocalClipboardManager.current
|
||||||
var showStackTrace by remember { mutableStateOf(false) }
|
var showStackTrace by remember { mutableStateOf(false) }
|
||||||
|
|
||||||
MaterialDialog {
|
MaterialDialog (
|
||||||
|
onCloseRequested = onAccept,
|
||||||
|
) {
|
||||||
Column(
|
Column(
|
||||||
modifier = Modifier
|
modifier = Modifier
|
||||||
.width(580.dp)
|
.width(580.dp)
|
||||||
|
@ -2,7 +2,7 @@ package com.jetpackduba.gitnuro.viewmodels
|
|||||||
|
|
||||||
import com.jetpackduba.gitnuro.SharedRepositoryStateManager
|
import com.jetpackduba.gitnuro.SharedRepositoryStateManager
|
||||||
import com.jetpackduba.gitnuro.TaskType
|
import com.jetpackduba.gitnuro.TaskType
|
||||||
import com.jetpackduba.gitnuro.exceptions.WatcherInitException
|
import com.jetpackduba.gitnuro.exceptions.codeToMessage
|
||||||
import com.jetpackduba.gitnuro.git.*
|
import com.jetpackduba.gitnuro.git.*
|
||||||
import com.jetpackduba.gitnuro.git.branches.CreateBranchUseCase
|
import com.jetpackduba.gitnuro.git.branches.CreateBranchUseCase
|
||||||
import com.jetpackduba.gitnuro.git.rebase.RebaseInteractiveState
|
import com.jetpackduba.gitnuro.git.rebase.RebaseInteractiveState
|
||||||
@ -110,6 +110,8 @@ class RepositoryOpenViewModel @Inject constructor(
|
|||||||
var authorViewModel: AuthorViewModel? = null
|
var authorViewModel: AuthorViewModel? = null
|
||||||
private set
|
private set
|
||||||
|
|
||||||
|
private var hasGitDirChanged = false
|
||||||
|
|
||||||
init {
|
init {
|
||||||
tabScope.run {
|
tabScope.run {
|
||||||
launch {
|
launch {
|
||||||
@ -119,7 +121,7 @@ class RepositoryOpenViewModel @Inject constructor(
|
|||||||
}
|
}
|
||||||
|
|
||||||
launch {
|
launch {
|
||||||
watchRepositoryChanges(tabState.git)
|
watchRepositoryChanges()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -158,55 +160,53 @@ class RepositoryOpenViewModel @Inject constructor(
|
|||||||
* the app by constantly running "git status" or even full refreshes.
|
* the app by constantly running "git status" or even full refreshes.
|
||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
private suspend fun watchRepositoryChanges(git: Git) = tabScope.launch(Dispatchers.IO) {
|
private suspend fun watchRepositoryChanges() = tabScope.launch(Dispatchers.IO) {
|
||||||
var hasGitDirChanged = false
|
|
||||||
|
|
||||||
launch {
|
launch {
|
||||||
fileChangesWatcher.changesNotifier.collect { latestUpdateChangedGitDir ->
|
fileChangesWatcher.changesNotifier.collect { watcherEvent ->
|
||||||
val isOperationRunning = tabState.operationRunning
|
when (watcherEvent) {
|
||||||
|
is WatcherEvent.RepositoryChanged -> repositoryChanged(watcherEvent.hasGitDirChanged)
|
||||||
|
is WatcherEvent.WatchInitError -> {
|
||||||
|
val message = codeToMessage(watcherEvent.code)
|
||||||
|
errorsManager.addError(
|
||||||
|
newErrorNow(
|
||||||
|
exception = Exception(message),
|
||||||
|
taskType = TaskType.CHANGES_DETECTION,
|
||||||
|
),
|
||||||
|
)
|
||||||
|
|
||||||
if (!isOperationRunning) { // Only update if there isn't any process running
|
|
||||||
printDebug(TAG, "Detected changes in the repository's directory")
|
|
||||||
|
|
||||||
val currentTimeMillis = System.currentTimeMillis()
|
|
||||||
|
|
||||||
if (
|
|
||||||
latestUpdateChangedGitDir &&
|
|
||||||
currentTimeMillis - tabState.lastOperation < MIN_TIME_AFTER_GIT_OPERATION
|
|
||||||
) {
|
|
||||||
printDebug(TAG, "Git operation was executed recently, ignoring file system change")
|
|
||||||
return@collect
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (latestUpdateChangedGitDir) {
|
|
||||||
hasGitDirChanged = true
|
|
||||||
}
|
|
||||||
|
|
||||||
if (isActive) {
|
|
||||||
updateApp(hasGitDirChanged)
|
|
||||||
}
|
|
||||||
|
|
||||||
hasGitDirChanged = false
|
|
||||||
} else {
|
|
||||||
printDebug(TAG, "Ignored file events during operation")
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
try {
|
private suspend fun CoroutineScope.repositoryChanged(hasGitDirChanged: Boolean) {
|
||||||
fileChangesWatcher.watchDirectoryPath(
|
val isOperationRunning = tabState.operationRunning
|
||||||
repository = git.repository,
|
|
||||||
)
|
if (!isOperationRunning) { // Only update if there isn't any process running
|
||||||
} catch (ex: WatcherInitException) {
|
printDebug(TAG, "Detected changes in the repository's directory")
|
||||||
val message = ex.message
|
|
||||||
if (message != null) {
|
val currentTimeMillis = System.currentTimeMillis()
|
||||||
errorsManager.addError(
|
|
||||||
newErrorNow(
|
if (
|
||||||
exception = ex,
|
hasGitDirChanged &&
|
||||||
taskType = TaskType.CHANGES_DETECTION,
|
currentTimeMillis - tabState.lastOperation < MIN_TIME_AFTER_GIT_OPERATION
|
||||||
),
|
) {
|
||||||
)
|
printDebug(TAG, "Git operation was executed recently, ignoring file system change")
|
||||||
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (hasGitDirChanged) {
|
||||||
|
this@RepositoryOpenViewModel.hasGitDirChanged = true
|
||||||
|
}
|
||||||
|
|
||||||
|
if (isActive) {
|
||||||
|
updateApp(hasGitDirChanged)
|
||||||
|
}
|
||||||
|
|
||||||
|
this@RepositoryOpenViewModel.hasGitDirChanged = false
|
||||||
|
} else {
|
||||||
|
printDebug(TAG, "Ignored file events during operation")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -395,7 +395,9 @@ class StatusViewModel @Inject constructor(
|
|||||||
val personIdent = getPersonIdent(git)
|
val personIdent = getPersonIdent(git)
|
||||||
|
|
||||||
doCommitUseCase(git, commitMessage, amend, personIdent)
|
doCommitUseCase(git, commitMessage, amend, personIdent)
|
||||||
|
|
||||||
updateCommitMessage("")
|
updateCommitMessage("")
|
||||||
|
_commitMessageChangesFlow.emit("")
|
||||||
_isAmend.value = false
|
_isAmend.value = false
|
||||||
|
|
||||||
positiveNotification(if (isAmend.value) "Commit amended" else "New commit created")
|
positiveNotification(if (isAmend.value) "Commit amended" else "New commit created")
|
||||||
|
@ -1,45 +1,37 @@
|
|||||||
package com.jetpackduba.gitnuro.viewmodels
|
package com.jetpackduba.gitnuro.viewmodels
|
||||||
|
|
||||||
import com.jetpackduba.gitnuro.SharedRepositoryStateManager
|
|
||||||
import com.jetpackduba.gitnuro.TaskType
|
import com.jetpackduba.gitnuro.TaskType
|
||||||
import com.jetpackduba.gitnuro.credentials.CredentialsAccepted
|
import com.jetpackduba.gitnuro.credentials.CredentialsAccepted
|
||||||
import com.jetpackduba.gitnuro.credentials.CredentialsState
|
import com.jetpackduba.gitnuro.credentials.CredentialsState
|
||||||
import com.jetpackduba.gitnuro.credentials.CredentialsStateManager
|
import com.jetpackduba.gitnuro.credentials.CredentialsStateManager
|
||||||
import com.jetpackduba.gitnuro.exceptions.WatcherInitException
|
import com.jetpackduba.gitnuro.git.FileChangesWatcher
|
||||||
import com.jetpackduba.gitnuro.git.*
|
import com.jetpackduba.gitnuro.git.ProcessingState
|
||||||
import com.jetpackduba.gitnuro.git.branches.CreateBranchUseCase
|
import com.jetpackduba.gitnuro.git.RefreshType
|
||||||
import com.jetpackduba.gitnuro.git.rebase.RebaseInteractiveState
|
import com.jetpackduba.gitnuro.git.TabState
|
||||||
import com.jetpackduba.gitnuro.git.repository.InitLocalRepositoryUseCase
|
import com.jetpackduba.gitnuro.git.repository.InitLocalRepositoryUseCase
|
||||||
import com.jetpackduba.gitnuro.git.repository.OpenRepositoryUseCase
|
import com.jetpackduba.gitnuro.git.repository.OpenRepositoryUseCase
|
||||||
import com.jetpackduba.gitnuro.git.repository.OpenSubmoduleRepositoryUseCase
|
import com.jetpackduba.gitnuro.git.repository.OpenSubmoduleRepositoryUseCase
|
||||||
import com.jetpackduba.gitnuro.git.stash.StashChangesUseCase
|
|
||||||
import com.jetpackduba.gitnuro.git.workspace.StageUntrackedFileUseCase
|
|
||||||
import com.jetpackduba.gitnuro.logging.printDebug
|
|
||||||
import com.jetpackduba.gitnuro.logging.printLog
|
import com.jetpackduba.gitnuro.logging.printLog
|
||||||
import com.jetpackduba.gitnuro.managers.AppStateManager
|
import com.jetpackduba.gitnuro.managers.AppStateManager
|
||||||
import com.jetpackduba.gitnuro.managers.ErrorsManager
|
import com.jetpackduba.gitnuro.managers.ErrorsManager
|
||||||
import com.jetpackduba.gitnuro.managers.newErrorNow
|
import com.jetpackduba.gitnuro.managers.newErrorNow
|
||||||
import com.jetpackduba.gitnuro.models.AuthorInfoSimple
|
|
||||||
import com.jetpackduba.gitnuro.models.errorNotification
|
|
||||||
import com.jetpackduba.gitnuro.models.positiveNotification
|
|
||||||
import com.jetpackduba.gitnuro.system.OpenFilePickerUseCase
|
import com.jetpackduba.gitnuro.system.OpenFilePickerUseCase
|
||||||
import com.jetpackduba.gitnuro.system.OpenUrlInBrowserUseCase
|
import com.jetpackduba.gitnuro.system.OpenUrlInBrowserUseCase
|
||||||
import com.jetpackduba.gitnuro.system.PickerType
|
import com.jetpackduba.gitnuro.system.PickerType
|
||||||
import com.jetpackduba.gitnuro.ui.IVerticalSplitPaneConfig
|
import com.jetpackduba.gitnuro.ui.IVerticalSplitPaneConfig
|
||||||
import com.jetpackduba.gitnuro.ui.SelectedItem
|
import com.jetpackduba.gitnuro.ui.SelectedItem
|
||||||
import com.jetpackduba.gitnuro.ui.TabsManager
|
|
||||||
import com.jetpackduba.gitnuro.ui.VerticalSplitPaneConfig
|
import com.jetpackduba.gitnuro.ui.VerticalSplitPaneConfig
|
||||||
import com.jetpackduba.gitnuro.updates.Update
|
import com.jetpackduba.gitnuro.updates.Update
|
||||||
import com.jetpackduba.gitnuro.updates.UpdatesRepository
|
import com.jetpackduba.gitnuro.updates.UpdatesRepository
|
||||||
import kotlinx.coroutines.*
|
import kotlinx.coroutines.CoroutineScope
|
||||||
import kotlinx.coroutines.flow.*
|
import kotlinx.coroutines.cancel
|
||||||
|
import kotlinx.coroutines.flow.MutableStateFlow
|
||||||
|
import kotlinx.coroutines.flow.SharingStarted
|
||||||
|
import kotlinx.coroutines.flow.StateFlow
|
||||||
|
import kotlinx.coroutines.flow.stateIn
|
||||||
|
import kotlinx.coroutines.launch
|
||||||
import org.eclipse.jgit.api.Git
|
import org.eclipse.jgit.api.Git
|
||||||
import org.eclipse.jgit.api.errors.CheckoutConflictException
|
|
||||||
import org.eclipse.jgit.blame.BlameResult
|
|
||||||
import org.eclipse.jgit.lib.Repository
|
import org.eclipse.jgit.lib.Repository
|
||||||
import org.eclipse.jgit.lib.RepositoryState
|
|
||||||
import org.eclipse.jgit.revwalk.RevCommit
|
|
||||||
import java.awt.Desktop
|
|
||||||
import java.io.File
|
import java.io.File
|
||||||
import javax.inject.Inject
|
import javax.inject.Inject
|
||||||
import javax.inject.Provider
|
import javax.inject.Provider
|
||||||
|
Loading…
Reference in New Issue
Block a user