| // Copyright (C) 2020 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.google.gerrit.server.schema; | |
| import static com.google.gerrit.server.update.context.RefUpdateContext.RefUpdateType.OFFLINE_OPERATION; | |
| import com.google.gerrit.common.Nullable; | |
| import com.google.gerrit.entities.AccountGroup; | |
| import com.google.gerrit.entities.GroupReference; | |
| import com.google.gerrit.entities.InternalGroup; | |
| import com.google.gerrit.git.RefUpdateUtil; | |
| import com.google.gerrit.server.account.ServiceUserClassifier; | |
| import com.google.gerrit.server.config.AllUsersName; | |
| import com.google.gerrit.server.extensions.events.GitReferenceUpdated; | |
| import com.google.gerrit.server.git.meta.MetaDataUpdate; | |
| import com.google.gerrit.server.group.db.AuditLogFormatter; | |
| import com.google.gerrit.server.group.db.GroupConfig; | |
| import com.google.gerrit.server.group.db.GroupDelta; | |
| import com.google.gerrit.server.group.db.GroupNameNotes; | |
| import com.google.gerrit.server.index.group.GroupIndex; | |
| import com.google.gerrit.server.index.group.GroupIndexCollection; | |
| import com.google.gerrit.server.update.context.RefUpdateContext; | |
| import java.io.IOException; | |
| import java.util.Optional; | |
| import org.eclipse.jgit.lib.BatchRefUpdate; | |
| import org.eclipse.jgit.lib.PersonIdent; | |
| import org.eclipse.jgit.lib.Repository; | |
| /** | |
| * Schema 184 for Gerrit metadata. | |
| * | |
| * <p>Upgrading to this schema version will rename the {@code Non-Interactive Users} group to {@code | |
| * Service Users}. | |
| */ | |
| public class Schema_184 implements NoteDbSchemaVersion { | |
| @Override | |
| public void upgrade(Arguments args, UpdateUI ui) throws Exception { | |
| try (Repository allUsersRepo = args.repoManager.openRepository(args.allUsers)) { | |
| AccountGroup.NameKey newName = AccountGroup.nameKey(ServiceUserClassifier.SERVICE_USERS); | |
| Optional<GroupReference> nonInteractiveUsers = | |
| GroupNameNotes.loadAllGroups(allUsersRepo).stream() | |
| .filter(g -> g.getName().equals("Non-Interactive Users")) | |
| .findAny(); | |
| if (!nonInteractiveUsers.isPresent()) { | |
| return; | |
| } | |
| GroupNameNotes newNameNotes = | |
| GroupNameNotes.forRename( | |
| args.allUsers, | |
| allUsersRepo, | |
| nonInteractiveUsers.get().getUUID(), | |
| AccountGroup.nameKey(nonInteractiveUsers.get().getName()), | |
| newName); | |
| GroupConfig groupConfig = | |
| GroupConfig.loadForGroup( | |
| args.allUsers, allUsersRepo, nonInteractiveUsers.get().getUUID()); | |
| groupConfig.setGroupDelta( | |
| GroupDelta.builder().setName(newName).build(), | |
| AuditLogFormatter.createPartiallyWorkingFallBack()); | |
| commit(args.allUsers, args.serverUser, allUsersRepo, groupConfig, newNameNotes); | |
| index( | |
| args.groupIndexCollection, | |
| groupConfig | |
| .getLoadedGroup() | |
| .orElseThrow( | |
| () -> new IllegalStateException("Created group wasn't automatically loaded"))); | |
| } | |
| } | |
| private void commit( | |
| AllUsersName allUsersName, | |
| PersonIdent serverUser, | |
| Repository allUsersRepo, | |
| GroupConfig groupConfig, | |
| GroupNameNotes groupNameNotes) | |
| throws IOException { | |
| try (RefUpdateContext ctx = RefUpdateContext.open(OFFLINE_OPERATION)) { | |
| BatchRefUpdate batchRefUpdate = allUsersRepo.getRefDatabase().newBatchUpdate(); | |
| try (MetaDataUpdate metaDataUpdate = | |
| createMetaDataUpdate(allUsersName, serverUser, allUsersRepo, batchRefUpdate)) { | |
| groupConfig.commit(metaDataUpdate); | |
| } | |
| // MetaDataUpdates unfortunately can't be reused. -> Create a new one. | |
| try (MetaDataUpdate metaDataUpdate = | |
| createMetaDataUpdate(allUsersName, serverUser, allUsersRepo, batchRefUpdate)) { | |
| groupNameNotes.commit(metaDataUpdate); | |
| } | |
| RefUpdateUtil.executeChecked(batchRefUpdate, allUsersRepo); | |
| } | |
| } | |
| private MetaDataUpdate createMetaDataUpdate( | |
| AllUsersName allUsersName, | |
| PersonIdent serverUser, | |
| Repository allUsersRepo, | |
| @Nullable BatchRefUpdate batchRefUpdate) { | |
| MetaDataUpdate metaDataUpdate = | |
| new MetaDataUpdate( | |
| GitReferenceUpdated.DISABLED, allUsersName, allUsersRepo, batchRefUpdate); | |
| metaDataUpdate.getCommitBuilder().setAuthor(serverUser); | |
| metaDataUpdate.getCommitBuilder().setCommitter(serverUser); | |
| return metaDataUpdate; | |
| } | |
| private void index(GroupIndexCollection indexCollection, InternalGroup group) { | |
| for (GroupIndex groupIndex : indexCollection.getWriteIndexes()) { | |
| groupIndex.replace(group); | |
| } | |
| } | |
| } |