diff --git a/src/main/kotlin/app/git/GitManager.kt b/src/main/kotlin/app/git/GitManager.kt index 455765e..ba971f9 100644 --- a/src/main/kotlin/app/git/GitManager.kt +++ b/src/main/kotlin/app/git/GitManager.kt @@ -207,8 +207,11 @@ class GitManager @Inject constructor( fun push() = managerScope.launch { safeProcessing { - remoteOperationsManager.push(safeGit) - coLoadLog() + try { + remoteOperationsManager.push(safeGit) + } finally { + coLoadLog() + } } } diff --git a/src/main/kotlin/app/git/RemoteOperationsManager.kt b/src/main/kotlin/app/git/RemoteOperationsManager.kt index 3705dd9..5aeddfe 100644 --- a/src/main/kotlin/app/git/RemoteOperationsManager.kt +++ b/src/main/kotlin/app/git/RemoteOperationsManager.kt @@ -9,10 +9,7 @@ import kotlinx.coroutines.isActive import kotlinx.coroutines.withContext import org.eclipse.jgit.api.Git import org.eclipse.jgit.lib.ProgressMonitor -import org.eclipse.jgit.transport.CredentialsProvider -import org.eclipse.jgit.transport.HttpTransport -import org.eclipse.jgit.transport.RefSpec -import org.eclipse.jgit.transport.SshTransport +import org.eclipse.jgit.transport.* import java.io.File import javax.inject.Inject @@ -40,7 +37,7 @@ class RemoteOperationsManager @Inject constructor( suspend fun push(git: Git) = withContext(Dispatchers.IO) { val currentBranchRefSpec = git.repository.fullBranch - git + val pushResult = git .push() .setRefSpecs(RefSpec(currentBranchRefSpec)) .setPushTags() @@ -52,8 +49,43 @@ class RemoteOperationsManager @Inject constructor( } } .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 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 -> "" + } + + } + suspend fun clone(directory: File, url: String) = withContext(Dispatchers.IO) { try { _cloneStatus.value = CloneStatus.Cloning(0) diff --git a/src/main/kotlin/app/git/StatusManager.kt b/src/main/kotlin/app/git/StatusManager.kt index 58ea08f..a53b513 100644 --- a/src/main/kotlin/app/git/StatusManager.kt +++ b/src/main/kotlin/app/git/StatusManager.kt @@ -65,7 +65,7 @@ class StatusManager @Inject constructor( val entries = it.value if(entries.count() > 1) - entries.filter { it.oldPath != "/dev/null" } + entries.filter { entry -> entry.oldPath != "/dev/null" } else entries }.flatten() @@ -80,7 +80,7 @@ class StatusManager @Inject constructor( val entries = it.value if(entries.count() > 1) - entries.filter { it.newPath != "/dev/null" } + entries.filter { entry -> entry.newPath != "/dev/null" } else entries }.flatten() diff --git a/src/main/kotlin/app/ui/AppTab.kt b/src/main/kotlin/app/ui/AppTab.kt index 1e34824..0275e50 100644 --- a/src/main/kotlin/app/ui/AppTab.kt +++ b/src/main/kotlin/app/ui/AppTab.kt @@ -148,6 +148,7 @@ fun AppTab( text = safeLastError.message, modifier = Modifier .padding(top = 8.dp, bottom = 16.dp) + .widthIn(max = 600.dp) ) } }