Merge "Display total comments and unresolved comments in patchset dropdown"
diff --git a/Documentation/intro-user.txt b/Documentation/intro-user.txt
index a0fcb11..2c42d74 100644
--- a/Documentation/intro-user.txt
+++ b/Documentation/intro-user.txt
@@ -548,12 +548,15 @@
 changes can also be used to backup unfinished changes.
 
 A draft change is created by pushing to the magic
-`refs/drafts/<target-branch>` ref.
+`refs/drafts/<target-branch>` ref, or by pushing with the 'draft'
+option to `refs/for/<target-branch>%draft`.
 
 .Push a Draft Change
 ----
   $ git commit
   $ git push origin HEAD:refs/drafts/master
+  # or
+  $ git push origin HEAD:refs/for/master%draft
 ----
 
 Draft changes have the state link:user-review-ui.html#draft[Draft] and
diff --git a/WORKSPACE b/WORKSPACE
index 3b46d22..f136155 100644
--- a/WORKSPACE
+++ b/WORKSPACE
@@ -109,18 +109,18 @@
     sha1 = "5d9e2e895e3111622720157d0aa540066d5fce3a",
 )
 
-GWT_VERS = "2.8.0"
+GWT_VERS = "2.8.1"
 
 maven_jar(
     name = "user",
     artifact = "com.google.gwt:gwt-user:" + GWT_VERS,
-    sha1 = "518579870499e15531f454f35dca0772d7fa31f7",
+    sha1 = "9a13fbee70848f1f1cddd3ae33ad180af3392d9e",
 )
 
 maven_jar(
     name = "dev",
     artifact = "com.google.gwt:gwt-dev:" + GWT_VERS,
-    sha1 = "f160a61272c5ebe805cd2d3d3256ed3ecf14893f",
+    sha1 = "c7e88c07e9cda90cc623b4451d0d9713ae03aa53",
 )
 
 maven_jar(
diff --git a/gerrit-acceptance-tests/src/test/java/com/google/gerrit/acceptance/api/accounts/AccountIT.java b/gerrit-acceptance-tests/src/test/java/com/google/gerrit/acceptance/api/accounts/AccountIT.java
index a3ca832..8478d1c 100644
--- a/gerrit-acceptance-tests/src/test/java/com/google/gerrit/acceptance/api/accounts/AccountIT.java
+++ b/gerrit-acceptance-tests/src/test/java/com/google/gerrit/acceptance/api/accounts/AccountIT.java
@@ -1001,9 +1001,9 @@
     return new String(out.toByteArray(), UTF_8);
   }
 
-  @SuppressWarnings({"unchecked", "rawtypes"})
-  private static void assertIteratorSize(int size, Iterator it) {
-    assertThat(ImmutableList.copyOf(it)).hasSize(size);
+  private static void assertIteratorSize(int size, Iterator<?> it) {
+    List<?> lst = ImmutableList.copyOf(it);
+    assertThat(lst).hasSize(size);
   }
 
   private static void assertKeyMapContains(TestKey expected, Map<String, GpgKeyInfo> actualMap) {
diff --git a/gerrit-server/src/main/java/com/google/gerrit/server/index/change/ChangeIndexRewriter.java b/gerrit-server/src/main/java/com/google/gerrit/server/index/change/ChangeIndexRewriter.java
index 437af65..ca80131 100644
--- a/gerrit-server/src/main/java/com/google/gerrit/server/index/change/ChangeIndexRewriter.java
+++ b/gerrit-server/src/main/java/com/google/gerrit/server/index/change/ChangeIndexRewriter.java
@@ -229,8 +229,8 @@
     }
     IndexPredicate<ChangeData> p = (IndexPredicate<ChangeData>) in;
 
-    FieldDef def = p.getField();
-    Schema schema = index.getSchema();
+    FieldDef<ChangeData, ?> def = p.getField();
+    Schema<ChangeData> schema = index.getSchema();
     return schema.hasField(def);
   }
 
diff --git a/gerrit-server/src/main/java/com/google/gerrit/server/mail/receive/MailProcessor.java b/gerrit-server/src/main/java/com/google/gerrit/server/mail/receive/MailProcessor.java
index 51e5739..862da9f 100644
--- a/gerrit-server/src/main/java/com/google/gerrit/server/mail/receive/MailProcessor.java
+++ b/gerrit-server/src/main/java/com/google/gerrit/server/mail/receive/MailProcessor.java
@@ -32,7 +32,6 @@
 import com.google.gerrit.reviewdb.client.PatchLineComment.Status;
 import com.google.gerrit.reviewdb.client.PatchSet;
 import com.google.gerrit.reviewdb.client.Project;
-import com.google.gerrit.reviewdb.server.ReviewDb;
 import com.google.gerrit.server.ApprovalsUtil;
 import com.google.gerrit.server.ChangeMessagesUtil;
 import com.google.gerrit.server.CommentsUtil;
@@ -80,7 +79,6 @@
   private final PatchListCache patchListCache;
   private final PatchSetUtil psUtil;
   private final Provider<InternalChangeQuery> queryProvider;
-  private final Provider<ReviewDb> reviewDb;
   private final DynamicMap<MailFilter> mailFilters;
   private final EmailReviewComments.Factory outgoingMailFactory;
   private final CommentAdded commentAdded;
@@ -98,7 +96,6 @@
       PatchListCache patchListCache,
       PatchSetUtil psUtil,
       Provider<InternalChangeQuery> queryProvider,
-      Provider<ReviewDb> reviewDb,
       DynamicMap<MailFilter> mailFilters,
       EmailReviewComments.Factory outgoingMailFactory,
       ApprovalsUtil approvalsUtil,
@@ -113,7 +110,6 @@
     this.patchListCache = patchListCache;
     this.psUtil = psUtil;
     this.queryProvider = queryProvider;
-    this.reviewDb = reviewDb;
     this.mailFilters = mailFilters;
     this.outgoingMailFactory = outgoingMailFactory;
     this.commentAdded = commentAdded;
diff --git a/gerrit-server/src/main/java/com/google/gerrit/server/query/account/AccountQueryBuilder.java b/gerrit-server/src/main/java/com/google/gerrit/server/query/account/AccountQueryBuilder.java
index c8857eb..8891af5 100644
--- a/gerrit-server/src/main/java/com/google/gerrit/server/query/account/AccountQueryBuilder.java
+++ b/gerrit-server/src/main/java/com/google/gerrit/server/query/account/AccountQueryBuilder.java
@@ -124,7 +124,7 @@
   @Override
   protected Predicate<AccountState> defaultField(String query) {
     Predicate<AccountState> defaultPredicate = AccountPredicates.defaultPredicate(query);
-    if ("self".equalsIgnoreCase(query)) {
+    if ("self".equalsIgnoreCase(query) || "me".equalsIgnoreCase(query)) {
       try {
         return Predicate.or(defaultPredicate, AccountPredicates.id(self()));
       } catch (QueryParseException e) {
diff --git a/gerrit-server/src/main/java/com/google/gerrit/server/query/change/ChangeQueryBuilder.java b/gerrit-server/src/main/java/com/google/gerrit/server/query/change/ChangeQueryBuilder.java
index 099a3d1..ca719c8 100644
--- a/gerrit-server/src/main/java/com/google/gerrit/server/query/change/ChangeQueryBuilder.java
+++ b/gerrit-server/src/main/java/com/google/gerrit/server/query/change/ChangeQueryBuilder.java
@@ -118,6 +118,8 @@
   private static final Pattern DEF_CHANGE =
       Pattern.compile("^(?:[1-9][0-9]*|(?:[^~]+~[^~]+~)?[iI][0-9a-f]{4,}.*)$");
 
+  private static final int MAX_ACCOUNTS_PER_DEFAULT_FIELD = 10;
+
   // NOTE: As new search operations are added, please keep the
   // SearchSuggestOracle up to date.
 
@@ -884,9 +886,13 @@
     return new HasDraftByPredicate(who);
   }
 
+  private boolean isSelf(String who) {
+    return "self".equals(who) || "me".equals(who);
+  }
+
   @Operator
   public Predicate<ChangeData> visibleto(String who) throws QueryParseException, OrmException {
-    if ("self".equals(who)) {
+    if (isSelf(who)) {
       return is_visible();
     }
     Set<Account.Id> m = args.accountResolver.findAll(args.db.get(), who);
@@ -939,6 +945,15 @@
     return Predicate.or(p);
   }
 
+  private Predicate<ChangeData> ownerDefaultField(String who)
+      throws QueryParseException, OrmException {
+    Set<Account.Id> accounts = parseAccount(who);
+    if (accounts.size() > MAX_ACCOUNTS_PER_DEFAULT_FIELD) {
+      return Predicate.any();
+    }
+    return owner(accounts);
+  }
+
   @Operator
   public Predicate<ChangeData> assignee(String who) throws QueryParseException, OrmException {
     return assignee(parseAccount(who));
@@ -968,17 +983,26 @@
 
   @Operator
   public Predicate<ChangeData> reviewer(String who) throws QueryParseException, OrmException {
+    return reviewer(who, false);
+  }
+
+  private Predicate<ChangeData> reviewerDefaultField(String who) throws QueryParseException, OrmException {
+    return reviewer(who, true);
+  }
+
+  private Predicate<ChangeData> reviewer(String who, boolean forDefaultField)
+      throws QueryParseException, OrmException {
     if (args.getSchema().hasField(ChangeField.WIP)) {
       return Predicate.and(
           Predicate.not(new BooleanPredicate(ChangeField.WIP, args.fillArgs)),
-          reviewerByState(who, ReviewerStateInternal.REVIEWER));
+          reviewerByState(who, ReviewerStateInternal.REVIEWER, forDefaultField));
     }
-    return reviewerByState(who, ReviewerStateInternal.REVIEWER);
+    return reviewerByState(who, ReviewerStateInternal.REVIEWER, forDefaultField);
   }
 
   @Operator
   public Predicate<ChangeData> cc(String who) throws QueryParseException, OrmException {
-    return reviewerByState(who, ReviewerStateInternal.CC);
+    return reviewerByState(who, ReviewerStateInternal.CC, false);
   }
 
   @Operator
@@ -1137,12 +1161,12 @@
     // Adapt the capacity of this list when adding more default predicates.
     List<Predicate<ChangeData>> predicates = Lists.newArrayListWithCapacity(11);
     try {
-      predicates.add(owner(query));
+      predicates.add(ownerDefaultField(query));
     } catch (OrmException | QueryParseException e) {
       // Skip.
     }
     try {
-      predicates.add(reviewer(query));
+      predicates.add(reviewerDefaultField(query));
     } catch (OrmException | QueryParseException e) {
       // Skip.
     }
@@ -1165,7 +1189,7 @@
   }
 
   private Set<Account.Id> parseAccount(String who) throws QueryParseException, OrmException {
-    if ("self".equals(who)) {
+    if (isSelf(who)) {
       return Collections.singleton(self());
     }
     Set<Account.Id> matches = args.accountResolver.findAll(args.db.get(), who);
@@ -1208,8 +1232,8 @@
     return args.getIdentifiedUser().getAccountId();
   }
 
-  public Predicate<ChangeData> reviewerByState(String who, ReviewerStateInternal state)
-      throws QueryParseException, OrmException {
+  public Predicate<ChangeData> reviewerByState(String who, ReviewerStateInternal state,
+      boolean forDefaultField) throws QueryParseException, OrmException {
     Predicate<ChangeData> reviewerByEmailPredicate = null;
     if (args.index.getSchema().hasField(ChangeField.REVIEWER_BY_EMAIL)) {
       Address address = Address.tryParse(who);
@@ -1220,12 +1244,13 @@
 
     Predicate<ChangeData> reviewerPredicate = null;
     try {
-      reviewerPredicate =
-          Predicate.or(
-              parseAccount(who)
-                  .stream()
-                  .map(id -> ReviewerPredicate.forState(args, id, state))
-                  .collect(toList()));
+      Set<Account.Id> accounts = parseAccount(who);
+      if (!forDefaultField || accounts.size() <= MAX_ACCOUNTS_PER_DEFAULT_FIELD) {
+        reviewerPredicate = Predicate.or(
+            accounts.stream()
+                .map(id -> ReviewerPredicate.forState(args, id, state))
+                .collect(toList()));
+      }
     } catch (QueryParseException e) {
       // Propagate this exception only if we can't use 'who' to query by email
       if (reviewerByEmailPredicate == null) {
diff --git a/gerrit-server/src/test/java/com/google/gerrit/server/query/account/AbstractQueryAccountsTest.java b/gerrit-server/src/test/java/com/google/gerrit/server/query/account/AbstractQueryAccountsTest.java
index 3d13536..6601266 100644
--- a/gerrit-server/src/test/java/com/google/gerrit/server/query/account/AbstractQueryAccountsTest.java
+++ b/gerrit-server/src/test/java/com/google/gerrit/server/query/account/AbstractQueryAccountsTest.java
@@ -255,6 +255,7 @@
     assertQuery("Jo Do", user1);
     assertQuery("jo do", user1);
     assertQuery("self", currentUserInfo, user3);
+    assertQuery("me", currentUserInfo);
     assertQuery("name:John", user1);
     assertQuery("name:john", user1);
     assertQuery("name:Doe", user1);
diff --git a/gerrit-server/src/test/java/com/google/gerrit/server/query/change/AbstractQueryChangesTest.java b/gerrit-server/src/test/java/com/google/gerrit/server/query/change/AbstractQueryChangesTest.java
index 34ef0b5..6df03cd 100644
--- a/gerrit-server/src/test/java/com/google/gerrit/server/query/change/AbstractQueryChangesTest.java
+++ b/gerrit-server/src/test/java/com/google/gerrit/server/query/change/AbstractQueryChangesTest.java
@@ -1988,6 +1988,19 @@
         .containsExactlyElementsIn(expectedPatterns);
   }
 
+  @Test
+  public void selfAndMe() throws Exception {
+    TestRepository<Repo> repo = createProject("repo");
+    Change change1 = insert(repo, newChange(repo));
+    Change change2 = insert(repo, newChange(repo), userId);
+    insert(repo, newChange(repo));
+    gApi.accounts().self().starChange(change1.getId().toString());
+    gApi.accounts().self().starChange(change2.getId().toString());
+
+    assertQuery("starredby:self", change2, change1);
+    assertQuery("starredby:me", change2, change1);
+  }
+
   protected ChangeInserter newChange(TestRepository<Repo> repo) throws Exception {
     return newChange(repo, null, null, null, null);
   }
diff --git a/polygerrit-ui/README.md b/polygerrit-ui/README.md
index 0fdbd44..3fd774d 100644
--- a/polygerrit-ui/README.md
+++ b/polygerrit-ui/README.md
@@ -95,8 +95,10 @@
 ./polygerrit-ui/app/run_test.sh
 ```
 
-To allow the tests to run in Safari it is necessary to enable the
-"Allow Remote Automation" option under the "Develop" menu.
+To allow the tests to run in Safari:
+
+* In the Advanced preferences tab, check "Show Develop menu in menu bar".
+* In the Develop menu, enable the "Allow Remote Automation" option.
 
 If you need to pass additional arguments to `wct`:
 
diff --git a/polygerrit-ui/app/elements/change/gr-reply-dialog/gr-reply-dialog.js b/polygerrit-ui/app/elements/change/gr-reply-dialog/gr-reply-dialog.js
index 0bb548b..60d3c4f 100644
--- a/polygerrit-ui/app/elements/change/gr-reply-dialog/gr-reply-dialog.js
+++ b/polygerrit-ui/app/elements/change/gr-reply-dialog/gr-reply-dialog.js
@@ -177,7 +177,8 @@
     },
 
     setLabelValue: function(label, value) {
-      var selectorEl = this.$$('iron-selector[data-label="' + label + '"]');
+      var selectorEl =
+          this.$.labelScores.$$('iron-selector[data-label="' + label + '"]');
       // The selector may not be present if it’s not at the latest patch set.
       if (!selectorEl) { return; }
       var item = selectorEl.$$('gr-button[data-value="' + value + '"]');
diff --git a/polygerrit-ui/app/elements/change/gr-reply-dialog/gr-reply-dialog_test.html b/polygerrit-ui/app/elements/change/gr-reply-dialog/gr-reply-dialog_test.html
index 253f01c..34ac167 100644
--- a/polygerrit-ui/app/elements/change/gr-reply-dialog/gr-reply-dialog_test.html
+++ b/polygerrit-ui/app/elements/change/gr-reply-dialog/gr-reply-dialog_test.html
@@ -214,6 +214,17 @@
       });
     });
 
+    test('setlabelValue', function() {
+      element._account = {_account_id: 1};
+      flushAsynchronousOperations();
+      var label = 'Verified';
+      var value = '+1';
+      element.setLabelValue(label, value);
+      flushAsynchronousOperations();
+      var labels = element.$.labelScores.getLabelValues();
+      assert.deepEqual(labels, {'Verified': 1});
+    });
+
     function getActiveElement() {
       return Polymer.IronOverlayManager.deepActiveElement;
     }
diff --git a/polygerrit-ui/app/elements/core/gr-search-bar/gr-search-bar.js b/polygerrit-ui/app/elements/core/gr-search-bar/gr-search-bar.js
index d4e7ae2..4edf1be 100644
--- a/polygerrit-ui/app/elements/core/gr-search-bar/gr-search-bar.js
+++ b/polygerrit-ui/app/elements/core/gr-search-bar/gr-search-bar.js
@@ -82,6 +82,7 @@
   ];
 
   var SELF_EXPRESSION = 'self';
+  var ME_EXPRESSION = 'me';
 
   var MAX_AUTOCOMPLETE_RESULTS = 10;
 
@@ -176,9 +177,13 @@
           }).then(function(accounts) {
             // When the expression supplied is a beginning substring of 'self',
             // add it as an autocomplete option.
-            return SELF_EXPRESSION.indexOf(expression) === 0 ?
-                accounts.concat([predicate + ':' + SELF_EXPRESSION]) :
-                accounts;
+            if (SELF_EXPRESSION.indexOf(expression) === 0) {
+              return accounts.concat([predicate + ':' + SELF_EXPRESSION]);
+            } else if (ME_EXPRESSION.indexOf(expression) === 0) {
+              return accounts.concat([predicate + ':' + ME_EXPRESSION]);
+            } else {
+              return accounts;
+            }
           });
     },
 
diff --git a/polygerrit-ui/app/elements/core/gr-search-bar/gr-search-bar_test.html b/polygerrit-ui/app/elements/core/gr-search-bar/gr-search-bar_test.html
index 3ddc96b..05ceb34 100644
--- a/polygerrit-ui/app/elements/core/gr-search-bar/gr-search-bar_test.html
+++ b/polygerrit-ui/app/elements/core/gr-search-bar/gr-search-bar_test.html
@@ -160,6 +160,17 @@
         });
       });
 
+      test('Inserts me as option when valid', function(done) {
+        element._getSearchSuggestions('owner:m').then(function(s) {
+          assert.equal(s[0].value, 'owner:me');
+        }).then(function() {
+          element._getSearchSuggestions('owner:meme').then(function(s) {
+            assert.notEqual(s[0].value, 'owner:me');
+            done();
+          });
+        });
+      });
+
       test('Autocompletes groups', function(done) {
         element._getSearchSuggestions('ownerin:pol').then(function(s) {
           assert.equal(s[0].value, 'ownerin:Polygerrit');