in java/com/google/gerrit/plugins/codeowners/restapi/CheckCodeOwner.java [149:347]
public Response<CodeOwnerCheckInfo> apply(BranchResource branchResource)
throws BadRequestException, AuthException, IOException, ConfigInvalidException,
PermissionBackendException, ResourceNotFoundException {
permissionBackend.currentUser().check(checkCodeOwnerCapability.getPermission());
validateInput(branchResource);
Path absolutePath = JgitPath.of(path).getAsAbsolutePath();
List<String> messages = new ArrayList<>();
List<Path> codeOwnerConfigFilePaths = new ArrayList<>();
AtomicBoolean isCodeOwnershipAssignedToEmail = new AtomicBoolean(false);
AtomicBoolean isCodeOwnershipAssignedToAllUsers = new AtomicBoolean(false);
AtomicBoolean isDefaultCodeOwner = new AtomicBoolean(false);
AtomicBoolean hasRevelantCodeOwnerDefinitions = new AtomicBoolean(false);
AtomicBoolean parentCodeOwnersAreIgnored = new AtomicBoolean(false);
Set<String> annotations = new HashSet<>();
codeOwnerConfigHierarchy.visit(
branchResource.getBranchKey(),
ObjectId.fromString(branchResource.getRevision().get()),
absolutePath,
codeOwnerConfig -> {
messages.add(
String.format(
"checking code owner config file %s", codeOwnerConfig.key().format(codeOwners)));
OptionalResultWithMessages<PathCodeOwnersResult> pathCodeOwnersResult =
pathCodeOwnersFactory
.createWithoutCache(codeOwnerConfig, absolutePath)
.resolveCodeOwnerConfig();
messages.addAll(pathCodeOwnersResult.messages());
pathCodeOwnersResult
.get()
.unresolvedImports()
.forEach(
unresolvedImport ->
messages.add(unresolvedImportFormatter.format(unresolvedImport)));
Optional<CodeOwnerReference> codeOwnerReference =
pathCodeOwnersResult.get().getPathCodeOwners().stream()
.filter(cor -> cor.email().equals(email))
.findAny();
if (codeOwnerReference.isPresent()
&& !CodeOwnerResolver.ALL_USERS_WILDCARD.equals(email)) {
isCodeOwnershipAssignedToEmail.set(true);
if (RefNames.isConfigRef(codeOwnerConfig.key().ref())) {
messages.add(
String.format(
"found email %s as a code owner in the default code owner config", email));
isDefaultCodeOwner.set(true);
} else {
Path codeOwnerConfigFilePath = codeOwners.getFilePath(codeOwnerConfig.key());
messages.add(
String.format(
"found email %s as a code owner in %s", email, codeOwnerConfigFilePath));
codeOwnerConfigFilePaths.add(codeOwnerConfigFilePath);
}
ImmutableSet<String> localAnnotations =
pathCodeOwnersResult.get().getAnnotationsFor(email);
if (!localAnnotations.isEmpty()) {
messages.add(
String.format("email %s is annotated with %s", email, sort(localAnnotations)));
annotations.addAll(localAnnotations);
}
}
if (pathCodeOwnersResult.get().getPathCodeOwners().stream()
.anyMatch(cor -> cor.email().equals(CodeOwnerResolver.ALL_USERS_WILDCARD))) {
isCodeOwnershipAssignedToAllUsers.set(true);
if (RefNames.isConfigRef(codeOwnerConfig.key().ref())) {
messages.add(
String.format(
"found the all users wildcard ('%s') as a code owner in the default code"
+ " owner config which makes %s a code owner",
CodeOwnerResolver.ALL_USERS_WILDCARD, email));
isDefaultCodeOwner.set(true);
} else {
Path codeOwnerConfigFilePath = codeOwners.getFilePath(codeOwnerConfig.key());
messages.add(
String.format(
"found the all users wildcard ('%s') as a code owner in %s which makes %s a"
+ " code owner",
CodeOwnerResolver.ALL_USERS_WILDCARD, codeOwnerConfigFilePath, email));
if (!codeOwnerConfigFilePaths.contains(codeOwnerConfigFilePath)) {
codeOwnerConfigFilePaths.add(codeOwnerConfigFilePath);
}
}
ImmutableSet<String> localAnnotations =
pathCodeOwnersResult.get().getAnnotationsFor(CodeOwnerResolver.ALL_USERS_WILDCARD);
if (!localAnnotations.isEmpty()) {
messages.add(
String.format(
"found annotations for the all users wildcard ('%s') which apply to %s: %s",
CodeOwnerResolver.ALL_USERS_WILDCARD, email, sort(localAnnotations)));
annotations.addAll(localAnnotations);
}
}
if (codeOwnerResolverProvider
.get()
.resolvePathCodeOwners(codeOwnerConfig, absolutePath)
.hasRevelantCodeOwnerDefinitions()) {
hasRevelantCodeOwnerDefinitions.set(true);
}
if (pathCodeOwnersResult.get().ignoreParentCodeOwners()) {
messages.add("parent code owners are ignored");
parentCodeOwnersAreIgnored.set(true);
}
return !pathCodeOwnersResult.get().ignoreParentCodeOwners();
});
boolean isGlobalCodeOwner = false;
if (isGlobalCodeOwner(branchResource.getNameKey(), email)) {
isGlobalCodeOwner = true;
messages.add(String.format("found email %s as global code owner", email));
isCodeOwnershipAssignedToEmail.set(true);
}
if (isGlobalCodeOwner(branchResource.getNameKey(), CodeOwnerResolver.ALL_USERS_WILDCARD)) {
isGlobalCodeOwner = true;
messages.add(
String.format(
"found email %s as global code owner", CodeOwnerResolver.ALL_USERS_WILDCARD));
isCodeOwnershipAssignedToAllUsers.set(true);
}
boolean isResolvable;
Boolean canReadRef = null;
Boolean canSeeChange = null;
Boolean canApproveChange = null;
if (email.equals(CodeOwnerResolver.ALL_USERS_WILDCARD)) {
isResolvable = true;
} else {
OptionalResultWithMessages<CodeOwner> isResolvableResult = isResolvable();
isResolvable = isResolvableResult.isPresent();
messages.addAll(isResolvableResult.messages());
if (isResolvable) {
PermissionBackend.WithUser withUser =
permissionBackend.absentUser(isResolvableResult.get().accountId());
canReadRef = withUser.ref(branchResource.getBranchKey()).test(RefPermission.READ);
if (changeNotes != null) {
PermissionBackend.ForChange forChange = withUser.change(changeNotes);
canSeeChange = forChange.test(ChangePermission.READ);
RequiredApproval requiredApproval =
codeOwnersPluginConfiguration
.getProjectConfig(branchResource.getNameKey())
.getRequiredApproval();
canApproveChange =
forChange.test(
new LabelPermission.WithValue(
requiredApproval.labelType(), requiredApproval.value()));
}
}
}
ImmutableSet<String> unsupportedAnnotations =
annotations.stream()
.filter(annotation -> !CodeOwnerAnnotations.isSupported(annotation))
.collect(toImmutableSet());
if (!unsupportedAnnotations.isEmpty()) {
messages.add(
String.format(
"dropping unsupported annotations for %s: %s", email, sort(unsupportedAnnotations)));
annotations.removeAll(unsupportedAnnotations);
}
boolean isFallbackCodeOwner =
!isCodeOwnershipAssignedToEmail.get()
&& !isCodeOwnershipAssignedToAllUsers.get()
&& !hasRevelantCodeOwnerDefinitions.get()
&& !parentCodeOwnersAreIgnored.get()
&& isFallbackCodeOwner(branchResource.getNameKey());
CodeOwnerCheckInfo codeOwnerCheckInfo = new CodeOwnerCheckInfo();
codeOwnerCheckInfo.isCodeOwner =
(isCodeOwnershipAssignedToEmail.get()
|| isCodeOwnershipAssignedToAllUsers.get()
|| isFallbackCodeOwner)
&& isResolvable;
codeOwnerCheckInfo.isResolvable = isResolvable;
codeOwnerCheckInfo.canReadRef = canReadRef;
codeOwnerCheckInfo.canSeeChange = canSeeChange;
codeOwnerCheckInfo.canApproveChange = canApproveChange;
codeOwnerCheckInfo.codeOwnerConfigFilePaths =
codeOwnerConfigFilePaths.stream().map(Path::toString).collect(toList());
codeOwnerCheckInfo.isFallbackCodeOwner = isFallbackCodeOwner && isResolvable;
codeOwnerCheckInfo.isDefaultCodeOwner = isDefaultCodeOwner.get();
codeOwnerCheckInfo.isGlobalCodeOwner = isGlobalCodeOwner;
codeOwnerCheckInfo.isOwnedByAllUsers = isCodeOwnershipAssignedToAllUsers.get();
codeOwnerCheckInfo.annotations = sort(annotations);
codeOwnerCheckInfo.debugLogs = messages;
return Response.ok(codeOwnerCheckInfo);
}