| // 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 gerrit_owners; | |
| import static com.googlesource.gerrit.owners.common.StreamUtils.iteratorStream; | |
| import com.google.gerrit.entities.Account; | |
| import com.google.gerrit.server.IdentifiedUser; | |
| import com.google.gerrit.server.rules.prolog.PrologEnvironment; | |
| import com.google.gerrit.server.rules.prolog.StoredValues; | |
| import com.googlecode.prolog_cafe.exceptions.PInstantiationException; | |
| import com.googlecode.prolog_cafe.exceptions.PrologException; | |
| import com.googlecode.prolog_cafe.lang.Operation; | |
| import com.googlecode.prolog_cafe.lang.Predicate; | |
| import com.googlecode.prolog_cafe.lang.Prolog; | |
| import com.googlecode.prolog_cafe.lang.SymbolTerm; | |
| import com.googlecode.prolog_cafe.lang.Term; | |
| import com.googlecode.prolog_cafe.lang.VariableTerm; | |
| import com.googlesource.gerrit.owners.OwnersStoredValues; | |
| import com.googlesource.gerrit.owners.common.PathOwners; | |
| import java.io.File; | |
| import java.util.Map; | |
| import java.util.Set; | |
| import java.util.stream.Collectors; | |
| /** | |
| * Get the list of users owning this file Actually a variation of PRED_current_user/2 in gerrit main | |
| * module, sharing its cache.. This is really needed to avoid prolog consuming rules and RAM space | |
| * | |
| * <pre> | |
| * gerrit_owners:file_owners(+FilePath, -UserListFormatted). | |
| * </pre> | |
| */ | |
| class PRED_file_owners_2 extends Predicate.P2 { | |
| PRED_file_owners_2(Term a1, Term a2, Operation n) { | |
| arg1 = a1; | |
| arg2 = a2; | |
| cont = n; | |
| } | |
| @Override | |
| public Operation exec(Prolog engine) throws PrologException { | |
| engine.setB0(); | |
| Term a1 = arg1.dereference(); | |
| Term a2 = arg2.dereference(); | |
| if (a1 instanceof VariableTerm) { | |
| throw new PInstantiationException(this, 1); | |
| } | |
| if (!a2.unify(createFormattedList(engine, a1), engine.trail)) { | |
| return engine.fail(); | |
| } | |
| return cont; | |
| } | |
| public String getFullNameFromId(Prolog engine, Account.Id accountId) { | |
| Map<Account.Id, IdentifiedUser> cache = StoredValues.USERS.get(engine); | |
| IdentifiedUser user = cache.get(accountId); | |
| if (user == null) { | |
| IdentifiedUser.GenericFactory userFactory = userFactory(engine); | |
| IdentifiedUser who = userFactory.create(accountId); | |
| cache.put(accountId, who); | |
| user = who; | |
| } | |
| Account account = user.asIdentifiedUser().state().account(); | |
| String userName = account.fullName(); | |
| return sanitizeAsSubmitLabel(userName); | |
| } | |
| public Term createFormattedList(Prolog engine, Term key) { | |
| String path = key.toString(); | |
| PathOwners owners = OwnersStoredValues.PATH_OWNERS.get(engine); | |
| Set<String> ownersNames = | |
| owners.expandGroups() | |
| ? iteratorStream(owners.getFileOwners().get(path).iterator()) | |
| .map(id -> getFullNameFromId(engine, id)) | |
| .collect(Collectors.toSet()) | |
| : iteratorStream((owners.getFileGroupOwners().get(path)).iterator()) | |
| .collect(Collectors.toSet()); | |
| String ownVerb = ownersNames.size() > 1 ? "-own-" : "-owns-"; | |
| String userNames = ownersNames.stream().collect(Collectors.joining("-")); | |
| return SymbolTerm.create(userNames + ownVerb + sanitizeAsSubmitLabel(new File(path).getName())); | |
| } | |
| private String sanitizeAsSubmitLabel(String anyLabelPart) { | |
| return anyLabelPart.replaceAll("[\\s_\\.]+", "-"); | |
| } | |
| private static IdentifiedUser.GenericFactory userFactory(Prolog engine) { | |
| return ((PrologEnvironment) engine.control).getArgs().getUserFactory(); | |
| } | |
| } |