in java/com/google/gerrit/plugins/codeowners/restapi/AbstractGetCodeOwnersForPath.java [185:334]
protected Response<CodeOwnersInfo> applyImpl(R rsrc)
throws AuthException, BadRequestException, PermissionBackendException {
parseHexOptions();
validateLimit();
if (debug) {
permissionBackend.currentUser().check(checkCodeOwnerCapability.getPermission());
}
if (!seed.isPresent()) {
seed = getDefaultSeed(rsrc);
}
codeOwnerMetrics.countCodeOwnerSuggestions.increment(resolveAllUsers);
// The distance that applies to code owners that are defined in the root code owner
// configuration.
int rootDistance = rsrc.getPath().getNameCount();
int defaultOwnersDistance = rootDistance + 1;
int globalOwnersDistance = defaultOwnersDistance + 1;
int maxDistance = globalOwnersDistance;
CodeOwnerScoring.Builder distanceScoring = CodeOwnerScore.DISTANCE.createScoring(maxDistance);
CodeOwnerScoring.Builder isExplicitlyMentionedScoring =
CodeOwnerScore.IS_EXPLICITLY_MENTIONED.createScoring();
Set<CodeOwner> codeOwners = new HashSet<>();
ListMultimap<CodeOwner, CodeOwnerAnnotation> annotations = LinkedListMultimap.create();
AtomicBoolean ownedByAllUsers = new AtomicBoolean(false);
ImmutableList.Builder<String> debugLogsBuilder = ImmutableList.builder();
codeOwnerConfigHierarchy.visit(
rsrc.getBranch(),
rsrc.getRevision(),
rsrc.getPath(),
codeOwnerConfig -> {
CodeOwnerResolverResult pathCodeOwners =
codeOwnerResolver.get().resolvePathCodeOwners(codeOwnerConfig, rsrc.getPath());
debugLogsBuilder.addAll(pathCodeOwners.messages());
codeOwners.addAll(pathCodeOwners.codeOwners());
annotations.putAll(pathCodeOwners.annotations());
int distance =
codeOwnerConfig.key().branchNameKey().branch().equals(RefNames.REFS_CONFIG)
? defaultOwnersDistance
: rootDistance - codeOwnerConfig.key().folderPath().getNameCount();
pathCodeOwners
.codeOwners()
.forEach(
localCodeOwner -> {
distanceScoring.putValueForCodeOwner(localCodeOwner, distance);
isExplicitlyMentionedScoring.putValueForCodeOwner(
localCodeOwner, IS_EXPLICITLY_MENTIONED_SCORING_VALUE);
});
if (pathCodeOwners.ownedByAllUsers()) {
ownedByAllUsers.set(true);
ImmutableSet<CodeOwner> addedCodeOwners = fillUpWithRandomUsers(codeOwners, limit);
addedCodeOwners.forEach(
localCodeOwner -> {
distanceScoring.putValueForCodeOwner(localCodeOwner, distance);
isExplicitlyMentionedScoring.putValueForCodeOwner(
localCodeOwner, NOT_EXPLICITLY_MENTIONED_SCORING_VALUE);
});
if (codeOwners.size() < limit) {
logger.atFine().log(
"tried to fill up the suggestion list with random users,"
+ " but didn't find enough visible accounts"
+ " (wanted number of suggestions = %d, got = %d",
limit, codeOwners.size());
}
}
// We always need to iterate over all relevant OWNERS files (even if the limit has already
// been reached).
// This is needed to collect distance scores for code owners that are mentioned in the
// more distant OWNERS files. Those become relevant if further scores are applied later
// (e.g. the score for current reviewers of the change).
return true;
});
if (!ownedByAllUsers.get()) {
CodeOwnerResolverResult globalCodeOwners = getGlobalCodeOwners(rsrc.getBranch().project());
debugLogsBuilder.add("resolve global code owners");
debugLogsBuilder.addAll(globalCodeOwners.messages());
globalCodeOwners
.codeOwners()
.forEach(
codeOwner -> {
distanceScoring.putValueForCodeOwner(codeOwner, globalOwnersDistance);
isExplicitlyMentionedScoring.putValueForCodeOwner(
codeOwner, IS_EXPLICITLY_MENTIONED_SCORING_VALUE);
});
codeOwners.addAll(globalCodeOwners.codeOwners());
if (globalCodeOwners.ownedByAllUsers()) {
ownedByAllUsers.set(true);
ImmutableSet<CodeOwner> addedCodeOwners = fillUpWithRandomUsers(codeOwners, limit);
addedCodeOwners.forEach(
codeOwner -> {
distanceScoring.putValueForCodeOwner(codeOwner, globalOwnersDistance);
isExplicitlyMentionedScoring.putValueForCodeOwner(
codeOwner, NOT_EXPLICITLY_MENTIONED_SCORING_VALUE);
});
}
}
ImmutableSet<CodeOwner> filteredCodeOwners =
filterCodeOwners(
rsrc,
ImmutableMultimap.copyOf(annotations),
ImmutableSet.copyOf(codeOwners),
debugLogsBuilder);
CodeOwnerScorings codeOwnerScorings =
createScorings(
rsrc,
filteredCodeOwners,
distanceScoring.build(),
isExplicitlyMentionedScoring.build());
ImmutableMap<CodeOwner, Double> scoredCodeOwners =
codeOwnerScorings.getScorings(filteredCodeOwners);
ImmutableList<CodeOwner> sortedAndLimitedCodeOwners = sortAndLimit(rsrc, scoredCodeOwners);
if (highestScoreOnly) {
Optional<Double> highestScore =
scoredCodeOwners.values().stream().max(Comparator.naturalOrder());
if (highestScore.isPresent()) {
sortedAndLimitedCodeOwners =
sortedAndLimitedCodeOwners.stream()
.filter(codeOwner -> scoredCodeOwners.get(codeOwner).equals(highestScore.get()))
.collect(toImmutableList());
}
}
CodeOwnersInfo codeOwnersInfo = new CodeOwnersInfo();
codeOwnersInfo.codeOwners =
codeOwnerJsonFactory.create(getFillOptions()).format(sortedAndLimitedCodeOwners);
codeOwnersInfo.ownedByAllUsers = ownedByAllUsers.get() ? true : null;
ImmutableList<String> debugLogs = debugLogsBuilder.build();
codeOwnersInfo.debugLogs = debug ? debugLogs : null;
logger.atFine().log("debug logs: %s", debugLogs);
return Response.ok(codeOwnersInfo);
}