Merge branch 'stable-3.4'

* stable-3.4:
  Fix REST-API documentation for HTTP GET files-owners
  Introduce GenericMatcher for file-based regex fallback logic
  Filter out null parent projects when fetching the owners of a file
  Fix NPE when returning group owners without expansion
  Inherit OWNERS from all parent projects
  Add inheritance from parent project
  Refactor GetFilesOwnersIT and make FilesOwnersResponse public
  Introduce expandGroups option for disabling groups expansion
  Add labels information in files-owners API
  REST API to expose owners of each file
  Allow disabling the owners auto-assigned on a per-branch basis
  DRY out the logic to read the owners plugin config
  Allow disabling the owners on a per-branch basis

Also fix an error-prone issue in GetFilesOwners where the map
of an Optional was using a side effect implicitly, ignoring
the result.

Change-Id: I6e3de0de278475274d7f97935cf4f7b9d31a079e
diff --git a/external_plugin_deps.bzl b/external_plugin_deps.bzl
index bca48e4..5ad1930 100644
--- a/external_plugin_deps.bzl
+++ b/external_plugin_deps.bzl
@@ -2,13 +2,12 @@
 
 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_VER,
-            sha1 = "4b7f0e0dc527fab032e9800ed231080fdc3ac015",
-        )
+def external_plugin_deps():
+    maven_jar(
+        name = "jackson-core",
+        artifact = "com.fasterxml.jackson.core:jackson-core:" + JACKSON_VER,
+        sha1 = "4b7f0e0dc527fab032e9800ed231080fdc3ac015",
+    )
 
     maven_jar(
         name = "jackson-databind",
diff --git a/owners-autoassign/BUILD b/owners-autoassign/BUILD
index 024be42..4aa4cec 100644
--- a/owners-autoassign/BUILD
+++ b/owners-autoassign/BUILD
@@ -15,8 +15,8 @@
     ],
     resources = glob(["src/main/**/*"]),
     deps = [
+        ":owners-api-neverlink",
         "//owners-common",
-        "//plugins/owners-api",
     ],
 )
 
@@ -28,10 +28,16 @@
     visibility = ["//visibility:public"],
     deps = PLUGIN_DEPS_NEVERLINK + [
         "//owners-common",
-        "//plugins/owners-api",
+        ":owners-api-neverlink",
     ],
 )
 
+java_library(
+    name = "owners-api-neverlink",
+    neverlink = 1,
+    exports = ["//plugins/owners-api"],
+)
+
 junit_tests(
     name = "owners_autoassign_tests",
     testonly = 1,
diff --git a/owners-autoassign/src/main/java/com/googlesource/gerrit/owners/common/AutoassignModule.java b/owners-autoassign/src/main/java/com/googlesource/gerrit/owners/common/AutoassignModule.java
index 4ed43b2..931c05a 100644
--- a/owners-autoassign/src/main/java/com/googlesource/gerrit/owners/common/AutoassignModule.java
+++ b/owners-autoassign/src/main/java/com/googlesource/gerrit/owners/common/AutoassignModule.java
@@ -16,14 +16,35 @@
 
 package com.googlesource.gerrit.owners.common;
 
+import com.google.common.annotations.VisibleForTesting;
 import com.google.gerrit.extensions.events.GitReferenceUpdatedListener;
+import com.google.gerrit.extensions.registration.DynamicItem;
 import com.google.gerrit.extensions.registration.DynamicSet;
 import com.google.inject.AbstractModule;
+import com.google.inject.Inject;
+import com.google.inject.Scopes;
+import com.googlesource.gerrit.owners.api.OwnersAttentionSet;
 
 public class AutoassignModule extends AbstractModule {
+
+  private final Class<? extends OwnersAttentionSet> ownersAttentionSetImpl;
+
+  @Inject
+  public AutoassignModule() {
+    this(DefaultAddAllOwnersToAttentionSet.class);
+  }
+
+  @VisibleForTesting
+  public AutoassignModule(Class<? extends OwnersAttentionSet> ownersAttentionSetImpl) {
+    this.ownersAttentionSetImpl = ownersAttentionSetImpl;
+  }
+
   @Override
   protected void configure() {
     DynamicSet.bind(binder(), GitReferenceUpdatedListener.class).to(GitRefListener.class);
+    DynamicItem.bind(binder(), OwnersAttentionSet.class)
+        .to(ownersAttentionSetImpl)
+        .in(Scopes.SINGLETON);
     install(new AutoassignConfigModule());
   }
 }
diff --git a/owners-autoassign/src/main/java/com/googlesource/gerrit/owners/common/DefaultAddAllOwnersToAttentionSet.java b/owners-autoassign/src/main/java/com/googlesource/gerrit/owners/common/DefaultAddAllOwnersToAttentionSet.java
new file mode 100644
index 0000000..d53a239
--- /dev/null
+++ b/owners-autoassign/src/main/java/com/googlesource/gerrit/owners/common/DefaultAddAllOwnersToAttentionSet.java
@@ -0,0 +1,29 @@
+// Copyright (C) 2021 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.googlesource.gerrit.owners.common;
+
+import com.google.gerrit.entities.Account.Id;
+import com.google.gerrit.extensions.common.ChangeInfo;
+import com.googlesource.gerrit.owners.api.OwnersAttentionSet;
+import java.util.Collection;
+
+class DefaultAddAllOwnersToAttentionSet implements OwnersAttentionSet {
+
+  @Override
+  public Collection<Id> addToAttentionSet(ChangeInfo changeInfo, Collection<Id> owners) {
+    return owners;
+  }
+}
diff --git a/owners-autoassign/src/main/java/com/googlesource/gerrit/owners/common/GitRefListener.java b/owners-autoassign/src/main/java/com/googlesource/gerrit/owners/common/GitRefListener.java
index bae340a..5be3aa0 100644
--- a/owners-autoassign/src/main/java/com/googlesource/gerrit/owners/common/GitRefListener.java
+++ b/owners-autoassign/src/main/java/com/googlesource/gerrit/owners/common/GitRefListener.java
@@ -40,7 +40,8 @@
 import com.google.gerrit.server.notedb.ChangeNotes;
 import com.google.gerrit.server.notedb.ChangeNotesCommit;
 import com.google.gerrit.server.notedb.ChangeNotesCommit.ChangeNotesRevWalk;
-import com.google.gerrit.server.patch.PatchList;
+import com.google.gerrit.server.patch.DiffSummary;
+import com.google.gerrit.server.patch.DiffSummaryKey;
 import com.google.gerrit.server.patch.PatchListCache;
 import com.google.gerrit.server.patch.PatchListKey;
 import com.google.gerrit.server.patch.PatchListNotAvailableException;
@@ -224,7 +225,7 @@
                           .collect(Collectors.toList()))
               .orElse(Collections.emptyList());
 
-      PatchList patchList = getPatchList(repository, event, change);
+      DiffSummary patchList = getDiffSummary(repository, event, change);
       if (patchList != null) {
         PathOwners owners =
             new PathOwners(
@@ -252,7 +253,7 @@
     }
   }
 
-  private PatchList getPatchList(Repository repository, Event event, ChangeInfo change) {
+  private DiffSummary getDiffSummary(Repository repository, Event event, ChangeInfo change) {
     ObjectId newId = null;
     PatchListKey plKey;
     try {
@@ -266,7 +267,8 @@
         }
         plKey = PatchListKey.againstCommit(null, newId, IGNORE_NONE);
       }
-      return patchListCache.get(plKey, Project.nameKey(change.project));
+      return patchListCache.getDiffSummary(
+          DiffSummaryKey.fromPatchListKey(plKey), Project.nameKey(change.project));
     } catch (PatchListNotAvailableException | IOException e) {
       logger.warn("Could not load patch list for change {}", change.id, e);
     }
diff --git a/owners-autoassign/src/main/java/com/googlesource/gerrit/owners/common/ReviewerManager.java b/owners-autoassign/src/main/java/com/googlesource/gerrit/owners/common/ReviewerManager.java
index ea1975c..34d6e49 100644
--- a/owners-autoassign/src/main/java/com/googlesource/gerrit/owners/common/ReviewerManager.java
+++ b/owners-autoassign/src/main/java/com/googlesource/gerrit/owners/common/ReviewerManager.java
@@ -21,10 +21,10 @@
 import com.google.gerrit.entities.Project;
 import com.google.gerrit.entities.Project.NameKey;
 import com.google.gerrit.extensions.api.GerritApi;
-import com.google.gerrit.extensions.api.changes.AddReviewerInput;
 import com.google.gerrit.extensions.api.changes.AttentionSetInput;
 import com.google.gerrit.extensions.api.changes.ChangeApi;
 import com.google.gerrit.extensions.api.changes.ReviewInput;
+import com.google.gerrit.extensions.api.changes.ReviewerInput;
 import com.google.gerrit.extensions.client.ReviewerState;
 import com.google.gerrit.extensions.common.ChangeInfo;
 import com.google.gerrit.extensions.registration.DynamicItem;
@@ -58,15 +58,6 @@
   private final IdentifiedUser.GenericFactory userFactory;
   private final ChangeData.Factory changeDataFactory;
   private final PermissionBackend permissionBackend;
-
-  /**
-   * TODO: The optional injection here is needed for keeping backward compatibility with existing
-   * setups that do not have the owners-api.jar configured as Gerrit libModule.
-   *
-   * <p>Once merged to master, the optional injection can go and this can be moved as extra argument
-   * in the constructor.
-   */
-  @Inject(optional = true)
   private DynamicItem<OwnersAttentionSet> ownersForAttentionSet;
 
   private final AutoassignConfig cfg;
@@ -76,14 +67,16 @@
       OneOffRequestContext requestContext,
       GerritApi gApi,
       IdentifiedUser.GenericFactory userFactory,
-      ChangeData.Factory changeDataFactory,
       PermissionBackend permissionBackend,
+      ChangeData.Factory changeDataFactory,
+      DynamicItem<OwnersAttentionSet> ownersForAttentionSet,
       AutoassignConfig cfg) {
     this.requestContext = requestContext;
     this.gApi = gApi;
     this.userFactory = userFactory;
     this.changeDataFactory = changeDataFactory;
     this.permissionBackend = permissionBackend;
+    this.ownersForAttentionSet = ownersForAttentionSet;
     this.cfg = cfg;
   }
 
@@ -107,7 +100,7 @@
         Collection<Account.Id> validOwnersForAttentionSet = new ArrayList<>(accountsIds.size());
         for (Account.Id account : accountsIds) {
           if (!currentReviewers.contains(account.get()) && isVisibleTo(changeInfo, account)) {
-            AddReviewerInput addReviewerInput = new AddReviewerInput();
+            ReviewerInput addReviewerInput = new ReviewerInput();
             addReviewerInput.reviewer = account.toString();
             addReviewerInput.state = reviewerState;
             in.reviewers.add(addReviewerInput);
@@ -117,7 +110,8 @@
             }
           } else {
             log.warn(
-                "Not adding account {} as reviewer to change {} because the associated ref is not visible",
+                "Not adding account {} as reviewer to change {} because the associated ref is not"
+                    + " visible",
                 account,
                 changeInfo._number);
           }
@@ -137,7 +131,7 @@
 
         in.ignoreAutomaticAttentionSetRules = true;
         in.addToAttentionSet =
-            reviewersAccounts.stream()
+            ownersForAttentionSet.get().addToAttentionSet(changeInfo, reviewersAccounts).stream()
                 .map(
                     (reviewer) ->
                         new AttentionSetInput(
diff --git a/owners-autoassign/src/main/resources/Documentation/attention-set.md b/owners-autoassign/src/main/resources/Documentation/attention-set.md
index 7ad9a55..0ae7fa5 100644
--- a/owners-autoassign/src/main/resources/Documentation/attention-set.md
+++ b/owners-autoassign/src/main/resources/Documentation/attention-set.md
@@ -11,7 +11,7 @@
 a generic interface that can be used to customize Gerrit's default
 attention-set behaviour.
 
-## owner-api setup
+## owners-api setup
 
 Copy the `owners-api.jar` libModule into the $GERRIT_SITE/lib directory
 and add the following entry to `gerrit.config`:
diff --git a/owners-autoassign/src/main/resources/Documentation/config.md b/owners-autoassign/src/main/resources/Documentation/config.md
index 7de8eec..a99e3b1 100644
--- a/owners-autoassign/src/main/resources/Documentation/config.md
+++ b/owners-autoassign/src/main/resources/Documentation/config.md
@@ -1,3 +1,13 @@
+## Setup
+
+The owners-autoassign plugin depends on the shared library `owners-api.jar`
+which needs to be installed into the `$GERRIT_SITE/lib` and requires a
+restart of the Gerrit service.
+
+Once the `owners-api.jar` is loaded at Gerrit startup, the `owners-autoassign.jar`
+file can be installed like a regular Gerrit plugin, by being dropped to the
+`GRRIT_SITE/plugins` directory or installed through the plugin manager.
+
 ## Global configuration
 
 The global plugin configuration is read from the `$GERRIT_SITE/etc/owners-autoassign.config`
diff --git a/owners-autoassign/src/test/java/com/googlesource/gerrit/owners/common/AbstractAutoassignIT.java b/owners-autoassign/src/test/java/com/googlesource/gerrit/owners/common/AbstractAutoassignIT.java
index a38b7a3..52fc441 100644
--- a/owners-autoassign/src/test/java/com/googlesource/gerrit/owners/common/AbstractAutoassignIT.java
+++ b/owners-autoassign/src/test/java/com/googlesource/gerrit/owners/common/AbstractAutoassignIT.java
@@ -24,9 +24,9 @@
 import com.google.gerrit.acceptance.UseLocalDisk;
 import com.google.gerrit.acceptance.config.GlobalPluginConfig;
 import com.google.gerrit.common.RawInputUtil;
-import com.google.gerrit.extensions.api.changes.AddReviewerInput;
 import com.google.gerrit.extensions.api.changes.ChangeApi;
 import com.google.gerrit.extensions.api.changes.ChangeEditApi;
+import com.google.gerrit.extensions.api.changes.ReviewerInput;
 import com.google.gerrit.extensions.client.ReviewerState;
 import com.google.gerrit.extensions.common.AccountInfo;
 import com.google.gerrit.extensions.common.ChangeInfo;
@@ -35,6 +35,8 @@
 import com.google.gerrit.server.project.ProjectConfig;
 import com.google.inject.AbstractModule;
 import com.google.inject.Inject;
+import com.google.inject.Module;
+import com.googlesource.gerrit.owners.api.OwnersApiModule;
 import java.util.Collection;
 import java.util.HashMap;
 import java.util.List;
@@ -73,6 +75,11 @@
   }
 
   @Override
+  public Module createModule() {
+    return new OwnersApiModule();
+  }
+
+  @Override
   public void setUpTestPlugin() throws Exception {
     super.setUpTestPlugin();
 
@@ -145,7 +152,7 @@
     assertThat(reviewers).hasSize(1);
 
     // Switch user from CC to Reviewer or the other way around
-    AddReviewerInput switchReviewerInput = new AddReviewerInput();
+    ReviewerInput switchReviewerInput = new ReviewerInput();
     switchReviewerInput.reviewer = ownerEmail;
     switchReviewerInput.state =
         assignedUserState == ReviewerState.REVIEWER ? ReviewerState.CC : ReviewerState.REVIEWER;
diff --git a/owners-autoassign/src/test/java/com/googlesource/gerrit/owners/common/OwnersAutoassignWithAttentionSetIT.java b/owners-autoassign/src/test/java/com/googlesource/gerrit/owners/common/OwnersAutoassignWithAttentionSetIT.java
index 36795a6..56cf33a 100644
--- a/owners-autoassign/src/test/java/com/googlesource/gerrit/owners/common/OwnersAutoassignWithAttentionSetIT.java
+++ b/owners-autoassign/src/test/java/com/googlesource/gerrit/owners/common/OwnersAutoassignWithAttentionSetIT.java
@@ -30,12 +30,10 @@
 import com.google.gerrit.extensions.api.groups.GroupInput;
 import com.google.gerrit.extensions.client.ReviewerState;
 import com.google.gerrit.extensions.common.ChangeInfo;
-import com.google.gerrit.extensions.registration.DynamicItem;
 import com.google.gerrit.extensions.restapi.RestApiException;
 import com.google.inject.AbstractModule;
 import com.google.inject.Inject;
 import com.google.inject.Module;
-import com.google.inject.Scopes;
 import com.googlesource.gerrit.owners.api.OwnersApiModule;
 import com.googlesource.gerrit.owners.api.OwnersAttentionSet;
 import java.util.Collection;
@@ -58,11 +56,7 @@
   public static class TestModule extends AbstractModule {
     @Override
     protected void configure() {
-      install(new AutoassignModule());
-
-      DynamicItem.bind(binder(), OwnersAttentionSet.class)
-          .to(SelectFirstOwnerForAttentionSet.class)
-          .in(Scopes.SINGLETON);
+      install(new AutoassignModule(SelectFirstOwnerForAttentionSet.class));
     }
   }
 
@@ -88,7 +82,7 @@
 
   @Test
   public void shouldAddToAttentionSetOneUserIfAnotherUserHasNoPermission() throws Exception {
-    TestAccount userWithAccessToProject = accountCreator.user();
+    TestAccount userWithAccessToProject = accountCreator.user1();
     TestAccount userWithNoAccessToProject = accountCreator.user2();
 
     AccountGroup.UUID groupWithNoAccessToProject =
diff --git a/owners-autoassign/src/test/java/com/vmware/gerrit/owners/common/GitRefListenerIT.java b/owners-autoassign/src/test/java/com/vmware/gerrit/owners/common/GitRefListenerIT.java
index 2cbceda..884c986 100644
--- a/owners-autoassign/src/test/java/com/vmware/gerrit/owners/common/GitRefListenerIT.java
+++ b/owners-autoassign/src/test/java/com/vmware/gerrit/owners/common/GitRefListenerIT.java
@@ -35,6 +35,8 @@
 import com.google.gerrit.server.util.ThreadLocalRequestContext;
 import com.google.inject.AbstractModule;
 import com.google.inject.Inject;
+import com.google.inject.Module;
+import com.googlesource.gerrit.owners.api.OwnersApiModule;
 import com.googlesource.gerrit.owners.common.AutoassignConfigModule;
 import java.util.HashMap;
 import java.util.Map;
@@ -54,6 +56,11 @@
   String anOldObjectId = "anOldRef";
   String aNewObjectId = "aNewRef";
 
+  @Override
+  public Module createModule() {
+    return new OwnersApiModule();
+  }
+
   public static class TestModule extends AbstractModule {
     @Override
     protected void configure() {
diff --git a/owners-common/common.bzl b/owners-common/common.bzl
index c571145..d2ce9f5 100644
--- a/owners-common/common.bzl
+++ b/owners-common/common.bzl
@@ -1,5 +1,5 @@
 EXTERNAL_DEPS = [
-    "@jackson-core//jar:neverlink",
+    "@jackson-core//jar",
     "@jackson-databind//jar",
     "@jackson-annotations//jar",
     "@jackson-dataformat-yaml//jar",
diff --git a/owners-common/src/main/java/com/googlesource/gerrit/owners/common/PathOwners.java b/owners-common/src/main/java/com/googlesource/gerrit/owners/common/PathOwners.java
index 6159e08..5583dc9 100644
--- a/owners-common/src/main/java/com/googlesource/gerrit/owners/common/PathOwners.java
+++ b/owners-common/src/main/java/com/googlesource/gerrit/owners/common/PathOwners.java
@@ -21,6 +21,7 @@
 import static com.googlesource.gerrit.owners.common.JgitWrapper.getBlobAsBytes;
 
 import com.google.common.collect.ImmutableList;
+import com.google.common.collect.ImmutableSet;
 import com.google.common.collect.Maps;
 import com.google.common.collect.Multimaps;
 import com.google.common.collect.SetMultimap;
@@ -32,8 +33,8 @@
 import com.google.gerrit.entities.Project;
 import com.google.gerrit.entities.RefNames;
 import com.google.gerrit.server.git.GitRepositoryManager;
-import com.google.gerrit.server.patch.PatchList;
-import com.google.gerrit.server.patch.PatchListEntry;
+import com.google.gerrit.server.patch.DiffSummary;
+import com.google.gerrit.server.patch.filediff.FileDiffOutput;
 import java.io.IOException;
 import java.util.Collection;
 import java.util.Collections;
@@ -73,10 +74,10 @@
 
   private final List<Project.NameKey> parentProjectsNames;
 
-  private final PatchList patchList;
-
   private final ConfigurationParser parser;
 
+  private final Set<String> modifiedPaths;
+
   private final Accounts accounts;
 
   private final GitRepositoryManager repositoryManager;
@@ -95,12 +96,48 @@
       Repository repository,
       List<Project.NameKey> parentProjectsNames,
       Optional<String> branchWhenEnabled,
-      PatchList patchList,
+      Map<String, FileDiffOutput> fileDiffMap,
+      boolean expandGroups) {
+    this(
+        accounts,
+        repositoryManager,
+        repository,
+        parentProjectsNames,
+        branchWhenEnabled,
+        getModifiedPaths(fileDiffMap),
+        expandGroups);
+  }
+
+  public PathOwners(
+      Accounts accounts,
+      GitRepositoryManager repositoryManager,
+      Repository repository,
+      List<Project.NameKey> parentProjectsNames,
+      Optional<String> branchWhenEnabled,
+      DiffSummary diffSummary,
+      boolean expandGroups) {
+    this(
+        accounts,
+        repositoryManager,
+        repository,
+        parentProjectsNames,
+        branchWhenEnabled,
+        ImmutableSet.copyOf(diffSummary.getPaths()),
+        expandGroups);
+  }
+
+  public PathOwners(
+      Accounts accounts,
+      GitRepositoryManager repositoryManager,
+      Repository repository,
+      List<Project.NameKey> parentProjectsNames,
+      Optional<String> branchWhenEnabled,
+      Set<String> modifiedPaths,
       boolean expandGroups) {
     this.repositoryManager = repositoryManager;
     this.repository = repository;
     this.parentProjectsNames = parentProjectsNames;
-    this.patchList = patchList;
+    this.modifiedPaths = modifiedPaths;
     this.parser = new ConfigurationParser(accounts);
     this.accounts = accounts;
     this.expandGroups = expandGroups;
@@ -112,7 +149,6 @@
     fileOwners = map.getFileOwners();
     fileGroupOwners = map.getFileGroupOwners();
   }
-
   /**
    * Returns a read only view of the paths to owners mapping.
    *
@@ -161,7 +197,6 @@
       PathOwnersEntry projectEntry = getPathOwnersEntry(repository, RefNames.REFS_CONFIG);
       PathOwnersEntry rootEntry = getPathOwnersEntry(repository, branch);
 
-      Set<String> modifiedPaths = getModifiedPaths();
       Map<String, PathOwnersEntry> entries = new HashMap<>();
       PathOwnersEntry currentEntry = null;
       for (String path : modifiedPaths) {
@@ -346,22 +381,22 @@
   }
 
   /**
-   * Parses the patch list for any paths that were modified.
+   * Parses the diff list for any paths that were modified.
    *
    * @return set of modified paths.
    */
-  private Set<String> getModifiedPaths() {
+  private static Set<String> getModifiedPaths(Map<String, FileDiffOutput> patchList) {
     Set<String> paths = Sets.newHashSet();
-    for (PatchListEntry patch : patchList.getPatches()) {
+    for (Map.Entry<String, FileDiffOutput> patch : patchList.entrySet()) {
       // Ignore commit message and Merge List
-      String newName = patch.getNewName();
+      String newName = patch.getKey();
       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
-        if (patch.getChangeType() == Patch.ChangeType.RENAMED) {
-          paths.add(patch.getOldName());
+        if (patch.getValue().changeType() == Patch.ChangeType.RENAMED) {
+          paths.add(patch.getValue().oldPath().get());
         }
       }
     }
diff --git a/owners/src/main/java/com/googlesource/gerrit/owners/OwnersStoredValues.java b/owners/src/main/java/com/googlesource/gerrit/owners/OwnersStoredValues.java
index 7181ab6..562d7cb 100644
--- a/owners/src/main/java/com/googlesource/gerrit/owners/OwnersStoredValues.java
+++ b/owners/src/main/java/com/googlesource/gerrit/owners/OwnersStoredValues.java
@@ -18,7 +18,7 @@
 
 import com.google.gerrit.entities.Project;
 import com.google.gerrit.server.git.GitRepositoryManager;
-import com.google.gerrit.server.patch.PatchList;
+import com.google.gerrit.server.patch.filediff.FileDiffOutput;
 import com.google.gerrit.server.project.ProjectState;
 import com.google.gerrit.server.rules.StoredValue;
 import com.google.gerrit.server.rules.StoredValues;
@@ -29,6 +29,7 @@
 import java.util.Arrays;
 import java.util.Collections;
 import java.util.List;
+import java.util.Map;
 import java.util.Optional;
 import org.eclipse.jgit.lib.Repository;
 import org.slf4j.Logger;
@@ -49,7 +50,7 @@
         new StoredValue<PathOwners>() {
           @Override
           protected PathOwners createValue(Prolog engine) {
-            PatchList patchList = StoredValues.PATCH_LIST.get(engine);
+            Map<String, FileDiffOutput> patchList = StoredValues.DIFF_LIST.get(engine);
             Repository repository = StoredValues.REPOSITORY.get(engine);
             ProjectState projectState = StoredValues.PROJECT_STATE.get(engine);
             GitRepositoryManager gitRepositoryManager = StoredValues.REPO_MANAGER.get(engine);
diff --git a/owners/src/main/java/com/googlesource/gerrit/owners/restapi/GetFilesOwners.java b/owners/src/main/java/com/googlesource/gerrit/owners/restapi/GetFilesOwners.java
index 47e542f..475f1cd 100644
--- a/owners/src/main/java/com/googlesource/gerrit/owners/restapi/GetFilesOwners.java
+++ b/owners/src/main/java/com/googlesource/gerrit/owners/restapi/GetFilesOwners.java
@@ -33,9 +33,9 @@
 import com.google.gerrit.server.account.AccountCache;
 import com.google.gerrit.server.change.RevisionResource;
 import com.google.gerrit.server.git.GitRepositoryManager;
-import com.google.gerrit.server.patch.PatchList;
 import com.google.gerrit.server.patch.PatchListCache;
 import com.google.gerrit.server.project.ProjectCache;
+import com.google.gerrit.server.query.change.ChangeData;
 import com.google.inject.Inject;
 import com.google.inject.Singleton;
 import com.googlesource.gerrit.owners.common.Accounts;
@@ -61,6 +61,7 @@
   private final GitRepositoryManager repositoryManager;
   private final PluginSettings pluginSettings;
   private final GerritApi gerritApi;
+  private final ChangeData.Factory changeDataFactory;
 
   @Inject
   GetFilesOwners(
@@ -70,7 +71,8 @@
       ProjectCache projectCache,
       GitRepositoryManager repositoryManager,
       PluginSettings pluginSettings,
-      GerritApi gerritApi) {
+      GerritApi gerritApi,
+      ChangeData.Factory changeDataFactory) {
     this.patchListCache = patchListCache;
     this.accounts = accounts;
     this.accountCache = accountCache;
@@ -78,6 +80,7 @@
     this.repositoryManager = repositoryManager;
     this.pluginSettings = pluginSettings;
     this.gerritApi = gerritApi;
+    this.changeDataFactory = changeDataFactory;
   }
 
   @Override
@@ -95,7 +98,7 @@
             .orElse(Collections.emptyList());
 
     try (Repository repository = repositoryManager.openRepository(change.getProject())) {
-      PatchList patchList = patchListCache.get(change, ps);
+      Set<String> changePaths = new HashSet<>(changeDataFactory.create(change).currentFilePaths());
 
       String branch = change.getDest().branch();
       PathOwners owners =
@@ -105,7 +108,7 @@
               repository,
               maybeParentProjectNameKey,
               pluginSettings.isBranchDisabled(branch) ? Optional.empty() : Optional.of(branch),
-              patchList,
+              changePaths,
               pluginSettings.expandGroups());
 
       Map<String, Set<GroupOwner>> fileToOwners =
@@ -153,7 +156,7 @@
     changeInfo.labels.forEach(
         (label, labelInfo) -> {
           Optional.ofNullable(labelInfo.all)
-              .map(
+              .ifPresent(
                   approvalInfos -> {
                     approvalInfos.forEach(
                         approvalInfo -> {
@@ -163,7 +166,6 @@
                           currentOwnerLabels.put(label, approvalInfo.value);
                           ownerToLabels.put(currentOwnerId, currentOwnerLabels);
                         });
-                    return ownerToLabels;
                   });
         });