Merge "Show whether diff sides lack trailing newlines"
diff --git a/WORKSPACE b/WORKSPACE
index 1e99f2b..ca888bc 100644
--- a/WORKSPACE
+++ b/WORKSPACE
@@ -35,9 +35,11 @@
 load("@io_bazel_rules_closure//closure:defs.bzl", "closure_repositories")
 
 # Prevent redundant loading of dependencies.
+# TODO(davido): Omit re-fetching ancient args4j version when these PRs are merged:
+# https://github.com/bazelbuild/rules_closure/pull/262
+# https://github.com/google/closure-templates/pull/155
 closure_repositories(
     omit_aopalliance = True,
-    omit_args4j = True,
     omit_javax_inject = True,
 )
 
@@ -289,9 +291,9 @@
 )
 
 maven_jar(
-    name = "args4j",
-    artifact = "args4j:args4j:2.0.26",
-    sha1 = "01ebb18ebb3b379a74207d5af4ea7c8338ebd78b",
+    name = "args4j-intern",
+    artifact = "args4j:args4j:2.0.29",
+    sha1 = "55ca4ddc4e906ffbaec043113b36bb410a3d909e",
 )
 
 maven_jar(
diff --git a/java/com/google/gerrit/server/cache/h2/H2CacheImpl.java b/java/com/google/gerrit/server/cache/h2/H2CacheImpl.java
index 1365cb6..6878e46 100644
--- a/java/com/google/gerrit/server/cache/h2/H2CacheImpl.java
+++ b/java/com/google/gerrit/server/cache/h2/H2CacheImpl.java
@@ -532,8 +532,11 @@
         try (PreparedStatement ps = c.conn.prepareStatement("DELETE FROM data WHERE version!=?")) {
           ps.setInt(1, version);
           int oldEntries = ps.executeUpdate();
-          logger.atInfo().log(
-              "Pruned %d entries not matching version %d from cache %s", oldEntries, version, url);
+          if (oldEntries > 0) {
+            logger.atInfo().log(
+                "Pruned %d entries not matching version %d from cache %s",
+                oldEntries, version, url);
+          }
         }
         try (Statement s = c.conn.createStatement()) {
           // Compute size without restricting to version (although obsolete data was just pruned
diff --git a/lib/BUILD b/lib/BUILD
index e2dbbf1..a9d82e9 100644
--- a/lib/BUILD
+++ b/lib/BUILD
@@ -108,7 +108,7 @@
     name = "args4j",
     data = ["//lib:LICENSE-args4j"],
     visibility = ["//visibility:public"],
-    exports = ["@args4j//jar"],
+    exports = ["@args4j-intern//jar"],
 )
 
 java_library(
diff --git a/polygerrit-ui/app/elements/change/gr-change-view/gr-change-view.html b/polygerrit-ui/app/elements/change/gr-change-view/gr-change-view.html
index 06a244c..b73fe02 100644
--- a/polygerrit-ui/app/elements/change/gr-change-view/gr-change-view.html
+++ b/polygerrit-ui/app/elements/change/gr-change-view/gr-change-view.html
@@ -362,7 +362,9 @@
         <div class="headerTitle">
           <gr-change-star
               id="changeStar"
-              change="{{_change}}" hidden$="[[!_loggedIn]]"></gr-change-star>
+              change="{{_change}}"
+              on-toggle-star="_handleToggleStar"
+              hidden$="[[!_loggedIn]]"></gr-change-star>
           <div class="changeStatuses">
             <template is="dom-repeat" items="[[_changeStatuses]]" as="status">
               <gr-change-status
diff --git a/polygerrit-ui/app/elements/change/gr-change-view/gr-change-view.js b/polygerrit-ui/app/elements/change/gr-change-view/gr-change-view.js
index 8263329..c47e12e 100644
--- a/polygerrit-ui/app/elements/change/gr-change-view/gr-change-view.js
+++ b/polygerrit-ui/app/elements/change/gr-change-view/gr-change-view.js
@@ -1623,5 +1623,10 @@
     _resetReplyOverlayFocusStops() {
       this.$.replyOverlay.setFocusStops(this.$.replyDialog.getFocusStops());
     },
+
+    _handleToggleStar(e) {
+      this.$.restAPI.saveChangeStarred(e.detail.change._number,
+          e.detail.starred);
+    },
   });
 })();
diff --git a/polygerrit-ui/app/elements/change/gr-change-view/gr-change-view_test.html b/polygerrit-ui/app/elements/change/gr-change-view/gr-change-view_test.html
index efbd3dc..af87a7e 100644
--- a/polygerrit-ui/app/elements/change/gr-change-view/gr-change-view_test.html
+++ b/polygerrit-ui/app/elements/change/gr-change-view/gr-change-view_test.html
@@ -1735,5 +1735,18 @@
       assert.isTrue(setStub.calledOnce);
       assert.isTrue(setStub.calledWith(101, 'test-project'));
     });
+
+    test('_handleToggleStar called when star is tapped', () => {
+      element._change = {
+        owner: {_account_id: 1},
+        starred: false,
+      };
+      element._loggedIn = true;
+      const stub = sandbox.stub(element, '_handleToggleStar');
+      flushAsynchronousOperations();
+
+      MockInteractions.tap(element.$.changeStar.$$('button'));
+      assert.isTrue(stub.called);
+    });
   });
 </script>
diff --git a/polygerrit-ui/app/elements/diff/gr-diff-builder/gr-diff-builder-image.js b/polygerrit-ui/app/elements/diff/gr-diff-builder/gr-diff-builder-image.js
index 27f8d39..ec78421 100644
--- a/polygerrit-ui/app/elements/diff/gr-diff-builder/gr-diff-builder-image.js
+++ b/polygerrit-ui/app/elements/diff/gr-diff-builder/gr-diff-builder-image.js
@@ -35,6 +35,7 @@
   GrDiffBuilderImage.prototype.constructor = GrDiffBuilderImage;
 
   GrDiffBuilderImage.prototype.renderDiff = function() {
+    this._outputEl.classList.add('image-diff');
     const section = this._createElement('tbody', 'image-diff');
 
     this._emitImagePair(section);
@@ -75,10 +76,10 @@
   GrDiffBuilderImage.prototype._emitImagePair = function(section) {
     const tr = this._createElement('tr');
 
-    tr.appendChild(this._createElement('td'));
+    tr.appendChild(this._createElement('td', 'left lineNum blank'));
     tr.appendChild(this._createImageCell(this._baseImage, 'left', section));
 
-    tr.appendChild(this._createElement('td'));
+    tr.appendChild(this._createElement('td', 'right lineNum blank'));
     tr.appendChild(this._createImageCell(
         this._revisionImage, 'right', section));
 
@@ -126,7 +127,7 @@
       addNamesInLabel = true;
     }
 
-    tr.appendChild(this._createElement('td'));
+    tr.appendChild(this._createElement('td', 'left lineNum blank'));
     let td = this._createElement('td', 'left');
     let label = this._createElement('label');
     let nameSpan;
@@ -145,7 +146,7 @@
     td.appendChild(label);
     tr.appendChild(td);
 
-    tr.appendChild(this._createElement('td'));
+    tr.appendChild(this._createElement('td', 'right lineNum blank'));
     td = this._createElement('td', 'right');
     label = this._createElement('label');
     labelSpan = this._createElement('span', 'label');
diff --git a/polygerrit-ui/app/elements/diff/gr-diff-builder/gr-diff-builder.js b/polygerrit-ui/app/elements/diff/gr-diff-builder/gr-diff-builder.js
index 997e1ba..409ccf9 100644
--- a/polygerrit-ui/app/elements/diff/gr-diff-builder/gr-diff-builder.js
+++ b/polygerrit-ui/app/elements/diff/gr-diff-builder/gr-diff-builder.js
@@ -544,7 +544,7 @@
     return result;
   };
 
-  GrDiffBuilder.prototype._createElement = function(tagName, className) {
+  GrDiffBuilder.prototype._createElement = function(tagName, classStr) {
     const el = document.createElement(tagName);
     // When Shady DOM is being used, these classes are added to account for
     // Polymer's polyfill behavior. In order to guarantee sufficient
@@ -553,8 +553,10 @@
     // automatically) are not being used for performance reasons, this is
     // done manually.
     el.classList.add('style-scope', 'gr-diff');
-    if (className) {
-      el.classList.add(className);
+    if (classStr) {
+      for (const className of classStr.split(' ')) {
+        el.classList.add(className);
+      }
     }
     return el;
   };
diff --git a/polygerrit-ui/app/elements/diff/gr-diff-builder/gr-diff-builder_test.html b/polygerrit-ui/app/elements/diff/gr-diff-builder/gr-diff-builder_test.html
index 129bff1..a00ecb3 100644
--- a/polygerrit-ui/app/elements/diff/gr-diff-builder/gr-diff-builder_test.html
+++ b/polygerrit-ui/app/elements/diff/gr-diff-builder/gr-diff-builder_test.html
@@ -81,6 +81,13 @@
 
     teardown(() => { sandbox.restore(); });
 
+    test('_createElement classStr applies all classes', () => {
+      const node = builder._createElement('div', 'test classes');
+      assert.isTrue(node.classList.contains('gr-diff'));
+      assert.isTrue(node.classList.contains('test'));
+      assert.isTrue(node.classList.contains('classes'));
+    });
+
     test('context control buttons', () => {
       const section = {};
       const line = {contextGroup: {lines: []}};
diff --git a/polygerrit-ui/app/elements/diff/gr-diff/gr-diff.html b/polygerrit-ui/app/elements/diff/gr-diff/gr-diff.html
index 0fb15c4..379bb34 100644
--- a/polygerrit-ui/app/elements/diff/gr-diff/gr-diff.html
+++ b/polygerrit-ui/app/elements/diff/gr-diff/gr-diff.html
@@ -55,11 +55,15 @@
         background-color: var(--table-header-background-color);
       }
       .image-diff .gr-diff {
+        background-color: var(--table-header-background-color);
         text-align: center;
       }
       .image-diff img {
+        box-shadow: 0 1px 3px rgba(0, 0, 0, .3);
         max-width: 50em;
-        outline: 1px solid var(--border-color);
+      }
+      .image-diff .right.lineNum {
+        border-left: 1px solid var(--border-color);
       }
       .image-diff label,
       .binary-diff label {
diff --git a/polygerrit-ui/app/elements/shared/gr-label-info/gr-label-info.html b/polygerrit-ui/app/elements/shared/gr-label-info/gr-label-info.html
index 195ddc3..2aead04 100644
--- a/polygerrit-ui/app/elements/shared/gr-label-info/gr-label-info.html
+++ b/polygerrit-ui/app/elements/shared/gr-label-info/gr-label-info.html
@@ -77,6 +77,9 @@
           width: 2em;
         }
       }
+      gr-button[disabled] iron-icon {
+        color: var(--border-color);
+      }
       gr-account-chip {
         margin-right: .25em;
       }
@@ -127,4 +130,4 @@
     <gr-rest-api-interface id="restAPI"></gr-rest-api-interface>
   </template>
   <script src="gr-label-info.js"></script>
-</dom-module>
\ No newline at end of file
+</dom-module>
diff --git a/polygerrit-ui/app/elements/shared/gr-label-info/gr-label-info.js b/polygerrit-ui/app/elements/shared/gr-label-info/gr-label-info.js
index 4182977..2fe5f7b1 100644
--- a/polygerrit-ui/app/elements/shared/gr-label-info/gr-label-info.js
+++ b/polygerrit-ui/app/elements/shared/gr-label-info/gr-label-info.js
@@ -177,4 +177,4 @@
       return '';
     },
   });
-})();
\ No newline at end of file
+})();