diff --git a/plugins/git4idea/src/git4idea/commands/GitCommandResult.java b/plugins/git4idea/src/git4idea/commands/GitCommandResult.java index 00b38073dd86..536e3855df66 100644 --- a/plugins/git4idea/src/git4idea/commands/GitCommandResult.java +++ b/plugins/git4idea/src/git4idea/commands/GitCommandResult.java @@ -13,6 +13,7 @@ import git4idea.i18n.GitBundle; import org.jetbrains.annotations.Nls; import org.jetbrains.annotations.NonNls; import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Nullable; import java.util.Arrays; import java.util.Collection; @@ -31,24 +32,35 @@ public class GitCommandResult { private final boolean myAuthenticationFailed; private final List myErrorOutput; private final List myOutput; + protected final @Nullable @Nls String myRootName; public GitCommandResult(boolean startFailed, int exitCode, @NotNull List errorOutput, @NotNull List output) { - this(startFailed, exitCode, false, errorOutput, output); + this(startFailed, exitCode, errorOutput, output, null); + } + + public GitCommandResult(boolean startFailed, + int exitCode, + @NotNull List errorOutput, + @NotNull List output, + @Nullable @Nls String rootName) { + this(startFailed, exitCode, false, errorOutput, output, rootName); } private GitCommandResult(boolean startFailed, int exitCode, boolean authenticationFailed, @NotNull List errorOutput, - @NotNull List output) { + @NotNull List output, + @Nullable @Nls String rootName) { myExitCode = exitCode; myStartFailed = startFailed; myAuthenticationFailed = authenticationFailed; myErrorOutput = errorOutput; myOutput = output; + myRootName = rootName; } /** @@ -59,7 +71,8 @@ public class GitCommandResult { result.myExitCode, authenticationFailed, result.myErrorOutput, - result.myOutput); + result.myOutput, + result.myRootName); } /** @@ -139,15 +152,20 @@ public class GitCommandResult { * @throws VcsException with message from {@link #getErrorOutputAsJoinedString()} */ public void throwOnError(int... ignoredErrorCodes) throws VcsException { - if (!success(ignoredErrorCodes)) throw new VcsException(getErrorOutputAsJoinedString()); + if (success(ignoredErrorCodes)) return; + String errorMessage = getErrorOutputAsJoinedString(); + if (myRootName != null) { + errorMessage = "[" + myRootName + "] " + errorMessage; + } + throw new VcsException(errorMessage); } static @NotNull GitCommandResult startError(@NotNull @Nls String error) { - return new GitCommandResult(true, -1, Collections.singletonList(error), Collections.emptyList()); + return new GitCommandResult(true, -1, Collections.singletonList(error), Collections.emptyList(), null); } public static @NotNull GitCommandResult error(@NotNull @Nls String error) { - return new GitCommandResult(false, 1, Collections.singletonList(error), Collections.emptyList()); + return new GitCommandResult(false, 1, Collections.singletonList(error), Collections.emptyList(), null); } /** diff --git a/plugins/git4idea/src/git4idea/commands/GitHandler.java b/plugins/git4idea/src/git4idea/commands/GitHandler.java index 76db7feba5ec..a04df4f987cb 100644 --- a/plugins/git4idea/src/git4idea/commands/GitHandler.java +++ b/plugins/git4idea/src/git4idea/commands/GitHandler.java @@ -25,7 +25,6 @@ import com.intellij.openapi.vfs.VirtualFile; import com.intellij.util.EnvironmentUtil; import com.intellij.util.EventDispatcher; import com.intellij.util.ThrowableConsumer; -import com.intellij.vcs.VcsLocaleHelper; import com.intellij.vcsUtil.VcsFileUtil; import git4idea.GitVcs; import git4idea.config.GitExecutable; @@ -486,8 +485,7 @@ public abstract class GitHandler { executionEnvironment.putAll(myCustomEnv); executionEnvironment.put(GitCommand.IJ_HANDLER_MARKER_ENV, "true"); - // customizers take read locks, which could not be acquired under potemkin progress - if (!(ProgressManager.getInstance().getProgressIndicator() instanceof PotemkinProgress)) { + if (!shouldSuppressReadLocks()) { VcsEnvCustomizer.EP_NAME.forEachExtensionSafe(customizer -> { customizer.customizeCommandAndEnvironment(myProject, executionEnvironment, myExecutableContext); }); @@ -496,6 +494,16 @@ public abstract class GitHandler { } } + /** + * Tasks executed under {@link PotemkinProgress#runInBackground} cannot take read lock. + */ + protected static boolean shouldSuppressReadLocks() { + if (ProgressManager.getInstance().getProgressIndicator() instanceof PotemkinProgress) { + return !ApplicationManager.getApplication().isDispatchThread(); + } + return false; + } + protected abstract Process startProcess() throws ExecutionException; /** diff --git a/plugins/git4idea/src/git4idea/commands/GitImplBase.java b/plugins/git4idea/src/git4idea/commands/GitImplBase.java index fe3c347cec64..ab7ad23e881d 100644 --- a/plugins/git4idea/src/git4idea/commands/GitImplBase.java +++ b/plugins/git4idea/src/git4idea/commands/GitImplBase.java @@ -17,6 +17,7 @@ import com.intellij.openapi.util.*; import com.intellij.openapi.util.io.FileUtil; import com.intellij.openapi.util.registry.Registry; import com.intellij.openapi.util.text.StringUtil; +import com.intellij.openapi.vcs.ProjectLevelVcsManager; import com.intellij.openapi.vfs.CharsetToolkit; import com.intellij.openapi.vfs.VirtualFile; import com.intellij.util.concurrency.annotations.RequiresBackgroundThread; @@ -32,6 +33,7 @@ import git4idea.rebase.GitSimpleEditorHandler; import git4idea.rebase.GitUnstructuredEditor; import git4idea.util.GitVcsConsoleWriter; import one.util.streamex.StreamEx; +import org.jetbrains.annotations.Nls; import org.jetbrains.annotations.NonNls; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; @@ -197,10 +199,35 @@ public abstract class GitImplBase implements Git { catch (IOException e) { return GitCommandResult.error(GitBundle.message("git.error.cant.process.output", e.getLocalizedMessage())); } + + String rootName = getPresentableRootName(handler); return new GitCommandResult(resultListener.myStartFailed, resultListener.myExitCode, outputCollector.myErrorOutput, - outputCollector.myOutput); + outputCollector.myOutput, + rootName); + } + + private static @Nullable @Nls String getPresentableRootName(@NotNull GitLineHandler handler) { + if (GitHandler.shouldSuppressReadLocks()) return null; + if (handler.getCommand().equals(GitCommand.VERSION)) return null; + + VirtualFile root = handler.getExecutableContext().getRoot(); + if (root == null) return null; + + Project project = handler.project(); + if (project == null) return root.getName(); + + ProjectLevelVcsManager vcsManager = ProjectLevelVcsManager.getInstance(project); + VirtualFile vcsRoot = vcsManager.getVcsRootFor(root); + if (root.equals(vcsRoot)) { + if (vcsManager.getRootsUnderVcs(GitVcs.getInstance(project)).length == 1) { + return null; + } + return ProjectLevelVcsManager.getInstance(project).getShortNameForVcsRoot(root); + } + + return root.getName(); } /** diff --git a/plugins/git4idea/src/git4idea/commands/GitRebaseCommandResult.kt b/plugins/git4idea/src/git4idea/commands/GitRebaseCommandResult.kt index d76a05f3f611..d2a993b58809 100644 --- a/plugins/git4idea/src/git4idea/commands/GitRebaseCommandResult.kt +++ b/plugins/git4idea/src/git4idea/commands/GitRebaseCommandResult.kt @@ -3,16 +3,24 @@ package git4idea.commands import git4idea.commands.GitRebaseCommandResult.CancelState.* -class GitRebaseCommandResult private constructor(val commandResult: GitCommandResult, - private val cancelState: CancelState) : GitCommandResult(commandResult.hasStartFailed(), - commandResult.exitCode, - commandResult.output, - commandResult.errorOutput) { +class GitRebaseCommandResult private constructor( + val commandResult: GitCommandResult, + private val cancelState: CancelState +) : GitCommandResult(commandResult.hasStartFailed(), + commandResult.exitCode, + commandResult.output, + commandResult.errorOutput, + commandResult.myRootName) { companion object { - @JvmStatic fun normal(commandResult: GitCommandResult) = GitRebaseCommandResult(commandResult, NOT_CANCELLED) - @JvmStatic fun cancelledInCommitList(commandResult: GitCommandResult) = GitRebaseCommandResult(commandResult, COMMIT_LIST_CANCELLED) - @JvmStatic fun cancelledInCommitMessage(commandResult: GitCommandResult) = GitRebaseCommandResult(commandResult, EDITOR_CANCELLED) + @JvmStatic + fun normal(commandResult: GitCommandResult) = GitRebaseCommandResult(commandResult, NOT_CANCELLED) + + @JvmStatic + fun cancelledInCommitList(commandResult: GitCommandResult) = GitRebaseCommandResult(commandResult, COMMIT_LIST_CANCELLED) + + @JvmStatic + fun cancelledInCommitMessage(commandResult: GitCommandResult) = GitRebaseCommandResult(commandResult, EDITOR_CANCELLED) } private enum class CancelState { diff --git a/plugins/git4idea/tests/git4idea/branch/GitBranchWorkerTest.kt b/plugins/git4idea/tests/git4idea/branch/GitBranchWorkerTest.kt index 532b93a09122..91f3fa35cffb 100644 --- a/plugins/git4idea/tests/git4idea/branch/GitBranchWorkerTest.kt +++ b/plugins/git4idea/tests/git4idea/branch/GitBranchWorkerTest.kt @@ -645,7 +645,7 @@ class GitBranchWorkerTest : GitPlatformTest() { repository.git("branch todelete") } git.onBranchDelete { - if (second == it) GitCommandResult(false, 1, listOf("Couldn't remove branch"), listOf()) + if (second == it) GitCommandResult.error("Couldn't remove branch") else null } } diff --git a/plugins/git4idea/tests/git4idea/push/GitPushOperationMultiRepoTest.kt b/plugins/git4idea/tests/git4idea/push/GitPushOperationMultiRepoTest.kt index 93cc49f32b91..d806acaedcc6 100644 --- a/plugins/git4idea/tests/git4idea/push/GitPushOperationMultiRepoTest.kt +++ b/plugins/git4idea/tests/git4idea/push/GitPushOperationMultiRepoTest.kt @@ -55,7 +55,7 @@ class GitPushOperationMultiRepoTest : GitPushOperationBaseTest() { fun `test try push from all roots even if one fails`() { // fail in the first repo git.onPush { - if (it == ultimate) GitCommandResult(false, 128, listOf("Failed to push to origin"), listOf()) + if (it == ultimate) GitCommandResult.error("Failed to push to origin") else null } diff --git a/plugins/git4idea/tests/git4idea/test/TestGit.kt b/plugins/git4idea/tests/git4idea/test/TestGit.kt index 5696e5c210fc..85ded7dbbff4 100644 --- a/plugins/git4idea/tests/git4idea/test/TestGit.kt +++ b/plugins/git4idea/tests/git4idea/test/TestGit.kt @@ -166,7 +166,7 @@ class TestGitImpl : GitImpl() { } } - private fun fatalResult() = GitCommandResult(false, 128, listOf("fatal: error: $UNKNOWN_ERROR_TEXT"), emptyList()) + private fun fatalResult() = GitCommandResult(false, 128, listOf("fatal: error: $UNKNOWN_ERROR_TEXT"), emptyList(), null) }