| // Copyright (C) 2011 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 com.google.gerrit.common.data.AccessSection; |
| import com.google.gerrit.common.data.GlobalCapability; |
| import com.google.gerrit.common.data.PermissionRule; |
| import com.google.gerrit.common.data.PermissionRule.Action; |
| import com.google.gerrit.reviewdb.client.AccountGroup; |
| import com.google.gerrit.reviewdb.client.AccountGroupName; |
| import com.google.gerrit.reviewdb.client.Project; |
| import com.google.gerrit.reviewdb.client.SystemConfig; |
| import com.google.gerrit.reviewdb.server.ReviewDb; |
| import com.google.gerrit.server.GerritPersonIdent; |
| import com.google.gerrit.server.config.AllProjectsNameProvider; |
| import com.google.gerrit.server.config.SitePaths; |
| import com.google.gerrit.server.extensions.events.GitReferenceUpdated; |
| import com.google.gerrit.server.git.GitRepositoryManager; |
| import com.google.gerrit.server.git.MetaDataUpdate; |
| import com.google.gerrit.server.git.ProjectConfig; |
| import com.google.gwtorm.jdbc.JdbcSchema; |
| import com.google.gwtorm.server.OrmException; |
| import com.google.inject.Inject; |
| import com.google.inject.Provider; |
| |
| import org.eclipse.jgit.errors.ConfigInvalidException; |
| import org.eclipse.jgit.lib.PersonIdent; |
| import org.eclipse.jgit.lib.Repository; |
| import org.eclipse.jgit.storage.file.FileBasedConfig; |
| import org.eclipse.jgit.util.FS; |
| |
| import java.io.IOException; |
| import java.sql.PreparedStatement; |
| import java.sql.ResultSet; |
| import java.sql.SQLException; |
| import java.util.Collections; |
| |
| public class Schema_57 extends SchemaVersion { |
| private final SitePaths site; |
| private final GitRepositoryManager mgr; |
| private final PersonIdent serverUser; |
| |
| @Inject |
| Schema_57(Provider<Schema_56> prior, SitePaths site, |
| GitRepositoryManager mgr, @GerritPersonIdent PersonIdent serverUser) { |
| super(prior); |
| this.site = site; |
| this.mgr = mgr; |
| this.serverUser = serverUser; |
| } |
| |
| @Override |
| protected void migrateData(ReviewDb db, UpdateUI ui) throws OrmException { |
| SystemConfig sc = db.systemConfig().get(new SystemConfig.Key()); |
| Project.NameKey allProjects = sc.wildProjectName; |
| |
| FileBasedConfig cfg = new FileBasedConfig(site.gerrit_config, FS.DETECTED); |
| boolean cfgDirty = false; |
| try { |
| cfg.load(); |
| } catch (ConfigInvalidException err) { |
| throw new OrmException("Cannot read " + site.gerrit_config, err); |
| } catch (IOException err) { |
| throw new OrmException("Cannot read " + site.gerrit_config, err); |
| } |
| |
| if (!allProjects.get().equals(AllProjectsNameProvider.DEFAULT)) { |
| ui.message("Setting gerrit.allProjects = " + allProjects.get()); |
| cfg.setString("gerrit", null, "allProjects", allProjects.get()); |
| cfgDirty = true; |
| } |
| |
| try { |
| Repository git = mgr.openRepository(allProjects); |
| try { |
| MetaDataUpdate md = |
| new MetaDataUpdate(GitReferenceUpdated.DISABLED, allProjects, git); |
| md.getCommitBuilder().setAuthor(serverUser); |
| md.getCommitBuilder().setCommitter(serverUser); |
| |
| ProjectConfig config = ProjectConfig.read(md); |
| AccessSection cap = config.getAccessSection(AccessSection.GLOBAL_CAPABILITIES, true); |
| |
| // Move the Administrators group reference to All-Projects. |
| cap.getPermission(GlobalCapability.ADMINISTRATE_SERVER, true) |
| .add(new PermissionRule(config.resolve(db.accountGroups().get(sc.adminGroupId)))); |
| |
| // Move the repository.*.createGroup to Create Project. |
| String[] createGroupList = cfg.getStringList("repository", "*", "createGroup"); |
| |
| // Prepare the account_group_includes query |
| PreparedStatement stmt = ((JdbcSchema) db).getConnection(). |
| prepareStatement("SELECT COUNT(1) FROM account_group_includes WHERE group_id = ?"); |
| boolean isAccountGroupEmpty = false; |
| try { |
| stmt.setInt(1, sc.batchUsersGroupId.get()); |
| ResultSet rs = stmt.executeQuery(); |
| if (rs.next()) { |
| isAccountGroupEmpty = rs.getInt(1) == 0; |
| } |
| } finally { |
| stmt.close(); |
| } |
| |
| for (String name : createGroupList) { |
| AccountGroup.NameKey key = new AccountGroup.NameKey(name); |
| AccountGroupName groupName = db.accountGroupNames().get(key); |
| if (groupName == null) { |
| continue; |
| } |
| |
| AccountGroup group = db.accountGroups().get(groupName.getId()); |
| if (group == null) { |
| continue; |
| } |
| |
| cap.getPermission(GlobalCapability.CREATE_PROJECT, true) |
| .add(new PermissionRule(config.resolve(group))); |
| } |
| if (createGroupList.length != 0) { |
| ui.message("Moved repository.*.createGroup to 'Create Project' capability"); |
| cfg.unset("repository", "*", "createGroup"); |
| cfgDirty = true; |
| } |
| |
| AccountGroup batch = db.accountGroups().get(sc.batchUsersGroupId); |
| |
| if (batch != null |
| && db.accountGroupMembers().byGroup(sc.batchUsersGroupId).toList().isEmpty() |
| && !isAccountGroupEmpty) { |
| // If the batch user group is not used, delete it. |
| // |
| db.accountGroups().delete(Collections.singleton(batch)); |
| |
| AccountGroupName name = db.accountGroupNames().get(batch.getNameKey()); |
| if (name != null) { |
| db.accountGroupNames().delete(Collections.singleton(name)); |
| } |
| } else if (batch != null) { |
| cap.getPermission(GlobalCapability.PRIORITY, true) |
| .getRule(config.resolve(batch), true) |
| .setAction(Action.BATCH); |
| } |
| |
| md.setMessage("Upgrade to Gerrit Code Review schema 57\n"); |
| config.commit(md); |
| } catch (SQLException err) { |
| throw new OrmException( "Cannot read account_group_includes", err); |
| } finally { |
| git.close(); |
| } |
| } catch (ConfigInvalidException err) { |
| throw new OrmException("Cannot read " + allProjects, err); |
| } catch (IOException err) { |
| throw new OrmException("Cannot update " + allProjects, err); |
| } |
| |
| if (cfgDirty) { |
| try { |
| cfg.save(); |
| } catch (IOException err) { |
| throw new OrmException("Cannot update " + site.gerrit_config, err); |
| } |
| } |
| |
| // We cannot set the columns to NULL, so use 0 and a DELETED tag. |
| sc.adminGroupId = new AccountGroup.Id(0); |
| sc.adminGroupUUID = new AccountGroup.UUID("DELETED"); |
| sc.anonymousGroupId = new AccountGroup.Id(0); |
| sc.registeredGroupId = new AccountGroup.Id(0); |
| sc.wildProjectName = new Project.NameKey("DELETED"); |
| sc.ownerGroupId = new AccountGroup.Id(0); |
| sc.batchUsersGroupId = new AccountGroup.Id(0); |
| sc.batchUsersGroupUUID = new AccountGroup.UUID("DELETED"); |
| sc.registerEmailPrivateKey = "DELETED"; |
| |
| db.systemConfig().update(Collections.singleton(sc)); |
| } |
| } |