[git] do not mix normal output with error output; check exit code before parsing...
authorJulia Beliaeva <Julia.Beliaeva@jetbrains.com>
Sat, 29 Oct 2016 16:33:24 +0000 (19:33 +0300)
committerJulia Beliaeva <Julia.Beliaeva@jetbrains.com>
Sun, 30 Oct 2016 16:41:26 +0000 (19:41 +0300)
EA-90861

plugins/git4idea/src/git4idea/history/GitHistoryUtils.java

index 118cc1d54aa86ac73d4914c2a151efcc8a21ae16..39c24c130ec02bc99f2aa6d514c3676e30233f35 100644 (file)
@@ -15,6 +15,7 @@
  */
 package git4idea.history;
 
+import com.intellij.execution.process.ProcessOutputTypes;
 import com.intellij.openapi.application.ApplicationManager;
 import com.intellij.openapi.components.ServiceManager;
 import com.intellij.openapi.diagnostic.Logger;
@@ -55,6 +56,7 @@ import git4idea.history.browser.SHAHash;
 import git4idea.history.browser.SymbolicRefs;
 import git4idea.history.browser.SymbolicRefsI;
 import git4idea.history.wholeTree.AbstractHash;
+import git4idea.i18n.GitBundle;
 import git4idea.log.GitLogProvider;
 import git4idea.log.GitRefManager;
 import org.jetbrains.annotations.NotNull;
@@ -537,70 +539,85 @@ public class GitHistoryUtils {
                                                  @NotNull Consumer<StringBuilder> recordConsumer,
                                                  int bufferSize)
     throws VcsException {
-    final StringBuilder buffer = new StringBuilder();
+    final StringBuilder output = new StringBuilder();
+    final StringBuilder errors = new StringBuilder();
     final Ref<Boolean> foundRecordEnd = Ref.create(false);
     final Ref<VcsException> ex = new Ref<>();
     final AtomicInteger records = new AtomicInteger();
     handler.addLineListener(new GitLineHandlerListener() {
       @Override
       public void onLineAvailable(String line, Key outputType) {
-        try {
-          // format of the record is <RECORD_START>.*<RECORD_END>.*
-          // then next record goes
-          // (rather inconveniently, after RECORD_END there is a list of modified files)
-          // so here I'm trying to find text between two RECORD_START symbols
-          // that simultaneously contains a RECORD_END
-          // this helps to deal with commits like a929478f6720ac15d949117188cd6798b4a9c286 in linux repo that have RECORD_START symbols in the message
-          // wont help with RECORD_END symbols in the message however (have not seen those yet)
-
-          String tail = null;
-          if (!foundRecordEnd.get()) {
-            int recordEnd = line.indexOf(GitLogParser.RECORD_END);
-            if (recordEnd != -1) {
-              foundRecordEnd.set(true);
-              buffer.append(line.substring(0, recordEnd + 1));
-              line = line.substring(recordEnd + 1);
-            }
-            else {
-              buffer.append(line).append("\n");
+        if (outputType == ProcessOutputTypes.STDERR) {
+          errors.append(line).append("\n");
+        }
+        else if (outputType == ProcessOutputTypes.STDOUT) {
+          try {
+            // format of the record is <RECORD_START>.*<RECORD_END>.*
+            // then next record goes
+            // (rather inconveniently, after RECORD_END there is a list of modified files)
+            // so here I'm trying to find text between two RECORD_START symbols
+            // that simultaneously contains a RECORD_END
+            // this helps to deal with commits like a929478f6720ac15d949117188cd6798b4a9c286 in linux repo that have RECORD_START symbols in the message
+            // wont help with RECORD_END symbols in the message however (have not seen those yet)
+
+            String tail = null;
+            if (!foundRecordEnd.get()) {
+              int recordEnd = line.indexOf(GitLogParser.RECORD_END);
+              if (recordEnd != -1) {
+                foundRecordEnd.set(true);
+                output.append(line.substring(0, recordEnd + 1));
+                line = line.substring(recordEnd + 1);
+              }
+              else {
+                output.append(line).append("\n");
+              }
             }
-          }
 
-          if (foundRecordEnd.get()) {
-            int nextRecordStart = line.indexOf(GitLogParser.RECORD_START);
-            if (nextRecordStart == -1) {
-              buffer.append(line).append("\n");
+            if (foundRecordEnd.get()) {
+              int nextRecordStart = line.indexOf(GitLogParser.RECORD_START);
+              if (nextRecordStart == -1) {
+                output.append(line).append("\n");
+              }
+              else if (nextRecordStart == 0) {
+                tail = line + "\n";
+              }
+              else {
+                output.append(line.substring(0, nextRecordStart));
+                tail = line.substring(nextRecordStart) + "\n";
+              }
             }
-            else if (nextRecordStart == 0) {
-              tail = line + "\n";
-            }
-            else {
-              buffer.append(line.substring(0, nextRecordStart));
-              tail = line.substring(nextRecordStart) + "\n";
-            }
-          }
 
-          if (tail != null) {
-            if (records.incrementAndGet() > bufferSize) {
-              recordConsumer.consume(buffer);
-              buffer.setLength(0);
+            if (tail != null) {
+              if (records.incrementAndGet() > bufferSize) {
+                recordConsumer.consume(output);
+                output.setLength(0);
+              }
+              output.append(tail);
+              foundRecordEnd.set(false);
             }
-            buffer.append(tail);
-            foundRecordEnd.set(false);
           }
-        }
-        catch (Exception e) {
-          ex.set(new VcsException(e));
+          catch (Exception e) {
+            ex.set(new VcsException(e));
+          }
         }
       }
 
       @Override
       public void processTerminated(int exitCode) {
-        try {
-          recordConsumer.consume(buffer);
+        if (exitCode != 0) {
+          String errorMessage = errors.toString();
+          if (errorMessage.isEmpty()) {
+            errorMessage = GitBundle.message("git.error.exit", exitCode);
+          }
+          ex.set(new VcsException(errorMessage));
         }
-        catch (Exception e) {
-          ex.set(new VcsException(e));
+        else {
+          try {
+            recordConsumer.consume(output);
+          }
+          catch (Exception e) {
+            ex.set(new VcsException(e));
+          }
         }
       }