Merge branch 'stable-3.1' into stable-3.2

* change-292106:
  Adapt tests to compact JSON
  Revert "Clean up BUILD rules"

Change-Id: I9062c5f84c85cdf3203f8c4c7d7a8462f276c98e
diff --git a/src/main/java/com/googlesource/gerrit/plugins/findowners/Action.java b/src/main/java/com/googlesource/gerrit/plugins/findowners/Action.java
index 409270f..8da0290 100644
--- a/src/main/java/com/googlesource/gerrit/plugins/findowners/Action.java
+++ b/src/main/java/com/googlesource/gerrit/plugins/findowners/Action.java
@@ -14,6 +14,7 @@
 
 package com.googlesource.gerrit.plugins.findowners;
 
+import static com.google.gerrit.server.project.ProjectCache.illegalState;
 import static java.util.stream.Collectors.toList;
 
 import com.google.common.collect.Streams;
@@ -160,7 +161,8 @@
   public Response<RestResult> getChangeData(Parameters params, ChangeData changeData)
       throws BadRequestException {
     int patchset = getValidPatchsetNum(changeData, params.patchset);
-    ProjectState projectState = projectCache.get(changeData.project());
+    ProjectState projectState =
+        projectCache.get(changeData.project()).orElseThrow(illegalState(changeData.project()));
     Boolean useCache = params.nocache == null || !params.nocache;
     OwnersDb db =
         Cache.getInstance(config, repoManager)
diff --git a/src/main/resources/static/find-owners.js b/src/main/resources/static/find-owners.js
index 6bbf747..c6f2826 100644
--- a/src/main/resources/static/find-owners.js
+++ b/src/main/resources/static/find-owners.js
@@ -228,10 +228,6 @@
     function isExemptedFromOwnerApproval() {
       return message.match(/(Exempted|Exempt)-From-Owner-Approval:/);
     }
-    function showDiv(div, text) {
-      div.style.display = 'inline';
-      div.innerHTML = text;
-    }
     function strElement(s) {
       var e = document.createElement('span');
       e.innerHTML = s;
@@ -248,6 +244,8 @@
       b.appendChild(document.createTextNode(name));
       b.className = BUTTON_STYLE;
       b.onclick = action;
+      b.style.display = 'inline';
+      b.style.float = 'right';
       return b;
     }
     function showJsonLines(args, key, obj) {
@@ -290,8 +288,11 @@
       for (var i = 0; i < NUM_GROUP_TYPES; i++) {
         groupTypeDiv[i] = emptyDiv(GROUP_TYPE_DIV_ID[i]);
       }
+
+      var cancelButton = newButton('Cancel', hideFindOwnersPage);
+      header.appendChild(cancelButton);
       addApplyButton();
-      args.push(newButton('Cancel', hideFindOwnersPage));
+
       var ownersDiv = emptyDiv(OWNERS_DIV_ID);
       var numCheckBoxes = 0;
       var owner2boxes = {}; // owner name ==> array of checkbox id
@@ -303,7 +304,7 @@
         var apply = newButton('Apply', doApplyButton);
         apply.id = APPLY_BUTTON_ID;
         apply.style.display = 'none';
-        args.push(apply);
+        header.appendChild(apply);
       }
       function emptyDiv(id) {
         var e = document.createElement('div');
@@ -312,6 +313,9 @@
         args.push(e);
         return e;
       }
+      function colorSpan(str, color) {
+        return `<span style="color: ${color};">${str}</span>`;
+      }
       function doApplyButton() {
         addList = [];
         removeList = [];
@@ -337,7 +341,7 @@
         div.innerHTML = '';
         div.style.display = 'inline';
         div.appendChild(strElement(title));
-        function addOwner(ownerEmail) {
+        function addOwner(itemDiv, ownerEmail) {
           if (ownerEmail == '*') {
             return; // no need to list/select '*'
           }
@@ -349,17 +353,18 @@
             owner2boxes[name] = [];
           }
           owner2boxes[name].push(id);
+
           var box = document.createElement('input');
           box.type = 'checkbox';
           box.checked = (ownerEmail in reviewerId);
           box.id = id;
           box.value = name;
           box.onclick = clickBox;
-          div.appendChild(strElement('&nbsp;&nbsp; '));
+          itemDiv.appendChild(strElement('&nbsp;&nbsp; '));
           var nobr = document.createElement('nobr');
           nobr.appendChild(box);
           nobr.appendChild(strElement(name));
-          div.appendChild(nobr);
+          itemDiv.appendChild(nobr);
         }
         keys.forEach(function(key) {
           var owners = groups[key].owners; // string of owner emails
@@ -377,10 +382,15 @@
           if (hasNamedOwner(reducedList)) {
             item += ':';
           }
-          div.appendChild(strElement(item));
-          reducedList.forEach(addOwner);
-          div.appendChild(br());
+
+          let itemDiv = document.createElement('div');
+          itemDiv.style.paddingTop = '0.5em';
+          itemDiv.appendChild(strElement(item));
+          itemDiv.appendChild(br());
+          reducedList.forEach(addOwner.bind(this, itemDiv));
+          div.appendChild(itemDiv);
         });
+        div.lastElementChild.style.paddingBottom = '0.5em';
       }
       function addOwnersDiv(div, title) {
         div.innerHTML = '';
@@ -394,8 +404,11 @@
           if (email != '*') { // do not list special email *
             var vote = reviewerVote[email];
             if ((email in reviewerVote) && vote != 0) {
-              email += ' <font color="' +
-                  ((vote > 0) ? 'green">(+' : 'red">(') + vote + ')</font>';
+              if (vote > 0) {
+                email += colorSpan('&nbsp;(+' + vote + ')', 'green');
+              } else {
+                email += colorSpan('&nbsp;(' + vote + ')', 'red');
+              }
             }
             div.appendChild(strElement('&nbsp;&nbsp;' + email + '<br>'));
           }
@@ -409,8 +422,14 @@
         Object.keys(groups).sort().forEach(function(key) {
           listOfGroup[groups[key].type].push(key);
         });
-        showDiv(header, isExemptedFromOwnerApproval() ? HTML_IS_EXEMPTED :
-            ((onSubmit ? HTML_ONSUBMIT_HEADER : '') + HTML_SELECT_REVIEWERS));
+
+        // Add message to header div and make visible.
+        let headerMessageDiv = document.createElement('div');
+        headerMessageDiv.innerHTML = isExemptedFromOwnerApproval() ? HTML_IS_EXEMPTED :
+            ((onSubmit ? HTML_ONSUBMIT_HEADER : '') + HTML_SELECT_REVIEWERS);
+        header.appendChild(headerMessageDiv);
+        header.style.display = 'inline';
+
         numCheckBoxes = 0;
         owner2boxes = {};
         for (var i = 0; i < NUM_GROUP_TYPES; i++) {
diff --git a/src/test/java/com/googlesource/gerrit/plugins/findowners/ApiIT.java b/src/test/java/com/googlesource/gerrit/plugins/findowners/ApiIT.java
index c5396af..d6d039e 100644
--- a/src/test/java/com/googlesource/gerrit/plugins/findowners/ApiIT.java
+++ b/src/test/java/com/googlesource/gerrit/plugins/findowners/ApiIT.java
@@ -149,7 +149,7 @@
     String[] emails2 = {"abc@goog.com", "abc+xyz2@g.com", "xyz-team@goog.com"};
     // Create accounts with given user name, first and second email addresses.
     for (int i = 0; i < users.length; i++) {
-      accountCreator.create(users[i], emails1[i], "FullName " + users[i]).id();
+      accountCreator.create(users[i], emails1[i], "FullName " + users[i], null).id();
       EmailInput input = new EmailInput();
       input.email = emails2[i];
       input.noConfirmation = true;
diff --git a/src/test/java/com/googlesource/gerrit/plugins/findowners/FindOwners.java b/src/test/java/com/googlesource/gerrit/plugins/findowners/FindOwners.java
index cab6f70..8f5ee7a 100644
--- a/src/test/java/com/googlesource/gerrit/plugins/findowners/FindOwners.java
+++ b/src/test/java/com/googlesource/gerrit/plugins/findowners/FindOwners.java
@@ -18,6 +18,7 @@
 import static com.google.gerrit.acceptance.testsuite.project.TestProjectUpdate.block;
 import static com.google.gerrit.entities.RefNames.REFS_CONFIG;
 import static com.google.gerrit.server.group.SystemGroupBackend.REGISTERED_USERS;
+import static com.google.gerrit.server.project.ProjectCache.illegalState;
 import static java.nio.charset.StandardCharsets.UTF_8;
 
 import com.google.gerrit.acceptance.LightweightPluginDaemonTest;
@@ -175,7 +176,7 @@
         cache.get(
             true,
             null,
-            projectCache.get(project),
+            projectCache.get(project).orElseThrow(illegalState(project)),
             accountCache,
             emails,
             repoManager,
@@ -264,7 +265,7 @@
     // This function is called repeatedly in ConfigIT without recreating config.
     // So, here we recreate config, to get the latest owners file name.
     setConfig();
-    return config.getOwnersFileName(projectCache.get(name), null);
+    return config.getOwnersFileName(projectCache.get(name).orElseThrow(illegalState(name)));
   }
 
   protected Cache getCache() {
diff --git a/src/test/java/com/googlesource/gerrit/plugins/findowners/OwnersValidatorIT.java b/src/test/java/com/googlesource/gerrit/plugins/findowners/OwnersValidatorIT.java
index c176ef7..c5b61b3 100644
--- a/src/test/java/com/googlesource/gerrit/plugins/findowners/OwnersValidatorIT.java
+++ b/src/test/java/com/googlesource/gerrit/plugins/findowners/OwnersValidatorIT.java
@@ -83,7 +83,7 @@
     Set<String> registered;
 
     MockedEmails() {
-      super(null, null, null);
+      super(null, null);
       registered =
           ImmutableSet.of(
               "u1@g.com", "u2@g.com", "u2.m@g.com", "user1@google.com", "u1+review@g.com");