Merge branch 'stable-2.14' into stable-2.15

* stable-2.14:
  Fix label name generated by workskace-status.sh
  Ignore /MERGE_LIST when looking for owners
  Upgrade bazlets to latest stable-2.14 to build with 2.14.16 API
  Align Eclipse compiler settings with core Gerrit's
  Replace wildcard imports with explicit imports
  Upgrade jackson to 2.9.7
  bazlets: Replace native.git_repository with skylark rule
  Upgrade bazlets to latest stable-2.14 to build with 2.14.15 API
  Format all Bazel build files with buildifier
  Migrate (i.e. move) `tools/bazel.rc` to `.bazelrc`
  Update bazlets to latest stable-2.14 to build with 2.14.14 API
  Update bazlets to latest stable-2.14 to build with 2.14.13 API
  Fix names of build output jar files in README
  Adjust to renamed dependencies in core
  Update bazlets to latest revision on stable-2.14
  Filter out inactive accounts in OWNERS
  Bazel: Add standalone build mode
  Does not include jackson-core in the final artifacts
  Sync Jackson lib version with Gerrit
  Fix owners dependencies
  Remove duplicated build dependencies
  Reformat build files
  Remove Buck build
  Fix config documentation
  Fix Eclipse warnings
  Cleanup .gitignore file
  Eager initialize Owners Prolog Predicates
  Consider name and e-mail matching edge cases
  Batch sending mail when multiple reviewers added

Change-Id: I3c310a8eff7094ef4bd0c9bdb1fc2104b76dd835
diff --git a/.bazelrc b/.bazelrc
new file mode 100644
index 0000000..4ed16cf
--- /dev/null
+++ b/.bazelrc
@@ -0,0 +1,2 @@
+build --workspace_status_command=./tools/workspace-status.sh
+test --build_tests_only
diff --git a/.buckconfig b/.buckconfig
deleted file mode 100644
index bd040e3..0000000
--- a/.buckconfig
+++ /dev/null
@@ -1,3 +0,0 @@
-[java]
-  source_level = 8
-  target_level = 8
diff --git a/.gitignore b/.gitignore
index 2771034..6042b9d 100644
--- a/.gitignore
+++ b/.gitignore
@@ -1,5 +1,3 @@
-target
-
 # IntelliJ
 *.iml
 *.ipr
diff --git a/.settings/org.eclipse.jdt.core.prefs b/.settings/org.eclipse.jdt.core.prefs
new file mode 100644
index 0000000..40e022d
--- /dev/null
+++ b/.settings/org.eclipse.jdt.core.prefs
@@ -0,0 +1,126 @@
+eclipse.preferences.version=1
+org.eclipse.jdt.core.compiler.annotation.inheritNullAnnotations=disabled
+org.eclipse.jdt.core.compiler.annotation.missingNonNullByDefaultAnnotation=ignore
+org.eclipse.jdt.core.compiler.annotation.nonnull=org.eclipse.jdt.annotation.NonNull
+org.eclipse.jdt.core.compiler.annotation.nonnull.secondary=
+org.eclipse.jdt.core.compiler.annotation.nonnullbydefault=org.eclipse.jdt.annotation.NonNullByDefault
+org.eclipse.jdt.core.compiler.annotation.nonnullbydefault.secondary=
+org.eclipse.jdt.core.compiler.annotation.nullable=org.eclipse.jdt.annotation.Nullable
+org.eclipse.jdt.core.compiler.annotation.nullable.secondary=
+org.eclipse.jdt.core.compiler.annotation.nullanalysis=disabled
+org.eclipse.jdt.core.compiler.codegen.inlineJsrBytecode=enabled
+org.eclipse.jdt.core.compiler.codegen.methodParameters=do not generate
+org.eclipse.jdt.core.compiler.codegen.targetPlatform=1.8
+org.eclipse.jdt.core.compiler.codegen.unusedLocal=preserve
+org.eclipse.jdt.core.compiler.compliance=1.8
+org.eclipse.jdt.core.compiler.debug.lineNumber=generate
+org.eclipse.jdt.core.compiler.debug.localVariable=generate
+org.eclipse.jdt.core.compiler.debug.sourceFile=generate
+org.eclipse.jdt.core.compiler.doc.comment.support=enabled
+org.eclipse.jdt.core.compiler.problem.APILeak=warning
+org.eclipse.jdt.core.compiler.problem.annotationSuperInterface=ignore
+org.eclipse.jdt.core.compiler.problem.assertIdentifier=error
+org.eclipse.jdt.core.compiler.problem.autoboxing=ignore
+org.eclipse.jdt.core.compiler.problem.comparingIdentical=warning
+org.eclipse.jdt.core.compiler.problem.deadCode=warning
+org.eclipse.jdt.core.compiler.problem.deprecation=warning
+org.eclipse.jdt.core.compiler.problem.deprecationInDeprecatedCode=disabled
+org.eclipse.jdt.core.compiler.problem.deprecationWhenOverridingDeprecatedMethod=disabled
+org.eclipse.jdt.core.compiler.problem.discouragedReference=warning
+org.eclipse.jdt.core.compiler.problem.emptyStatement=warning
+org.eclipse.jdt.core.compiler.problem.enumIdentifier=error
+org.eclipse.jdt.core.compiler.problem.explicitlyClosedAutoCloseable=warning
+org.eclipse.jdt.core.compiler.problem.fallthroughCase=warning
+org.eclipse.jdt.core.compiler.problem.fatalOptionalError=disabled
+org.eclipse.jdt.core.compiler.problem.fieldHiding=warning
+org.eclipse.jdt.core.compiler.problem.finalParameterBound=warning
+org.eclipse.jdt.core.compiler.problem.finallyBlockNotCompletingNormally=warning
+org.eclipse.jdt.core.compiler.problem.forbiddenReference=warning
+org.eclipse.jdt.core.compiler.problem.hiddenCatchBlock=warning
+org.eclipse.jdt.core.compiler.problem.includeNullInfoFromAsserts=disabled
+org.eclipse.jdt.core.compiler.problem.incompatibleNonInheritedInterfaceMethod=warning
+org.eclipse.jdt.core.compiler.problem.incompleteEnumSwitch=warning
+org.eclipse.jdt.core.compiler.problem.indirectStaticAccess=ignore
+org.eclipse.jdt.core.compiler.problem.invalidJavadoc=warning
+org.eclipse.jdt.core.compiler.problem.invalidJavadocTags=enabled
+org.eclipse.jdt.core.compiler.problem.invalidJavadocTagsDeprecatedRef=enabled
+org.eclipse.jdt.core.compiler.problem.invalidJavadocTagsNotVisibleRef=enabled
+org.eclipse.jdt.core.compiler.problem.invalidJavadocTagsVisibility=private
+org.eclipse.jdt.core.compiler.problem.localVariableHiding=ignore
+org.eclipse.jdt.core.compiler.problem.methodWithConstructorName=warning
+org.eclipse.jdt.core.compiler.problem.missingDefaultCase=ignore
+org.eclipse.jdt.core.compiler.problem.missingDeprecatedAnnotation=ignore
+org.eclipse.jdt.core.compiler.problem.missingEnumCaseDespiteDefault=enabled
+org.eclipse.jdt.core.compiler.problem.missingHashCodeMethod=warning
+org.eclipse.jdt.core.compiler.problem.missingJavadocComments=ignore
+org.eclipse.jdt.core.compiler.problem.missingJavadocCommentsOverriding=disabled
+org.eclipse.jdt.core.compiler.problem.missingJavadocCommentsVisibility=public
+org.eclipse.jdt.core.compiler.problem.missingJavadocTagDescription=return_tag
+org.eclipse.jdt.core.compiler.problem.missingJavadocTags=ignore
+org.eclipse.jdt.core.compiler.problem.missingJavadocTagsMethodTypeParameters=disabled
+org.eclipse.jdt.core.compiler.problem.missingJavadocTagsOverriding=disabled
+org.eclipse.jdt.core.compiler.problem.missingJavadocTagsVisibility=protected
+org.eclipse.jdt.core.compiler.problem.missingOverrideAnnotation=warning
+org.eclipse.jdt.core.compiler.problem.missingOverrideAnnotationForInterfaceMethodImplementation=enabled
+org.eclipse.jdt.core.compiler.problem.missingSerialVersion=warning
+org.eclipse.jdt.core.compiler.problem.missingSynchronizedOnInheritedMethod=ignore
+org.eclipse.jdt.core.compiler.problem.noEffectAssignment=warning
+org.eclipse.jdt.core.compiler.problem.noImplicitStringConversion=warning
+org.eclipse.jdt.core.compiler.problem.nonExternalizedStringLiteral=ignore
+org.eclipse.jdt.core.compiler.problem.nonnullParameterAnnotationDropped=warning
+org.eclipse.jdt.core.compiler.problem.nonnullTypeVariableFromLegacyInvocation=warning
+org.eclipse.jdt.core.compiler.problem.nullAnnotationInferenceConflict=error
+org.eclipse.jdt.core.compiler.problem.nullReference=warning
+org.eclipse.jdt.core.compiler.problem.nullSpecViolation=error
+org.eclipse.jdt.core.compiler.problem.nullUncheckedConversion=warning
+org.eclipse.jdt.core.compiler.problem.overridingPackageDefaultMethod=warning
+org.eclipse.jdt.core.compiler.problem.parameterAssignment=ignore
+org.eclipse.jdt.core.compiler.problem.pessimisticNullAnalysisForFreeTypeVariables=warning
+org.eclipse.jdt.core.compiler.problem.possibleAccidentalBooleanAssignment=warning
+org.eclipse.jdt.core.compiler.problem.potentialNullReference=ignore
+org.eclipse.jdt.core.compiler.problem.potentiallyUnclosedCloseable=ignore
+org.eclipse.jdt.core.compiler.problem.rawTypeReference=warning
+org.eclipse.jdt.core.compiler.problem.redundantNullAnnotation=warning
+org.eclipse.jdt.core.compiler.problem.redundantNullCheck=warning
+org.eclipse.jdt.core.compiler.problem.redundantSpecificationOfTypeArguments=warning
+org.eclipse.jdt.core.compiler.problem.redundantSuperinterface=ignore
+org.eclipse.jdt.core.compiler.problem.reportMethodCanBePotentiallyStatic=ignore
+org.eclipse.jdt.core.compiler.problem.reportMethodCanBeStatic=ignore
+org.eclipse.jdt.core.compiler.problem.specialParameterHidingField=disabled
+org.eclipse.jdt.core.compiler.problem.staticAccessReceiver=warning
+org.eclipse.jdt.core.compiler.problem.suppressOptionalErrors=disabled
+org.eclipse.jdt.core.compiler.problem.suppressWarnings=enabled
+org.eclipse.jdt.core.compiler.problem.syntacticNullAnalysisForFields=disabled
+org.eclipse.jdt.core.compiler.problem.syntheticAccessEmulation=ignore
+org.eclipse.jdt.core.compiler.problem.terminalDeprecation=warning
+org.eclipse.jdt.core.compiler.problem.typeParameterHiding=warning
+org.eclipse.jdt.core.compiler.problem.unavoidableGenericTypeProblems=enabled
+org.eclipse.jdt.core.compiler.problem.uncheckedTypeOperation=warning
+org.eclipse.jdt.core.compiler.problem.unclosedCloseable=warning
+org.eclipse.jdt.core.compiler.problem.undocumentedEmptyBlock=ignore
+org.eclipse.jdt.core.compiler.problem.unhandledWarningToken=warning
+org.eclipse.jdt.core.compiler.problem.unlikelyCollectionMethodArgumentType=warning
+org.eclipse.jdt.core.compiler.problem.unlikelyCollectionMethodArgumentTypeStrict=disabled
+org.eclipse.jdt.core.compiler.problem.unlikelyEqualsArgumentType=warning
+org.eclipse.jdt.core.compiler.problem.unnecessaryElse=warning
+org.eclipse.jdt.core.compiler.problem.unnecessaryTypeCheck=warning
+org.eclipse.jdt.core.compiler.problem.unqualifiedFieldAccess=ignore
+org.eclipse.jdt.core.compiler.problem.unusedDeclaredThrownException=warning
+org.eclipse.jdt.core.compiler.problem.unusedDeclaredThrownExceptionExemptExceptionAndThrowable=enabled
+org.eclipse.jdt.core.compiler.problem.unusedDeclaredThrownExceptionIncludeDocCommentReference=enabled
+org.eclipse.jdt.core.compiler.problem.unusedDeclaredThrownExceptionWhenOverriding=disabled
+org.eclipse.jdt.core.compiler.problem.unusedExceptionParameter=ignore
+org.eclipse.jdt.core.compiler.problem.unusedImport=warning
+org.eclipse.jdt.core.compiler.problem.unusedLabel=warning
+org.eclipse.jdt.core.compiler.problem.unusedLocal=warning
+org.eclipse.jdt.core.compiler.problem.unusedObjectAllocation=ignore
+org.eclipse.jdt.core.compiler.problem.unusedParameter=warning
+org.eclipse.jdt.core.compiler.problem.unusedParameterIncludeDocCommentReference=enabled
+org.eclipse.jdt.core.compiler.problem.unusedParameterWhenImplementingAbstract=disabled
+org.eclipse.jdt.core.compiler.problem.unusedParameterWhenOverridingConcrete=disabled
+org.eclipse.jdt.core.compiler.problem.unusedPrivateMember=warning
+org.eclipse.jdt.core.compiler.problem.unusedTypeParameter=ignore
+org.eclipse.jdt.core.compiler.problem.unusedWarningToken=warning
+org.eclipse.jdt.core.compiler.problem.varargsArgumentNeedCast=warning
+org.eclipse.jdt.core.compiler.processAnnotations=enabled
+org.eclipse.jdt.core.compiler.source=1.8
diff --git a/WORKSPACE b/WORKSPACE
index 0cfa89f..7c2b01b 100644
--- a/WORKSPACE
+++ b/WORKSPACE
@@ -7,6 +7,15 @@
     #local_path = "/home/<user>/projects/bazlets",
 )
 
+# Snapshot Plugin API
+#load(
+#    "@com_googlesource_gerrit_bazlets//:gerrit_api_maven_local.bzl",
+#    "gerrit_api_maven_local",
+#)
+
+# Load snapshot Plugin API
+#gerrit_api_maven_local()
+
 # Release Plugin API
 load(
     "@com_googlesource_gerrit_bazlets//:gerrit_api.bzl",
diff --git a/bazlets.bzl b/bazlets.bzl
index de1b5d2..f089af4 100644
--- a/bazlets.bzl
+++ b/bazlets.bzl
@@ -1,10 +1,12 @@
+load("@bazel_tools//tools/build_defs/repo:git.bzl", "git_repository")
+
 NAME = "com_googlesource_gerrit_bazlets"
 
 def load_bazlets(
-        commit = None,
+        commit,
         local_path = None):
     if not local_path:
-        native.git_repository(
+        git_repository(
             name = NAME,
             remote = "https://gerrit.googlesource.com/bazlets",
             commit = commit,
diff --git a/config.md b/config.md
index 59d4a9c..a284e55 100644
--- a/config.md
+++ b/config.md
@@ -69,6 +69,7 @@
 rules applied to every change pushed, regardless of the folder or target branch.
 
 Example of assigning every configuration files to a specific owner group:
+
 ```yaml
 matchers:
 - suffix: *.config
diff --git a/external_plugin_deps.bzl b/external_plugin_deps.bzl
index a22be2b..7c6aa5c 100644
--- a/external_plugin_deps.bzl
+++ b/external_plugin_deps.bzl
@@ -1,35 +1,35 @@
 load("//tools/bzl:maven_jar.bzl", "maven_jar")
 
-JACKSON_REV = "2.8.9"
+JACKSON_VER = "2.9.7"
 
 def external_plugin_deps(omit_jackson_core = True):
     if not omit_jackson_core:
         maven_jar(
             name = "jackson-core",
-            artifact = "com.fasterxml.jackson.core:jackson-core:" + JACKSON_REV,
-            sha1 = "569b1752705da98f49aabe2911cc956ff7d8ed9d",
+            artifact = "com.fasterxml.jackson.core:jackson-core:" + JACKSON_VER,
+            sha1 = "4b7f0e0dc527fab032e9800ed231080fdc3ac015",
         )
 
     maven_jar(
         name = "jackson-databind",
-        artifact = "com.fasterxml.jackson.core:jackson-databind:" + JACKSON_REV,
-        sha1 = "4dfca3975be3c1a98eacb829e70f02e9a71bc159",
+        artifact = "com.fasterxml.jackson.core:jackson-databind:" + JACKSON_VER,
+        sha1 = "e6faad47abd3179666e89068485a1b88a195ceb7",
     )
 
     maven_jar(
         name = "jackson-annotations",
-        artifact = "com.fasterxml.jackson.core:jackson-annotations:" + JACKSON_REV,
-        sha1 = "e0e758381a6579cb2029dace23a7209b90ac7232",
+        artifact = "com.fasterxml.jackson.core:jackson-annotations:" + JACKSON_VER,
+        sha1 = "4b838e5c4fc17ac02f3293e9a558bb781a51c46d",
     )
 
     maven_jar(
         name = "jackson-dataformat-yaml",
-        artifact = "com.fasterxml.jackson.dataformat:jackson-dataformat-yaml:" + JACKSON_REV,
-        sha1 = "607f3253c20267e385c85f60c859760a73a29e37",
+        artifact = "com.fasterxml.jackson.dataformat:jackson-dataformat-yaml:" + JACKSON_VER,
+        sha1 = "a428edc4bb34a2da98a50eb759c26941d4e85960",
     )
 
     maven_jar(
         name = "snakeyaml",
-        artifact = "org.yaml:snakeyaml:1.17",
-        sha1 = "7a27ea250c5130b2922b86dea63cbb1cc10a660c",
+        artifact = "org.yaml:snakeyaml:1.23",
+        sha1 = "ec62d74fe50689c28c0ff5b35d3aebcaa8b5be68",
     )
diff --git a/owners-autoassign/BUCK b/owners-autoassign/BUCK
deleted file mode 100644
index 4b5f129..0000000
--- a/owners-autoassign/BUCK
+++ /dev/null
@@ -1,19 +0,0 @@
-include_defs('//plugins/owners-common/common.defs')
-include_defs('//lib/maven.defs')
-include_defs('//lib/prolog/prolog.defs')
-
-gerrit_plugin(
-  name = 'owners-autoassign',
-  srcs = glob([
-    'src/main/java/**/*.java',
-  ]),
-  manifest_entries = [
-    'Implementation-Title: Gerrit OWNERS autoassign plugin',
-    'Implementation-URL: https://gerrit.googlesource.com/plugins/owners',
-    'Gerrit-PluginName: owners-autoassign',
-    'Gerrit-Module: com.vmware.gerrit.owners.common.AutoassignModule',
-  ],
-  deps = [
-    '//plugins/owners-common:common',
-  ] + EXTERNAL_DEPS,
-)
diff --git a/owners-autoassign/BUILD b/owners-autoassign/BUILD
index adda79d..a835314 100644
--- a/owners-autoassign/BUILD
+++ b/owners-autoassign/BUILD
@@ -1,7 +1,4 @@
-load("//tools/bzl:junit.bzl", "junit_tests")
-load("//tools/bzl:plugin.bzl", "PLUGIN_DEPS", "PLUGIN_TEST_DEPS", "gerrit_plugin")
-load("//lib/prolog:prolog.bzl", "prolog_cafe_library")
-load("//owners-common:common.bzl", "EXTERNAL_DEPS")
+load("//tools/bzl:plugin.bzl", "gerrit_plugin")
 
 gerrit_plugin(
     name = "owners-autoassign",
diff --git a/owners-autoassign/src/main/java/com/vmware/gerrit/owners/common/ReviewerManager.java b/owners-autoassign/src/main/java/com/vmware/gerrit/owners/common/ReviewerManager.java
index b026390..5b0abe4 100644
--- a/owners-autoassign/src/main/java/com/vmware/gerrit/owners/common/ReviewerManager.java
+++ b/owners-autoassign/src/main/java/com/vmware/gerrit/owners/common/ReviewerManager.java
@@ -17,7 +17,8 @@
 package com.vmware.gerrit.owners.common;
 
 import com.google.gerrit.extensions.api.GerritApi;
-import com.google.gerrit.extensions.api.changes.ChangeApi;
+import com.google.gerrit.extensions.api.changes.AddReviewerInput;
+import com.google.gerrit.extensions.api.changes.ReviewInput;
 import com.google.gerrit.extensions.restapi.RestApiException;
 import com.google.gerrit.reviewdb.client.Account;
 import com.google.gerrit.reviewdb.client.Change;
@@ -26,6 +27,7 @@
 import com.google.gwtorm.server.OrmException;
 import com.google.inject.Inject;
 import com.google.inject.Singleton;
+import java.util.ArrayList;
 import java.util.Collection;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
@@ -46,12 +48,16 @@
   public void addReviewers(Change change, Collection<Account.Id> reviewers)
       throws ReviewerManagerException {
     try (ManualRequestContext ctx = requestContext.openAs(change.getOwner())) {
-
-      ChangeApi cApi = gApi.changes().id(change.getId().get());
+      // TODO(davido): Switch back to using changes API again,
+      // when it supports batch mode for adding reviewers
+      ReviewInput in = new ReviewInput();
+      in.reviewers = new ArrayList<>(reviewers.size());
       for (Account.Id account : reviewers) {
-        cApi.addReviewer(account.toString());
+        AddReviewerInput addReviewerInput = new AddReviewerInput();
+        addReviewerInput.reviewer = account.toString();
+        in.reviewers.add(addReviewerInput);
       }
-
+      gApi.changes().id(change.getId().get()).current().review(in);
     } catch (RestApiException | OrmException e) {
       log.error("Couldn't add reviewers to the change", e);
       throw new ReviewerManagerException(e);
diff --git a/owners-common/common.defs b/owners-common/common.defs
deleted file mode 100644
index 860a830..0000000
--- a/owners-common/common.defs
+++ /dev/null
@@ -1,8 +0,0 @@
-EXTERNAL_DEPS = [
-  '//plugins/owners-common' + i for i in [
-    ':jackson-core',
-    ':jackson-databind',
-    ':jackson-annotations',
-    ':jackson-dataformat-yaml',
-    ':snakeyaml',
-]]
diff --git a/owners-common/src/main/java/com/vmware/gerrit/owners/common/AccountsImpl.java b/owners-common/src/main/java/com/vmware/gerrit/owners/common/AccountsImpl.java
index 5bafdac..f22712a 100644
--- a/owners-common/src/main/java/com/vmware/gerrit/owners/common/AccountsImpl.java
+++ b/owners-common/src/main/java/com/vmware/gerrit/owners/common/AccountsImpl.java
@@ -14,6 +14,9 @@
 
 package com.vmware.gerrit.owners.common;
 
+import static com.google.gerrit.server.account.externalids.ExternalId.SCHEME_GERRIT;
+import static com.google.gerrit.server.account.externalids.ExternalId.SCHEME_MAILTO;
+
 import com.google.gerrit.common.errors.NoSuchGroupException;
 import com.google.gerrit.reviewdb.client.Account;
 import com.google.gerrit.reviewdb.client.Account.Id;
@@ -24,6 +27,7 @@
 import com.google.gerrit.server.account.AccountState;
 import com.google.gerrit.server.account.GroupCache;
 import com.google.gerrit.server.account.GroupMembers;
+import com.google.gerrit.server.account.externalids.ExternalId;
 import com.google.gerrit.server.group.InternalGroup;
 import com.google.gerrit.server.project.NoSuchProjectException;
 import com.google.gerrit.server.util.ManualRequestContext;
@@ -32,7 +36,6 @@
 import com.google.inject.Inject;
 import java.io.IOException;
 import java.util.Collections;
-import java.util.Objects;
 import java.util.Optional;
 import java.util.Set;
 import java.util.stream.Collectors;
@@ -101,15 +104,26 @@
   }
 
   private Set<Account.Id> findUserOrEmail(String nameOrEmail) {
-    try {
+    try (ManualRequestContext ctx = oneOffRequestContext.open()) {
       Set<Id> accountIds = resolver.findAll(nameOrEmail);
       if (accountIds.isEmpty()) {
         log.warn("User '{}' does not resolve to any account.", nameOrEmail);
         return accountIds;
       }
 
+      Set<Id> activeAccountIds =
+          accountIds.stream().filter(this::isActive).collect(Collectors.toSet());
+      if (activeAccountIds.isEmpty()) {
+        log.warn(
+            "User '{}' resolves to {} accounts {}, but none of them are active",
+            nameOrEmail,
+            accountIds.size(),
+            accountIds);
+        return activeAccountIds;
+      }
+
       Set<Id> fulllyMatchedAccountIds =
-          accountIds
+          activeAccountIds
               .stream()
               .filter(id -> isFullMatch(id, nameOrEmail))
               .collect(Collectors.toSet());
@@ -131,20 +145,41 @@
 
   private boolean isFullMatch(Account.Id id, String nameOrEmail) {
     AccountState account = byId.get(id);
-    return Objects.toString(account.getAccount().getFullName(), "")
-            .trim()
-            .equalsIgnoreCase(nameOrEmail)
+    return isFullNameMatch(account, nameOrEmail)
         || account
             .getExternalIds()
             .stream()
-            .anyMatch(
-                extId ->
-                    getSchemeRest(extId.key().scheme(), extId.key().get())
-                        .trim()
-                        .equalsIgnoreCase(nameOrEmail));
+            .anyMatch(eid -> isEMailMatch(eid, nameOrEmail) || isUsernameMatch(eid, nameOrEmail));
   }
 
-  private String getSchemeRest(String scheme, String key) {
-    return null != scheme ? key.substring(scheme.length() + 1) : key;
+  private boolean isFullNameMatch(AccountState account, String fullName) {
+    return Optional.ofNullable(account.getAccount().getFullName())
+        .filter(n -> n.trim().equalsIgnoreCase(fullName))
+        .isPresent();
+  }
+
+  private boolean isUsernameMatch(ExternalId externalId, String username) {
+    return keySchemeRest(SCHEME_GERRIT, externalId.key())
+        .filter(name -> name.equals(username))
+        .isPresent();
+  }
+
+  private boolean isEMailMatch(ExternalId externalId, String email) {
+    ExternalId.Key externalKey = externalId.key();
+    return OptionalUtils.combine(
+            Optional.ofNullable(externalId.email()).filter(mail -> mail.equalsIgnoreCase(email)),
+            keySchemeRest(SCHEME_MAILTO, externalKey).filter(mail -> mail.equalsIgnoreCase(email)))
+        .isPresent();
+  }
+
+  private boolean isActive(Account.Id accountId) {
+    return byId.get(accountId).getAccount().isActive();
+  }
+
+  private Optional<String> keySchemeRest(String scheme, ExternalId.Key key) {
+    if (scheme != null && key.isScheme(scheme)) {
+      return Optional.of(key.get().substring(scheme.length() + 1));
+    }
+    return Optional.empty();
   }
 }
diff --git a/owners-common/src/main/java/com/vmware/gerrit/owners/common/OptionalUtils.java b/owners-common/src/main/java/com/vmware/gerrit/owners/common/OptionalUtils.java
new file mode 100644
index 0000000..7a6f83c
--- /dev/null
+++ b/owners-common/src/main/java/com/vmware/gerrit/owners/common/OptionalUtils.java
@@ -0,0 +1,24 @@
+// Copyright (C) 2017 The Android Open Source Project
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+package com.vmware.gerrit.owners.common;
+
+import java.util.Optional;
+
+public class OptionalUtils {
+
+  public static <T> Optional<T> combine(Optional<T> firstChoice, Optional<T> secondChoice) {
+    return Optional.ofNullable(firstChoice.orElse(secondChoice.orElse(null)));
+  }
+}
diff --git a/owners-common/src/main/java/com/vmware/gerrit/owners/common/PathOwners.java b/owners-common/src/main/java/com/vmware/gerrit/owners/common/PathOwners.java
index 0e3da7c..614ac4c 100644
--- a/owners-common/src/main/java/com/vmware/gerrit/owners/common/PathOwners.java
+++ b/owners-common/src/main/java/com/vmware/gerrit/owners/common/PathOwners.java
@@ -16,6 +16,8 @@
 
 package com.vmware.gerrit.owners.common;
 
+import static com.google.gerrit.reviewdb.client.Patch.COMMIT_MSG;
+import static com.google.gerrit.reviewdb.client.Patch.MERGE_LIST;
 import static com.vmware.gerrit.owners.common.JgitWrapper.getBlobAsBytes;
 
 import com.google.common.collect.Maps;
@@ -220,9 +222,10 @@
   private Set<String> getModifiedPaths() {
     Set<String> paths = Sets.newHashSet();
     for (PatchListEntry patch : patchList.getPatches()) {
-      // Ignore commit message
-      if (!patch.getNewName().equals("/COMMIT_MSG")) {
-        paths.add(patch.getNewName());
+      // Ignore commit message and Merge List
+      String newName = patch.getNewName();
+      if (!COMMIT_MSG.equals(newName) && !MERGE_LIST.equals(newName)) {
+        paths.add(newName);
 
         // If a file was moved then we need approvals for old and new
         // path
diff --git a/owners-common/src/test/java/com/vmware/gerrit/owners/common/RegexMatcherTest.java b/owners-common/src/test/java/com/vmware/gerrit/owners/common/RegexMatcherTest.java
index 747912b..8d3aa0f 100644
--- a/owners-common/src/test/java/com/vmware/gerrit/owners/common/RegexMatcherTest.java
+++ b/owners-common/src/test/java/com/vmware/gerrit/owners/common/RegexMatcherTest.java
@@ -15,7 +15,8 @@
 
 package com.vmware.gerrit.owners.common;
 
-import static org.junit.Assert.*;
+import static org.junit.Assert.assertFalse;
+import static org.junit.Assert.assertTrue;
 
 import org.junit.Test;
 
diff --git a/owners/BUCK b/owners/BUCK
deleted file mode 100644
index 5640fe1..0000000
--- a/owners/BUCK
+++ /dev/null
@@ -1,43 +0,0 @@
-include_defs('//bucklets/gerrit_plugin.bucklet')
-include_defs('//lib/prolog/prolog.defs')
-include_defs('//plugins/owners-common/common.defs')
-
-# buck is unhappy to build a gerrit_plugin with no source files.
-# On the other side, gerrit-owners-prolog-rules needs to be built after all the java files have been
-# compiled. For this reason we have a stub class that has no content and just makes buck happy.
-COMPILE_STUB = ['src/main/java/com/vmware/gerrit/owners/CompileStub.java']
-
-java_library(
-  name = 'gerrit-owners-lib',
-  srcs = glob([
-    'src/main/java/**/*.java',
-  ], excludes=COMPILE_STUB),
-  provided_deps = [
-    '//plugins/owners-common:common',
-  ] + GERRIT_PLUGIN_API + EXTERNAL_DEPS,
-)
-
-prolog_cafe_library(
-  name = 'gerrit-owners-prolog-rules',
-  srcs = glob(['src/main/prolog/*.pl']),
-  deps = [
-    ':gerrit-owners-lib',
-    '//gerrit-server/src/main/prolog:common',
-  ],
-)
-
-gerrit_plugin(
-  name = 'owners',
-  srcs = COMPILE_STUB,
-  manifest_entries = [
-    'Implementation-Title: Gerrit OWNERS plugin',
-    'Implementation-URL: https://gerrit.googlesource.com/plugins/owners',
-    'Gerrit-PluginName: owners',
-    'Gerrit-Module: com.vmware.gerrit.owners.OwnersModule',
-  ],
-  deps = [
-    ':gerrit-owners-lib',
-    ':gerrit-owners-prolog-rules',
-    '//plugins/owners-common:common',
-  ] + EXTERNAL_DEPS,
-)
diff --git a/owners/BUILD b/owners/BUILD
index 3a87774..2e56051 100644
--- a/owners/BUILD
+++ b/owners/BUILD
@@ -1,30 +1,35 @@
-load("//tools/bzl:junit.bzl", "junit_tests")
-load("//tools/bzl:plugin.bzl", "PLUGIN_DEPS", "PLUGIN_DEPS_NEVERLINK", "PLUGIN_TEST_DEPS", "gerrit_plugin")
+load("//tools/bzl:plugin.bzl", "PLUGIN_DEPS_NEVERLINK", "gerrit_plugin")
 load("//lib/prolog:prolog.bzl", "prolog_cafe_library")
-load("//owners-common:common.bzl", "EXTERNAL_DEPS")
+
+PROLOG_PREDICATES = glob(["src/main/java/gerrit_owners/**/*.java"]) + [
+    "src/main/java/com/vmware/gerrit/owners/OwnersStoredValues.java",
+]
 
 java_library(
-    name = "gerrit-owners-lib",
-    srcs = glob([
-        "src/main/java/**/*.java",
-    ]),
+    name = "gerrit-owners-predicates",
+    srcs = PROLOG_PREDICATES,
     deps = [
         "@prolog-runtime//jar:neverlink",
         "//owners-common:owners-common",
-    ] + PLUGIN_DEPS_NEVERLINK + EXTERNAL_DEPS,
+    ] + PLUGIN_DEPS_NEVERLINK,
 )
 
 prolog_cafe_library(
     name = "gerrit-owners-prolog-rules",
     srcs = glob(["src/main/prolog/*.pl"]),
     deps = PLUGIN_DEPS_NEVERLINK + [
-        ":gerrit-owners-lib",
+        ":gerrit-owners-predicates",
     ],
 )
 
 gerrit_plugin(
     name = "owners",
-    srcs = ["src/main/java/com/vmware/gerrit/owners/CompileStub.java"],
+    srcs = glob(
+        [
+            "src/main/java/**/*.java",
+        ],
+        exclude = PROLOG_PREDICATES,
+    ),
     manifest_entries = [
         "Implementation-Title: Gerrit OWNERS plugin",
         "Implementation-URL: https://gerrit.googlesource.com/plugins/owners",
@@ -32,10 +37,10 @@
         "Gerrit-Module: com.vmware.gerrit.owners.OwnersModule",
         "Gerrit-ApiVersion: 2.14-SNAPSHOT",
     ],
-    resources = glob(["src/main/**/*"]),
+    resources = glob(["src/main/resources/**/*"]),
     deps = [
-        ":gerrit-owners-lib",
+        ":gerrit-owners-predicates",
         ":gerrit-owners-prolog-rules",
         "//owners-common",
-    ] + EXTERNAL_DEPS,
+    ],
 )
diff --git a/owners/src/main/java/com/vmware/gerrit/owners/OwnersModule.java b/owners/src/main/java/com/vmware/gerrit/owners/OwnersModule.java
index 3b5b567..c4a5f80 100644
--- a/owners/src/main/java/com/vmware/gerrit/owners/OwnersModule.java
+++ b/owners/src/main/java/com/vmware/gerrit/owners/OwnersModule.java
@@ -22,6 +22,8 @@
 public class OwnersModule extends AbstractModule {
   @Override
   protected void configure() {
-    DynamicSet.bind(binder(), PredicateProvider.class).to(OwnerPredicateProvider.class);
+    DynamicSet.bind(binder(), PredicateProvider.class)
+        .to(OwnerPredicateProvider.class)
+        .asEagerSingleton();
   }
 }