Merge "Distinguish between error and timeout in intraline diff error message"
diff --git a/Documentation/config-gerrit.txt b/Documentation/config-gerrit.txt
index 27b4874..28e252a 100644
--- a/Documentation/config-gerrit.txt
+++ b/Documentation/config-gerrit.txt
@@ -648,8 +648,11 @@
 Maximum number of milliseconds to wait for intraline difference data
 before giving up and disabling it for a particular file pair.  This is
 a work around for an infinite loop bug in the intraline difference
-implementation.  If computation takes longer than the timeout the
-worker thread is terminated and no intraline difference is displayed.
+implementation.
++
+If computation takes longer than the timeout, the worker thread is
+terminated, an error message is shown, and no intraline difference is
+displayed for the file pair.
 +
 Values should use common unit suffixes to express their setting:
 +
diff --git a/gerrit-common/src/main/java/com/google/gerrit/common/data/PatchScript.java b/gerrit-common/src/main/java/com/google/gerrit/common/data/PatchScript.java
index 2308b77..fecbb76 100644
--- a/gerrit-common/src/main/java/com/google/gerrit/common/data/PatchScript.java
+++ b/gerrit-common/src/main/java/com/google/gerrit/common/data/PatchScript.java
@@ -53,6 +53,7 @@
   protected boolean hugeFile;
   protected boolean intralineDifference;
   protected boolean intralineFailure;
+  protected boolean intralineTimeout;
 
   public PatchScript(final Change.Key ck, final ChangeType ct, final String on,
       final String nn, final FileMode om, final FileMode nm,
@@ -60,7 +61,7 @@
       final SparseFileContent ca, final SparseFileContent cb,
       final List<Edit> e, final DisplayMethod ma, final DisplayMethod mb,
       final CommentDetail cd, final List<Patch> hist, final boolean hf,
-      final boolean id, final boolean idf) {
+      final boolean id, final boolean idf, final boolean idt) {
     changeId = ck;
     changeType = ct;
     oldName = on;
@@ -79,6 +80,7 @@
     hugeFile = hf;
     intralineDifference = id;
     intralineFailure = idf;
+    intralineTimeout = idt;
   }
 
   protected PatchScript() {
@@ -152,6 +154,10 @@
     return intralineFailure;
   }
 
+  public boolean hasIntralineTimeout() {
+    return intralineTimeout;
+  }
+
   public boolean isExpandAllComments() {
     return diffPrefs.isExpandAllComments();
   }
diff --git a/gerrit-gwtui/src/main/java/com/google/gerrit/client/patches/PatchConstants.java b/gerrit-gwtui/src/main/java/com/google/gerrit/client/patches/PatchConstants.java
index 9d4a481..8c9c56b 100644
--- a/gerrit-gwtui/src/main/java/com/google/gerrit/client/patches/PatchConstants.java
+++ b/gerrit-gwtui/src/main/java/com/google/gerrit/client/patches/PatchConstants.java
@@ -36,6 +36,7 @@
   String patchHistoryTitle();
   String disabledOnLargeFiles();
   String intralineFailure();
+  String intralineTimeout();
   String illegalNumberOfColumns();
 
   String upToChange();
diff --git a/gerrit-gwtui/src/main/java/com/google/gerrit/client/patches/PatchConstants.properties b/gerrit-gwtui/src/main/java/com/google/gerrit/client/patches/PatchConstants.properties
index e9fec4b..5acdb5f 100644
--- a/gerrit-gwtui/src/main/java/com/google/gerrit/client/patches/PatchConstants.properties
+++ b/gerrit-gwtui/src/main/java/com/google/gerrit/client/patches/PatchConstants.properties
@@ -18,6 +18,7 @@
 patchSet = Patch Set
 disabledOnLargeFiles = Disabled on very large source files.
 intralineFailure = Intraline difference not available due to server error.
+intralineTimeout = Intraline difference not available due to timeout.
 illegalNumberOfColumns = The number of columns cannot be zero or negative
 
 upToChange = Up to change
diff --git a/gerrit-gwtui/src/main/java/com/google/gerrit/client/patches/PatchScreen.java b/gerrit-gwtui/src/main/java/com/google/gerrit/client/patches/PatchScreen.java
index b8b474f..b18946b 100644
--- a/gerrit-gwtui/src/main/java/com/google/gerrit/client/patches/PatchScreen.java
+++ b/gerrit-gwtui/src/main/java/com/google/gerrit/client/patches/PatchScreen.java
@@ -125,6 +125,7 @@
   private HandlerRegistration regNavigation;
   private HandlerRegistration regAction;
   private boolean intralineFailure;
+  private boolean intralineTimeout;
 
   /**
    * How this patch should be displayed in the patch screen.
@@ -493,6 +494,7 @@
     }
 
     intralineFailure = isFirst && script.hasIntralineFailure();
+    intralineTimeout = isFirst && script.hasIntralineTimeout();
   }
 
   @Override
@@ -501,6 +503,9 @@
     if (intralineFailure) {
       intralineFailure = false;
       new ErrorDialog(PatchUtil.C.intralineFailure()).show();
+    } else if (intralineTimeout) {
+      intralineTimeout = false;
+      new ErrorDialog(PatchUtil.C.intralineTimeout()).show();
     }
     if (topView != null && prefs.get().isRetainHeader()) {
       setTopView(topView);
diff --git a/gerrit-httpd/src/main/java/com/google/gerrit/httpd/rpc/patch/PatchScriptBuilder.java b/gerrit-httpd/src/main/java/com/google/gerrit/httpd/rpc/patch/PatchScriptBuilder.java
index 502c9a3..5019403 100644
--- a/gerrit-httpd/src/main/java/com/google/gerrit/httpd/rpc/patch/PatchScriptBuilder.java
+++ b/gerrit-httpd/src/main/java/com/google/gerrit/httpd/rpc/patch/PatchScriptBuilder.java
@@ -133,6 +133,7 @@
       throws IOException {
     boolean intralineDifferenceIsPossible = true;
     boolean intralineFailure = false;
+    boolean intralineTimeout = false;
 
     a.path = oldName(content);
     b.path = newName(content);
@@ -160,10 +161,14 @@
             break;
 
           case ERROR:
-          case TIMEOUT:
             intralineDifferenceIsPossible = false;
             intralineFailure = true;
             break;
+
+          case TIMEOUT:
+            intralineDifferenceIsPossible = false;
+            intralineTimeout = true;
+            break;
         }
       } else {
         intralineDifferenceIsPossible = false;
@@ -212,7 +217,7 @@
         content.getOldName(), content.getNewName(), a.fileMode, b.fileMode,
         content.getHeaderLines(), diffPrefs, a.dst, b.dst, edits,
         a.displayMethod, b.displayMethod, comments, history, hugeFile,
-        intralineDifferenceIsPossible, intralineFailure);
+        intralineDifferenceIsPossible, intralineFailure, intralineTimeout);
   }
 
   private static boolean isModify(PatchListEntry content) {