CodeOwnerResolverResult: Include flag if there are unresolved code owners
Android wants a configuration option to make all users code owners of
paths for which no code owners are defined:
1. if for a path no code owners are defined, the path is owned by all
users
2. if for a path code owners are defined, only these users own the path
3. if for a path code owners are defined, but none of them is resolvable
the path is owned by no one and changes require an override for
submission
As a first step for adding such a configuration option we extend
CodeOwnerResolverResult with a flag that is set if there are unresolved
code owners. This allows callers to differentiate the cases above:
1. codeOwners is empty, ownedByAllUsers = false,
hasUnresolvedCodeOwners = false
2. codeOwner is non-empty or ownedByAllUsers = true
3. codeOwners is empty, ownedByAllUsers = false,
hasUnresolvedCodeOwners = true
Signed-off-by: Edwin Kempin <ekempin@google.com>
Change-Id: Iab1abf7a139dcead9e8ccad55b989a00d53ff8fc
diff --git a/java/com/google/gerrit/plugins/codeowners/backend/CodeOwnerResolver.java b/java/com/google/gerrit/plugins/codeowners/backend/CodeOwnerResolver.java
index c6b5f55..205e931 100644
--- a/java/com/google/gerrit/plugins/codeowners/backend/CodeOwnerResolver.java
+++ b/java/com/google/gerrit/plugins/codeowners/backend/CodeOwnerResolver.java
@@ -177,6 +177,7 @@
public CodeOwnerResolverResult resolve(Set<CodeOwnerReference> codeOwnerReferences) {
requireNonNull(codeOwnerReferences, "codeOwnerReferences");
AtomicBoolean ownedByAllUsers = new AtomicBoolean(false);
+ AtomicBoolean hasUnresolvedCodeOwners = new AtomicBoolean(false);
ImmutableSet<CodeOwner> codeOwners =
codeOwnerReferences.stream()
.filter(
@@ -188,10 +189,18 @@
return true;
})
.map(this::resolve)
- .filter(Optional::isPresent)
+ .filter(
+ codeOwner -> {
+ if (!codeOwner.isPresent()) {
+ hasUnresolvedCodeOwners.set(true);
+ return false;
+ }
+ return true;
+ })
.map(Optional::get)
.collect(toImmutableSet());
- return CodeOwnerResolverResult.create(codeOwners, ownedByAllUsers.get());
+ return CodeOwnerResolverResult.create(
+ codeOwners, ownedByAllUsers.get(), hasUnresolvedCodeOwners.get());
}
/**
diff --git a/java/com/google/gerrit/plugins/codeowners/backend/CodeOwnerResolverResult.java b/java/com/google/gerrit/plugins/codeowners/backend/CodeOwnerResolverResult.java
index 226d541..cd11262 100644
--- a/java/com/google/gerrit/plugins/codeowners/backend/CodeOwnerResolverResult.java
+++ b/java/com/google/gerrit/plugins/codeowners/backend/CodeOwnerResolverResult.java
@@ -43,17 +43,24 @@
*/
public abstract boolean ownedByAllUsers();
+ /** Whether there are code owner references which couldn't be resolved. */
+ public abstract boolean hasUnresolvedCodeOwners();
+
@Override
public String toString() {
return MoreObjects.toStringHelper(this)
.add("codeOwners", codeOwners())
.add("ownedByAllUsers", ownedByAllUsers())
+ .add("hasUnresolvedCodeOwners", hasUnresolvedCodeOwners())
.toString();
}
/** Creates a {@link CodeOwnerResolverResult} instance. */
public static CodeOwnerResolverResult create(
- ImmutableSet<CodeOwner> codeOwners, boolean ownedByAllUsers) {
- return new AutoValue_CodeOwnerResolverResult(codeOwners, ownedByAllUsers);
+ ImmutableSet<CodeOwner> codeOwners,
+ boolean ownedByAllUsers,
+ boolean hasUnresolvedCodeOwners) {
+ return new AutoValue_CodeOwnerResolverResult(
+ codeOwners, ownedByAllUsers, hasUnresolvedCodeOwners);
}
}
diff --git a/javatests/com/google/gerrit/plugins/codeowners/backend/CodeOwnerResolverTest.java b/javatests/com/google/gerrit/plugins/codeowners/backend/CodeOwnerResolverTest.java
index cefe297..86652b2 100644
--- a/javatests/com/google/gerrit/plugins/codeowners/backend/CodeOwnerResolverTest.java
+++ b/javatests/com/google/gerrit/plugins/codeowners/backend/CodeOwnerResolverTest.java
@@ -192,6 +192,7 @@
codeOwnerResolver.get().resolvePathCodeOwners(codeOwnerConfig, Paths.get("/README.md"));
assertThat(result.codeOwners()).isEmpty();
assertThat(result.ownedByAllUsers()).isFalse();
+ assertThat(result.hasUnresolvedCodeOwners()).isFalse();
}
@Test
@@ -205,6 +206,7 @@
codeOwnerResolver.get().resolvePathCodeOwners(codeOwnerConfig, Paths.get("/README.md"));
assertThat(result.codeOwnersAccountIds()).containsExactly(admin.id(), user.id());
assertThat(result.ownedByAllUsers()).isFalse();
+ assertThat(result.hasUnresolvedCodeOwners()).isFalse();
}
@Test
@@ -219,6 +221,7 @@
codeOwnerResolver.get().resolvePathCodeOwners(codeOwnerConfig, Paths.get("/README.md"));
assertThat(result.codeOwnersAccountIds()).isEmpty();
assertThat(result.ownedByAllUsers()).isTrue();
+ assertThat(result.hasUnresolvedCodeOwners()).isFalse();
}
@Test
@@ -233,6 +236,23 @@
codeOwnerResolver.get().resolvePathCodeOwners(codeOwnerConfig, Paths.get("/README.md"));
assertThat(result.codeOwnersAccountIds()).containsExactly(admin.id());
assertThat(result.ownedByAllUsers()).isFalse();
+ assertThat(result.hasUnresolvedCodeOwners()).isTrue();
+ }
+
+ @Test
+ public void resolvePathCodeOwnersNonResolvableCodeOwnersAreFilteredOutIfOwnedByAllUsers()
+ throws Exception {
+ CodeOwnerConfig codeOwnerConfig =
+ CodeOwnerConfig.builder(CodeOwnerConfig.Key.create(project, "master", "/"), TEST_REVISION)
+ .addCodeOwnerSet(
+ CodeOwnerSet.createWithoutPathExpressions(
+ "*", admin.email(), "non-existing@example.com"))
+ .build();
+ CodeOwnerResolverResult result =
+ codeOwnerResolver.get().resolvePathCodeOwners(codeOwnerConfig, Paths.get("/README.md"));
+ assertThat(result.codeOwnersAccountIds()).containsExactly(admin.id());
+ assertThat(result.ownedByAllUsers()).isTrue();
+ assertThat(result.hasUnresolvedCodeOwners()).isTrue();
}
@Test
@@ -386,6 +406,21 @@
CodeOwnerReference.create(user.email())));
assertThat(result.codeOwnersAccountIds()).containsExactly(admin.id(), user.id());
assertThat(result.ownedByAllUsers()).isFalse();
+ assertThat(result.hasUnresolvedCodeOwners()).isFalse();
+ }
+
+ @Test
+ public void resolveCodeOwnerReferencesNonResolveableCodeOwnersAreFilteredOut() throws Exception {
+ CodeOwnerResolverResult result =
+ codeOwnerResolver
+ .get()
+ .resolve(
+ ImmutableSet.of(
+ CodeOwnerReference.create(admin.email()),
+ CodeOwnerReference.create("non-existing@example.com")));
+ assertThat(result.codeOwnersAccountIds()).containsExactly(admin.id());
+ assertThat(result.ownedByAllUsers()).isFalse();
+ assertThat(result.hasUnresolvedCodeOwners()).isTrue();
}
@Test