Improve Git error message handling (#1011)

Co-authored-by: Harsh Shandilya <me@msfjarvis.dev>
This commit is contained in:
Fabian Henneke
2020-08-12 10:50:08 +02:00
committed by GitHub
parent 372c0f3dbd
commit d08397872a
3 changed files with 24 additions and 37 deletions

View File

@@ -6,58 +6,48 @@
package com.zeapo.pwdstore.git package com.zeapo.pwdstore.git
import android.os.RemoteException import android.os.RemoteException
import androidx.annotation.StringRes
import com.zeapo.pwdstore.Application import com.zeapo.pwdstore.Application
import com.zeapo.pwdstore.R import com.zeapo.pwdstore.R
import java.net.UnknownHostException
/** /**
* Supertype for all Git-related [Exception]s that can be thrown by [GitCommandExecutor.execute]. * Supertype for all Git-related [Exception]s that can be thrown by [GitCommandExecutor.execute].
*/ */
sealed class GitException(message: String? = null) : Exception(message) { sealed class GitException(@StringRes res: Int, vararg fmt: String) : Exception(buildMessage(res, *fmt)) {
override val message = super.message!!
companion object {
private fun buildMessage(@StringRes res: Int, vararg fmt: String) = Application.instance.resources.getString(res, *fmt)
}
/** /**
* Encapsulates possible errors from a [org.eclipse.jgit.api.PullCommand]. * Encapsulates possible errors from a [org.eclipse.jgit.api.PullCommand].
*/ */
class PullException(val reason: Reason) : GitException() { sealed class PullException(@StringRes res: Int, vararg fmt: String) : GitException(res, *fmt) {
object PullRebaseFailed : PullException(R.string.git_pull_fail_error)
enum class Reason {
REBASE_FAILED,
}
} }
/** /**
* Encapsulates possible errors from a [org.eclipse.jgit.api.PushCommand]. * Encapsulates possible errors from a [org.eclipse.jgit.api.PushCommand].
*/ */
class PushException(val reason: Reason, vararg val fmt: String) : GitException() { sealed class PushException(@StringRes res: Int, vararg fmt: String) : GitException(res, *fmt) {
enum class Reason {
NON_FAST_FORWARD, object NonFastForward : PushException(R.string.git_push_nff_error)
REMOTE_REJECTED, object RemoteRejected : PushException(R.string.git_push_other_error)
GENERIC, class Generic(message: String) : PushException(R.string.git_push_generic_error, message)
}
} }
} }
object ErrorMessages { object ErrorMessages {
private val PULL_REASON_MAP = mapOf(
GitException.PullException.Reason.REBASE_FAILED to R.string.git_pull_fail_error,
)
private val PUSH_REASON_MAP = mapOf(
GitException.PushException.Reason.NON_FAST_FORWARD to R.string.git_push_nff_error,
GitException.PushException.Reason.REMOTE_REJECTED to R.string.git_push_other_error,
GitException.PushException.Reason.GENERIC to R.string.git_push_generic_error,
)
operator fun get(throwable: Throwable?): String { operator fun get(throwable: Throwable?): String {
val resources = Application.instance.resources val resources = Application.instance.resources
if (throwable == null) return resources.getString(R.string.git_unknown_error) if (throwable == null) return resources.getString(R.string.git_unknown_error)
return when (val rootCause = rootCause(throwable)) { return when (val rootCause = rootCause(throwable)) {
is GitException.PullException -> { is GitException -> rootCause.message
resources.getString(PULL_REASON_MAP.getValue(rootCause.reason)) is UnknownHostException -> resources.getString(R.string.git_unknown_host, throwable.message)
}
is GitException.PushException -> {
resources.getString(PUSH_REASON_MAP.getValue(rootCause.reason), *rootCause.fmt)
}
else -> throwable.message ?: resources.getString(R.string.git_unknown_error) else -> throwable.message ?: resources.getString(R.string.git_unknown_error)
} }
} }

View File

@@ -59,7 +59,7 @@ class GitCommandExecutor(
} }
val rr = result.rebaseResult val rr = result.rebaseResult
if (rr.status === RebaseResult.Status.STOPPED) { if (rr.status === RebaseResult.Status.STOPPED) {
operationResult = Result.Err(PullException(PullException.Reason.REBASE_FAILED)) operationResult = Result.Err(PullException.PullRebaseFailed)
} }
} }
is PushCommand -> { is PushCommand -> {
@@ -70,21 +70,17 @@ class GitCommandExecutor(
// Code imported (modified) from Gerrit PushOp, license Apache v2 // Code imported (modified) from Gerrit PushOp, license Apache v2
for (rru in result.remoteUpdates) { for (rru in result.remoteUpdates) {
val error = when (rru.status) { val error = when (rru.status) {
RemoteRefUpdate.Status.REJECTED_NONFASTFORWARD -> { RemoteRefUpdate.Status.REJECTED_NONFASTFORWARD -> PushException.NonFastForward
PushException(PushException.Reason.NON_FAST_FORWARD)
}
RemoteRefUpdate.Status.REJECTED_NODELETE, RemoteRefUpdate.Status.REJECTED_NODELETE,
RemoteRefUpdate.Status.REJECTED_REMOTE_CHANGED, RemoteRefUpdate.Status.REJECTED_REMOTE_CHANGED,
RemoteRefUpdate.Status.NON_EXISTING, RemoteRefUpdate.Status.NON_EXISTING,
RemoteRefUpdate.Status.NOT_ATTEMPTED, RemoteRefUpdate.Status.NOT_ATTEMPTED,
-> { -> PushException.Generic(rru.status.name)
PushException(PushException.Reason.GENERIC, rru.status.name)
}
RemoteRefUpdate.Status.REJECTED_OTHER_REASON -> { RemoteRefUpdate.Status.REJECTED_OTHER_REASON -> {
if ("non-fast-forward" == rru.message) { if ("non-fast-forward" == rru.message) {
PushException(PushException.Reason.REMOTE_REJECTED) PushException.RemoteRejected
} else { } else {
PushException(PushException.Reason.GENERIC, rru.message) PushException.Generic(rru.message)
} }
} }
RemoteRefUpdate.Status.UP_TO_DATE -> { RemoteRefUpdate.Status.UP_TO_DATE -> {

View File

@@ -374,6 +374,7 @@
<string name="git_push_nff_error">Push was rejected by remote, run pull before pushing again. You can use Synchronize rather than pull/push as it implements both</string> <string name="git_push_nff_error">Push was rejected by remote, run pull before pushing again. You can use Synchronize rather than pull/push as it implements both</string>
<string name="git_push_generic_error">Push was rejected by remote, reason: %1$s</string> <string name="git_push_generic_error">Push was rejected by remote, reason: %1$s</string>
<string name="git_push_other_error">Remote rejected non-fast-forward push. Check receive.denyNonFastForwards variable in config file of destination repository.</string> <string name="git_push_other_error">Remote rejected non-fast-forward push. Check receive.denyNonFastForwards variable in config file of destination repository.</string>
<string name="git_unknown_host">Unknown host: %1$s</string>
<string name="git_operation_running">Running git operation…</string> <string name="git_operation_running">Running git operation…</string>
<!-- OpenKeychain not installed --> <!-- OpenKeychain not installed -->