Merge branch 'stable-2.10'

* stable-2.10:
  Update version to 2.10
  Remove the archetypeRepository property from the mvn archetype:generate
  Update the Gerrit version in the plugin development documentation
  Update 2.10 release notes
  Drop broken Schema migrations
  Update version to 2.10-rc2

Conflicts:
	VERSION
	gerrit-extension-api/pom.xml
	gerrit-plugin-api/pom.xml
	gerrit-plugin-archetype/pom.xml
	gerrit-plugin-gwt-archetype/pom.xml
	gerrit-plugin-gwtui/pom.xml
	gerrit-plugin-js-archetype/pom.xml
	gerrit-server/src/main/java/com/google/gerrit/server/schema/Schema_52.java
	gerrit-server/src/main/java/com/google/gerrit/server/schema/Schema_53.java
	gerrit-server/src/main/java/com/google/gerrit/server/schema/Schema_57.java
	gerrit-server/src/main/java/com/google/gerrit/server/schema/Schema_59.java
	gerrit-server/src/main/java/com/google/gerrit/server/schema/Schema_63.java
	gerrit-server/src/main/java/com/google/gerrit/server/schema/Schema_64.java
	gerrit-server/src/main/java/com/google/gerrit/server/schema/Schema_65.java
	gerrit-server/src/main/java/com/google/gerrit/server/schema/Schema_67.java
	gerrit-server/src/main/java/com/google/gerrit/server/schema/Schema_68.java
	gerrit-server/src/main/java/com/google/gerrit/server/schema/Schema_69.java
	gerrit-server/src/main/java/com/google/gerrit/server/schema/Schema_71.java
	gerrit-server/src/main/java/com/google/gerrit/server/schema/Schema_73.java
	gerrit-server/src/main/java/com/google/gerrit/server/schema/Schema_74.java
	gerrit-server/src/main/java/com/google/gerrit/server/schema/Schema_77.java
	gerrit-server/src/main/java/com/google/gerrit/server/schema/Schema_81.java
	gerrit-server/src/main/java/com/google/gerrit/server/schema/Schema_82.java
	gerrit-war/pom.xml

Change-Id: I44b2635bfb6b4011cc10f1fe29db5e6e734a9e3c
This commit is contained in:
Saša Živkov 2015-01-27 17:11:27 +01:00
commit b67addf513
34 changed files with 11 additions and 2943 deletions

View File

@ -36,8 +36,7 @@ plugin project.
----
mvn archetype:generate -DarchetypeGroupId=com.google.gerrit \
-DarchetypeArtifactId=gerrit-plugin-archetype \
-DarchetypeVersion=2.10-SNAPSHOT \
-DarchetypeRepository=https://oss.sonatype.org/content/repositories/snapshots/ \
-DarchetypeVersion=2.10 \
-DgroupId=com.googlesource.gerrit.plugins.testplugin \
-DartifactId=testplugin
----

View File

@ -21,7 +21,6 @@ Important Notes
*WARNING:* This release contains schema changes. To upgrade:
----
java -jar gerrit.war init -d site_path
java -jar gerrit.war reindex --recheck-mergeable -d site_path
----
*WARNING:* When upgrading from an existing site that was initialized with Gerrit
@ -32,8 +31,8 @@ rather than only copying the .war file over the existing one.
It is recommended to run the `init` program in interactive mode. Warnings will
be suppressed in batch mode.
*WARNING:* Upgrading to 2.10.x requires the server be first upgraded to 2.1.7 (or
a later 2.1.x version), and then to 2.10.x. If you are upgrading from 2.2.x.x or
*WARNING:* Upgrading to 2.10.x requires the server be first upgraded to 2.8
(or 2.9) and then to 2.10.x. If you are upgrading from 2.8.x or
later, you may ignore this warning and upgrade directly to 2.10.x.
*WARNING:* The `auth.allowGoogleAccountUpgrade` setting is no longer supported.

View File

@ -1,31 +0,0 @@
// 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.inject.Inject;
import com.google.inject.Provider;
import com.google.inject.ProvisionException;
public class Schema_52 extends SchemaVersion {
@Inject
Schema_52() {
super(new Provider<SchemaVersion>() {
@Override
public SchemaVersion get() {
throw new ProvisionException("Cannot upgrade from 51");
}
});
}
}

View File

@ -1,478 +0,0 @@
// Copyright (C) 2010 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.common.data.Permission.CREATE;
import static com.google.gerrit.common.data.Permission.FORGE_AUTHOR;
import static com.google.gerrit.common.data.Permission.FORGE_COMMITTER;
import static com.google.gerrit.common.data.Permission.FORGE_SERVER;
import static com.google.gerrit.common.data.Permission.LABEL;
import static com.google.gerrit.common.data.Permission.OWNER;
import static com.google.gerrit.common.data.Permission.PUSH;
import static com.google.gerrit.common.data.Permission.PUSH_MERGE;
import static com.google.gerrit.common.data.Permission.PUSH_TAG;
import static com.google.gerrit.common.data.Permission.READ;
import static com.google.gerrit.common.data.Permission.SUBMIT;
import com.google.gerrit.common.data.AccessSection;
import com.google.gerrit.common.data.GroupReference;
import com.google.gerrit.common.data.LabelType;
import com.google.gerrit.common.data.Permission;
import com.google.gerrit.common.data.PermissionRule;
import com.google.gerrit.extensions.client.InheritableBoolean;
import com.google.gerrit.extensions.client.SubmitType;
import com.google.gerrit.reviewdb.client.AccountGroup;
import com.google.gerrit.reviewdb.client.LabelId;
import com.google.gerrit.reviewdb.client.Project;
import com.google.gerrit.reviewdb.client.RefNames;
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.account.GroupUUID;
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.gerrit.server.group.SystemGroupBackend;
import com.google.gerrit.server.schema.Schema_77.LegacyLabelTypes;
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.errors.RepositoryNotFoundException;
import org.eclipse.jgit.lib.PersonIdent;
import org.eclipse.jgit.lib.Repository;
import java.io.IOException;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.Statement;
import java.util.ArrayList;
import java.util.Collections;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
class Schema_53 extends SchemaVersion {
private final GitRepositoryManager mgr;
private final PersonIdent serverUser;
private SystemConfig systemConfig;
private Map<AccountGroup.Id, GroupReference> groupMap;
private LegacyLabelTypes labelTypes;
private GroupReference projectOwners;
private Map<Project.NameKey, Project.NameKey> parentsByProject;
private Map<Project.NameKey, List<OldRefRight>> rightsByProject;
private final String OLD_SUBMIT = "SUBM";
private final String OLD_READ = "READ";
private final String OLD_OWN = "OWN";
private final String OLD_PUSH_TAG = "pTAG";
private final String OLD_PUSH_HEAD = "pHD";
private final String OLD_FORGE_IDENTITY = "FORG";
@Inject
Schema_53(Provider<Schema_52> prior, GitRepositoryManager mgr,
@GerritPersonIdent PersonIdent serverUser) {
super(prior);
this.mgr = mgr;
this.serverUser = serverUser;
}
@Override
protected void migrateData(ReviewDb db, UpdateUI ui) throws OrmException,
SQLException {
systemConfig = db.systemConfig().get(new SystemConfig.Key());
labelTypes = Schema_77.getLegacyTypes(db);
assignGroupUUIDs(db);
readOldRefRights(db);
readProjectParents(db);
exportProjectConfig(db);
deleteActionCategories(db);
}
private void deleteActionCategories(ReviewDb db) throws SQLException {
try (Statement stmt = newStatement(db)) {
stmt.executeUpdate("DELETE FROM approval_categories WHERE position < 0");
}
}
private void assignGroupUUIDs(ReviewDb db) throws OrmException {
groupMap = new HashMap<>();
List<AccountGroup> groups = db.accountGroups().all().toList();
for (AccountGroup g : groups) {
if (g.getId().equals(systemConfig.ownerGroupId)) {
g.setGroupUUID(SystemGroupBackend.PROJECT_OWNERS);
projectOwners = GroupReference.forGroup(g);
} else if (g.getId().equals(systemConfig.anonymousGroupId)) {
g.setGroupUUID(SystemGroupBackend.ANONYMOUS_USERS);
} else if (g.getId().equals(systemConfig.registeredGroupId)) {
g.setGroupUUID(SystemGroupBackend.REGISTERED_USERS);
} else {
g.setGroupUUID(GroupUUID.make(g.getName(), serverUser));
}
groupMap.put(g.getId(), GroupReference.forGroup(g));
}
db.accountGroups().update(groups);
systemConfig.adminGroupUUID = toUUID(systemConfig.adminGroupId);
systemConfig.batchUsersGroupUUID = toUUID(systemConfig.batchUsersGroupId);
db.systemConfig().update(Collections.singleton(systemConfig));
}
private AccountGroup.UUID toUUID(AccountGroup.Id id) {
return groupMap.get(id).getUUID();
}
private void exportProjectConfig(ReviewDb db) throws OrmException,
SQLException {
try (Statement s = newStatement(db);
ResultSet rs = s.executeQuery("SELECT * FROM projects ORDER BY name")) {
while (rs.next()) {
final String name = rs.getString("name");
final Project.NameKey nameKey = new Project.NameKey(name);
Repository git;
try {
git = mgr.openRepository(nameKey);
} catch (RepositoryNotFoundException notFound) {
// A repository may be missing if this project existed only to store
// inheritable permissions. For example 'All-Projects'.
try {
git = mgr.createRepository(nameKey);
} catch (IOException err) {
throw new OrmException("Cannot create repository " + name, err);
}
} catch (IOException e) {
throw new OrmException(e);
}
try {
MetaDataUpdate md =
new MetaDataUpdate(GitReferenceUpdated.DISABLED, nameKey, git);
md.getCommitBuilder().setAuthor(serverUser);
md.getCommitBuilder().setCommitter(serverUser);
ProjectConfig config = ProjectConfig.read(md);
loadProject(rs, config.getProject());
config.getAccessSections().clear();
convertRights(config);
// Grant out read on the config branch by default.
//
if (config.getProject().getNameKey().equals(systemConfig.wildProjectName)) {
AccessSection meta = config.getAccessSection(RefNames.REFS_CONFIG, true);
Permission read = meta.getPermission(READ, true);
read.getRule(config.resolve(projectOwners), true);
}
md.setMessage("Import project configuration from SQL\n");
config.commit(md);
} catch (ConfigInvalidException err) {
throw new OrmException("Cannot read project " + name, err);
} catch (IOException err) {
throw new OrmException("Cannot export project " + name, err);
} finally {
git.close();
}
}
}
}
private void loadProject(ResultSet rs, Project project) throws SQLException,
OrmException {
project.setDescription(rs.getString("description"));
project.setUseContributorAgreements(asInheritableBoolean(rs, "use_contributor_agreements"));
switch (rs.getString("submit_type").charAt(0)) {
case 'F':
project.setSubmitType(SubmitType.FAST_FORWARD_ONLY);
break;
case 'M':
project.setSubmitType(SubmitType.MERGE_IF_NECESSARY);
break;
case 'A':
project.setSubmitType(SubmitType.MERGE_ALWAYS);
break;
case 'C':
project.setSubmitType(SubmitType.CHERRY_PICK);
break;
default:
throw new OrmException("Unsupported submit_type="
+ rs.getString("submit_type") + " on project " + project.getName());
}
project.setUseSignedOffBy(asInheritableBoolean(rs, "use_signed_off_by"));
project.setRequireChangeID(asInheritableBoolean(rs, "require_change_id"));
project.setUseContentMerge(asInheritableBoolean(rs, "use_content_merge"));
project.setParentName(rs.getString("parent_name"));
}
private static InheritableBoolean asInheritableBoolean(ResultSet rs, String col)
throws SQLException {
return "Y".equals(rs.getString(col))
? InheritableBoolean.TRUE
: InheritableBoolean.INHERIT;
}
private void readOldRefRights(ReviewDb db) throws SQLException {
rightsByProject = new HashMap<>();
try (Statement s = newStatement(db);
ResultSet rs = s.executeQuery("SELECT * FROM ref_rights")) {
while (rs.next()) {
OldRefRight right = new OldRefRight(rs);
if (right.group == null || right.category == null) {
continue;
}
List<OldRefRight> list;
list = rightsByProject.get(right.project);
if (list == null) {
list = new ArrayList<>();
rightsByProject.put(right.project, list);
}
list.add(right);
}
}
}
private void readProjectParents(ReviewDb db) throws SQLException {
parentsByProject = new HashMap<>();
try (Statement s = newStatement(db);
ResultSet rs = s.executeQuery("SELECT * FROM projects")) {
while (rs.next()) {
String name = rs.getString("name");
String parent_name = rs.getString("parent_name");
if (parent_name == null) {
parent_name = systemConfig.wildProjectName.get();
}
parentsByProject.put(new Project.NameKey(name), //
new Project.NameKey(parent_name));
}
}
}
private void convertRights(ProjectConfig config) {
List<OldRefRight> myRights =
rightsByProject.get(config.getProject().getNameKey());
if (myRights == null) {
return;
}
for (OldRefRight old : myRights) {
AccessSection section = config.getAccessSection(old.ref_pattern, true);
GroupReference group = config.resolve(old.group);
if (OLD_SUBMIT.equals(old.category)) {
PermissionRule submit = rule(group);
if (old.max_value <= 0) {
submit.setDeny();
}
add(section, SUBMIT, old.exclusive, submit);
} else if (OLD_READ.equals(old.category)) {
if (old.exclusive) {
section.getPermission(READ, true).setExclusiveGroup(true);
newChangePermission(config, old.ref_pattern).setExclusiveGroup(true);
}
PermissionRule read = rule(group);
if (old.max_value <= 0) {
read.setDeny();
}
add(section, READ, old.exclusive, read);
if (3 <= old.max_value) {
newMergePermission(config, old.ref_pattern).add(rule(group));
} else if (3 <= inheritedMax(config, old)) {
newMergePermission(config, old.ref_pattern).add(deny(group));
}
if (2 <= old.max_value) {
newChangePermission(config, old.ref_pattern).add(rule(group));
} else if (2 <= inheritedMax(config, old)) {
newChangePermission(config, old.ref_pattern).add(deny(group));
}
} else if (OLD_OWN.equals(old.category)) {
add(section, OWNER, false, rule(group));
} else if (OLD_PUSH_TAG.equals(old.category)) {
PermissionRule push = rule(group);
if (old.max_value <= 0) {
push.setDeny();
}
add(section, PUSH_TAG, old.exclusive, push);
} else if (OLD_PUSH_HEAD.equals(old.category)) {
if (old.exclusive) {
section.getPermission(PUSH, true).setExclusiveGroup(true);
section.getPermission(CREATE, true).setExclusiveGroup(true);
}
PermissionRule push = rule(group);
if (old.max_value <= 0) {
push.setDeny();
}
push.setForce(3 <= old.max_value);
add(section, PUSH, old.exclusive, push);
if (2 <= old.max_value) {
add(section, CREATE, old.exclusive, rule(group));
} else if (2 <= inheritedMax(config, old)) {
add(section, CREATE, old.exclusive, deny(group));
}
} else if (OLD_FORGE_IDENTITY.equals(old.category)) {
if (old.exclusive) {
section.getPermission(FORGE_AUTHOR, true).setExclusiveGroup(true);
section.getPermission(FORGE_COMMITTER, true).setExclusiveGroup(true);
section.getPermission(FORGE_SERVER, true).setExclusiveGroup(true);
}
if (1 <= old.max_value) {
add(section, FORGE_AUTHOR, old.exclusive, rule(group));
}
if (2 <= old.max_value) {
add(section, FORGE_COMMITTER, old.exclusive, rule(group));
} else if (2 <= inheritedMax(config, old)) {
add(section, FORGE_COMMITTER, old.exclusive, deny(group));
}
if (3 <= old.max_value) {
add(section, FORGE_SERVER, old.exclusive, rule(group));
} else if (3 <= inheritedMax(config, old)) { add(section, FORGE_SERVER, old.exclusive, deny(group));
}
} else {
PermissionRule rule = rule(group);
rule.setRange(old.min_value, old.max_value);
if (old.min_value == 0 && old.max_value == 0) {
rule.setDeny();
}
LabelType type = labelTypes.byLabel(new LabelId(old.category));
String name = type != null ? type.getName() : old.category;
add(section, LABEL + name, old.exclusive, rule);
}
}
}
private static Permission newChangePermission(ProjectConfig config,
String name) {
if (name.startsWith(AccessSection.REGEX_PREFIX)) {
name = AccessSection.REGEX_PREFIX
+ "refs/for/"
+ name.substring(AccessSection.REGEX_PREFIX.length());
} else {
name = "refs/for/" + name;
}
return config.getAccessSection(name, true).getPermission(PUSH, true);
}
private static Permission newMergePermission(ProjectConfig config,
String name) {
if (name.startsWith(AccessSection.REGEX_PREFIX)) {
name = AccessSection.REGEX_PREFIX
+ "refs/for/"
+ name.substring(AccessSection.REGEX_PREFIX.length());
} else {
name = "refs/for/" + name;
}
return config.getAccessSection(name, true).getPermission(PUSH_MERGE, true);
}
private static PermissionRule rule(GroupReference group) {
return new PermissionRule(group);
}
private static PermissionRule deny(GroupReference group) {
PermissionRule rule = rule(group);
rule.setDeny();
return rule;
}
private int inheritedMax(ProjectConfig config, OldRefRight old) {
int max = 0;
String ref = old.ref_pattern;
String category = old.category;
AccountGroup.UUID group = old.group.getUUID();
Project.NameKey project = config.getProject().getParent();
if (project == null) {
project = systemConfig.wildProjectName;
}
do {
List<OldRefRight> rights = rightsByProject.get(project);
if (rights != null) {
for (OldRefRight r : rights) {
if (r.ref_pattern.equals(ref) //
&& r.group.getUUID().equals(group) //
&& r.category.equals(category)) {
max = Math.max(max, r.max_value);
break;
}
}
}
project = parentsByProject.get(project);
} while (!project.equals(systemConfig.wildProjectName));
return max;
}
private static void add(AccessSection section, String name,
boolean exclusive, PermissionRule rule) {
Permission p = section.getPermission(name, true);
if (exclusive) {
p.setExclusiveGroup(true);
}
p.add(rule);
}
private class OldRefRight {
final int min_value;
final int max_value;
final String ref_pattern;
final boolean exclusive;
final GroupReference group;
final String category;
final Project.NameKey project;
OldRefRight(ResultSet rs) throws SQLException {
min_value = rs.getInt("min_value");
max_value = rs.getInt("max_value");
project = new Project.NameKey(rs.getString("project_name"));
String r = rs.getString("ref_pattern");
exclusive = r.startsWith("-");
if (exclusive) {
r = r.substring(1);
}
ref_pattern = r;
category = rs.getString("category_id");
group = groupMap.get(new AccountGroup.Id(rs.getInt("group_id")));
}
}
}

View File

@ -1,25 +0,0 @@
// 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.inject.Inject;
import com.google.inject.Provider;
public class Schema_54 extends SchemaVersion {
@Inject
Schema_54(Provider<Schema_53> prior) {
super(prior);
}
}

View File

@ -1,62 +0,0 @@
// 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.reviewdb.client.Project;
import com.google.gerrit.reviewdb.client.SystemConfig;
import com.google.gerrit.reviewdb.server.ReviewDb;
import com.google.gerrit.server.git.GitRepositoryManager;
import com.google.gerrit.server.git.LocalDiskRepositoryManager;
import com.google.gwtorm.server.OrmException;
import com.google.inject.Inject;
import com.google.inject.Provider;
import org.eclipse.jgit.lib.Constants;
import org.eclipse.jgit.lib.RepositoryCache.FileKey;
import org.eclipse.jgit.util.FS;
import java.io.File;
import java.util.Collections;
public class Schema_55 extends SchemaVersion {
private final GitRepositoryManager mgr;
@Inject
Schema_55(Provider<Schema_54> prior, GitRepositoryManager mgr) {
super(prior);
this.mgr = mgr;
}
@Override
protected void migrateData(ReviewDb db, UpdateUI ui) throws OrmException {
SystemConfig sc = db.systemConfig().get(new SystemConfig.Key());
String oldName = sc.wildProjectName.get();
String newName = "All-Projects";
if ("-- All Projects --".equals(oldName)) {
ui.message("Renaming \"" + oldName + "\" to \"" + newName + "\"");
File base = ((LocalDiskRepositoryManager) mgr).getBasePath();
File oldDir = FileKey.resolve(new File(base, oldName), FS.DETECTED);
File newDir = new File(base, newName + Constants.DOT_GIT_EXT);
if (!oldDir.renameTo(newDir)) {
throw new OrmException("Cannot rename " + oldDir.getAbsolutePath()
+ " to " + newDir.getAbsolutePath());
}
sc.wildProjectName = new Project.NameKey(newName);
db.systemConfig().update(Collections.singleton(sc));
}
}
}

View File

@ -1,88 +0,0 @@
// 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.reviewdb.client.Project;
import com.google.gerrit.reviewdb.client.RefNames;
import com.google.gerrit.reviewdb.server.ReviewDb;
import com.google.gerrit.server.git.GitRepositoryManager;
import com.google.inject.Inject;
import com.google.inject.Provider;
import org.eclipse.jgit.lib.Constants;
import org.eclipse.jgit.lib.Ref;
import org.eclipse.jgit.lib.RefDatabase;
import org.eclipse.jgit.lib.RefUpdate;
import org.eclipse.jgit.lib.Repository;
import java.io.IOException;
import java.util.HashSet;
import java.util.Map;
import java.util.Set;
public class Schema_56 extends SchemaVersion {
private final GitRepositoryManager mgr;
private final Set<String> keysOne;
private final Set<String> keysTwo;
@Inject
Schema_56(Provider<Schema_55> prior, GitRepositoryManager mgr) {
super(prior);
this.mgr = mgr;
keysOne = new HashSet<>();
keysTwo = new HashSet<>();
keysOne.add(RefNames.REFS_CONFIG);
keysTwo.add(RefNames.REFS_CONFIG);
keysTwo.add(Constants.HEAD);
}
@Override
protected void migrateData(ReviewDb db, UpdateUI ui) {
for (Project.NameKey name : mgr.list()) {
Repository git;
try {
git = mgr.openRepository(name);
} catch (IOException e) {
ui.message("warning: Cannot open " + name.get());
continue;
}
try {
Map<String, Ref> all;
try {
all = git.getRefDatabase().getRefs(RefDatabase.ALL);
} catch (IOException e) {
ui.message("warning: " + name.get() + ": Cannot read refs: "
+ e.getMessage());
e.printStackTrace();
continue;
}
if (all.keySet().equals(keysOne) || all.keySet().equals(keysTwo)) {
try {
RefUpdate update = git.updateRef(Constants.HEAD);
update.disableRefLog();
update.link(RefNames.REFS_CONFIG);
} catch (IOException err) {
ui.message("warning: " + name.get() + ": Cannot update HEAD to "
+ RefNames.REFS_CONFIG + ": " + err.getMessage());
}
}
} finally {
git.close();
}
}
}
}

View File

@ -1,188 +0,0 @@
// 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.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
boolean isAccountGroupEmpty = false;
try (PreparedStatement stmt = prepareStatement(db,
"SELECT COUNT(1) FROM account_group_includes WHERE group_id = ?")) {
stmt.setInt(1, sc.batchUsersGroupId.get());
try (ResultSet rs = stmt.executeQuery()) {
if (rs.next()) {
isAccountGroupEmpty = rs.getInt(1) == 0;
}
}
}
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));
}
}

View File

@ -1,25 +0,0 @@
// 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.inject.Inject;
import com.google.inject.Provider;
public class Schema_58 extends SchemaVersion {
@Inject
Schema_58(Provider<Schema_57> prior) {
super(prior);
}
}

View File

@ -1,27 +0,0 @@
// 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.inject.Inject;
import com.google.inject.Provider;
public class Schema_59 extends SchemaVersion {
@Inject
Schema_59(Provider<Schema_58> prior) {
super(prior);
}
// Don't migrate columns; they are removed in Schema_100.
}

View File

@ -1,70 +0,0 @@
// 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.reviewdb.client.Change;
import com.google.gerrit.reviewdb.client.ChangeMessage;
import com.google.gerrit.reviewdb.client.PatchSet;
import com.google.gerrit.reviewdb.server.ReviewDb;
import com.google.gwtorm.server.OrmException;
import com.google.gwtorm.server.ResultSet;
import com.google.inject.Inject;
import com.google.inject.Provider;
import java.util.LinkedList;
import java.util.List;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
public class Schema_60 extends SchemaVersion {
@Inject
Schema_60(Provider<Schema_59> prior) {
super(prior);
}
@Override
protected void migrateData(ReviewDb db, UpdateUI ui) throws OrmException {
Pattern patternA = Pattern.compile("Patch Set ([0-9]+):.*", Pattern.DOTALL);
Pattern patternB = Pattern.compile("Uploaded patch set ([0-9]+).");
ResultSet<ChangeMessage> results = db.changeMessages().all();
List<ChangeMessage> updates = new LinkedList<>();
for (ChangeMessage cm : results) {
Change.Id id = cm.getKey().getParentKey();
String msg = cm.getMessage();
Matcher matcherA = patternA.matcher(msg);
Matcher matcherB = patternB.matcher(msg);
PatchSet.Id newId = null;
if (matcherA.matches()) {
int patchSetNum = Integer.parseInt(matcherA.group(1));
newId = new PatchSet.Id(id, patchSetNum);
} else if (matcherB.matches()) {
int patchSetNum = Integer.parseInt(matcherB.group(1));
newId = new PatchSet.Id(id, patchSetNum);
}
if (newId != null) {
cm.setPatchSetId(newId);
updates.add(cm);
}
if (updates.size() >= 100) {
db.changeMessages().update(updates);
updates.clear();
}
}
if (!updates.isEmpty()) {
db.changeMessages().update(updates);
}
}
}

View File

@ -1,25 +0,0 @@
// 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.inject.Inject;
import com.google.inject.Provider;
public class Schema_61 extends SchemaVersion {
@Inject
Schema_61(Provider<Schema_60> prior) {
super(prior);
}
}

View File

@ -1,25 +0,0 @@
// 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.inject.Inject;
import com.google.inject.Provider;
public class Schema_62 extends SchemaVersion {
@Inject
Schema_62(Provider<Schema_61> prior) {
super(prior);
}
}

View File

@ -1,45 +0,0 @@
// Copyright (C) 2012 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.reviewdb.server.ReviewDb;
import com.google.gwtorm.jdbc.JdbcSchema;
import com.google.gwtorm.schema.sql.DialectPostgreSQL;
import com.google.inject.Inject;
import com.google.inject.Provider;
import java.sql.SQLException;
import java.sql.Statement;
public class Schema_63 extends SchemaVersion {
@Inject
Schema_63(Provider<Schema_62> prior) {
super(prior);
}
@Override
protected void migrateData(ReviewDb db, UpdateUI ui) throws SQLException {
try (Statement stmt = newStatement(db)) {
if (((JdbcSchema) db).getDialect() instanceof DialectPostgreSQL) {
stmt.execute("CREATE INDEX changes_byBranchClosed"
+ " ON changes (status, dest_project_name, dest_branch_name, sort_key)"
+ " WHERE open = 'N'");
} else {
stmt.execute("CREATE INDEX changes_byBranchClosed"
+ " ON changes (status, dest_project_name, dest_branch_name, sort_key)");
}
}
}
}

View File

@ -1,110 +0,0 @@
// Copyright (C) 2012 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.common.collect.Lists;
import com.google.gerrit.common.data.AccessSection;
import com.google.gerrit.common.data.GlobalCapability;
import com.google.gerrit.common.data.GroupReference;
import com.google.gerrit.common.data.Permission;
import com.google.gerrit.reviewdb.client.AccountGroup;
import com.google.gerrit.reviewdb.server.ReviewDb;
import com.google.gerrit.server.GerritPersonIdent;
import com.google.gerrit.server.config.AllProjectsName;
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.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 java.io.IOException;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.Statement;
import java.util.List;
public class Schema_64 extends SchemaVersion {
private final AllProjectsName allProjects;
private final GitRepositoryManager mgr;
private final PersonIdent serverUser;
@Inject
Schema_64(Provider<Schema_63> prior,
AllProjectsName allProjects,
GitRepositoryManager mgr,
@GerritPersonIdent PersonIdent serverUser) {
super(prior);
this.allProjects = allProjects;
this.mgr = mgr;
this.serverUser = serverUser;
}
@Override
protected void migrateData(ReviewDb db, UpdateUI ui)
throws OrmException, SQLException {
List<GroupReference> groups = Lists.newArrayList();
try (Statement stmt = newStatement(db);
ResultSet rs = stmt.executeQuery(
"SELECT group_uuid, name FROM account_groups WHERE email_only_authors = 'Y'")) {
while (rs.next()) {
AccountGroup.UUID uuid = new AccountGroup.UUID(rs.getString(1));
GroupReference group = new GroupReference(uuid, rs.getString(2));
groups.add(group);
}
}
if (groups.isEmpty()) {
return;
}
ui.message("Moved account_groups.email_only_authors to 'Email Reviewers' capability");
Repository git;
try {
git = mgr.openRepository(allProjects);
} catch (IOException e) {
throw new OrmException(e);
}
try {
MetaDataUpdate md =
new MetaDataUpdate(GitReferenceUpdated.DISABLED, allProjects, git);
md.getCommitBuilder().setAuthor(serverUser);
md.getCommitBuilder().setCommitter(serverUser);
ProjectConfig config = ProjectConfig.read(md);
AccessSection section =
config.getAccessSection(AccessSection.GLOBAL_CAPABILITIES, true);
Permission capability =
section.getPermission(GlobalCapability.EMAIL_REVIEWERS, true);
for (GroupReference group : groups) {
capability.getRule(config.resolve(group), true).setDeny();
}
md.setMessage("Upgrade to Gerrit Code Review schema 64\n");
config.commit(md);
} catch (IOException e) {
throw new OrmException(e);
} catch (ConfigInvalidException e) {
throw new OrmException(e);
} finally {
git.close();
}
}
}

View File

@ -1,451 +0,0 @@
// Copyright (C) 2012 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.common.base.Strings;
import com.google.common.collect.Lists;
import com.google.common.collect.Maps;
import com.google.gerrit.common.TimeUtil;
import com.google.gerrit.common.data.AccessSection;
import com.google.gerrit.common.data.ContributorAgreement;
import com.google.gerrit.common.data.GlobalCapability;
import com.google.gerrit.common.data.GroupReference;
import com.google.gerrit.common.data.PermissionRule;
import com.google.gerrit.common.data.PermissionRule.Action;
import com.google.gerrit.reviewdb.client.Account;
import com.google.gerrit.reviewdb.client.AccountGroup;
import com.google.gerrit.reviewdb.client.AccountGroupMember;
import com.google.gerrit.reviewdb.client.AccountGroupMemberAudit;
import com.google.gerrit.reviewdb.client.AccountGroupName;
import com.google.gerrit.reviewdb.server.ReviewDb;
import com.google.gerrit.server.GerritPersonIdent;
import com.google.gerrit.server.account.GroupUUID;
import com.google.gerrit.server.config.AllProjectsName;
import com.google.gerrit.server.config.AnonymousCowardName;
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.gerrit.server.git.VersionedMetaData.BatchMetaDataUpdate;
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.CommitBuilder;
import org.eclipse.jgit.lib.PersonIdent;
import org.eclipse.jgit.lib.Repository;
import org.eclipse.jgit.util.SystemReader;
import java.io.IOException;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.Statement;
import java.sql.Timestamp;
import java.util.Collections;
import java.util.Comparator;
import java.util.Date;
import java.util.List;
import java.util.Map;
import java.util.TimeZone;
public class Schema_65 extends SchemaVersion {
private final AllProjectsName allProjects;
private final GitRepositoryManager mgr;
private final PersonIdent serverUser;
private final @AnonymousCowardName String anonymousCowardName;
@Inject
Schema_65(Provider<Schema_64> prior,
AllProjectsName allProjects,
GitRepositoryManager mgr,
@GerritPersonIdent PersonIdent serverUser,
@AnonymousCowardName String anonymousCowardName) {
super(prior);
this.allProjects = allProjects;
this.mgr = mgr;
this.serverUser = serverUser;
this.anonymousCowardName = anonymousCowardName;
}
@Override
protected void migrateData(ReviewDb db, UpdateUI ui)
throws OrmException, SQLException {
Repository git;
try {
git = mgr.openRepository(allProjects);
} catch (IOException e) {
throw new OrmException(e);
}
try {
MetaDataUpdate md =
new MetaDataUpdate(GitReferenceUpdated.DISABLED, allProjects, git);
ProjectConfig config = ProjectConfig.read(md);
Map<Integer, ContributorAgreement> agreements = getAgreementToAdd(db, config);
if (agreements.isEmpty()) {
return;
}
ui.message("Moved contributor agreements to project.config");
// Create the auto verify groups.
List<AccountGroup.UUID> adminGroupUUIDs = getAdministrateServerGroups(config);
for (ContributorAgreement agreement : agreements.values()) {
if (agreement.getAutoVerify() != null) {
getOrCreateGroupForIndividuals(db, config, adminGroupUUIDs, agreement);
}
}
// Scan AccountAgreement
long minTime = addAccountAgreements(db, config, adminGroupUUIDs, agreements);
ProjectConfig base = ProjectConfig.read(md, null);
for (ContributorAgreement agreement : agreements.values()) {
base.replace(agreement);
}
base.getAccountsSection().setSameGroupVisibility(
config.getAccountsSection().getSameGroupVisibility());
BatchMetaDataUpdate batch = base.openUpdate(md);
try {
// Scan AccountGroupAgreement
List<AccountGroupAgreement> groupAgreements =
getAccountGroupAgreements(db, agreements);
// Find the earliest change
for (AccountGroupAgreement aga : groupAgreements) {
minTime = Math.min(minTime, aga.getTime());
}
minTime -= 60 * 1000; // 1 Minute
CommitBuilder commit = new CommitBuilder();
commit.setAuthor(new PersonIdent(serverUser, new Date(minTime)));
commit.setCommitter(new PersonIdent(serverUser, new Date(minTime)));
commit.setMessage("Add the ContributorAgreements for upgrade to Gerrit Code Review schema 65\n");
batch.write(commit);
for (AccountGroupAgreement aga : groupAgreements) {
AccountGroup group = db.accountGroups().get(aga.groupId);
if (group == null) {
continue;
}
ContributorAgreement agreement = agreements.get(aga.claId);
agreement.getAccepted().add(new PermissionRule(config.resolve(group)));
base.replace(agreement);
PersonIdent ident = null;
if (aga.reviewedBy != null) {
Account ua = db.accounts().get(aga.reviewedBy);
if (ua != null) {
String name = ua.getFullName();
String email = ua.getPreferredEmail();
if (email == null || email.isEmpty()) {
// No preferred email is configured. Use a generic identity so we
// don't leak an address the user may have given us, but doesn't
// necessarily want to publish through Git records.
//
String user = ua.getUserName();
if (user == null || user.isEmpty()) {
user = "account-" + ua.getId().toString();
}
String host = SystemReader.getInstance().getHostname();
email = user + "@" + host;
}
if (name == null || name.isEmpty()) {
final int at = email.indexOf('@');
if (0 < at) {
name = email.substring(0, at);
} else {
name = anonymousCowardName;
}
}
ident = new PersonIdent(name, email, new Date(aga.getTime()), TimeZone.getDefault());
}
}
if (ident == null) {
ident = new PersonIdent(serverUser, new Date(aga.getTime()));
}
// Build the commits such that it keeps track of the date added and
// who added it.
commit = new CommitBuilder();
commit.setAuthor(ident);
commit.setCommitter(new PersonIdent(serverUser, new Date(aga.getTime())));
String msg = String.format("Accept %s contributor agreement for %s\n",
agreement.getName(), group.getName());
if (!Strings.isNullOrEmpty(aga.reviewComments)) {
msg += "\n" + aga.reviewComments + "\n";
}
commit.setMessage(msg);
batch.write(commit);
}
// Merge the agreements with the other data in project.config.
commit = new CommitBuilder();
commit.setAuthor(serverUser);
commit.setCommitter(serverUser);
commit.setMessage("Upgrade to Gerrit Code Review schema 65\n");
commit.addParentId(config.getRevision());
batch.write(config, commit);
// Save the the final metadata.
batch.commitAt(config.getRevision());
} finally {
batch.close();
}
} catch (IOException e) {
throw new OrmException(e);
} catch (ConfigInvalidException e) {
throw new OrmException(e);
} finally {
git.close();
}
}
private Map<Integer, ContributorAgreement> getAgreementToAdd(
ReviewDb db, ProjectConfig config) throws SQLException {
try (Statement stmt = newStatement(db)) {
ResultSet rs = stmt.executeQuery(
"SELECT short_name, id, require_contact_information," +
" short_description, agreement_url, auto_verify " +
"FROM contributor_agreements WHERE active = 'Y'");
try {
Map<Integer, ContributorAgreement> agreements = Maps.newHashMap();
while (rs.next()) {
String name = rs.getString(1);
if (config.getContributorAgreement(name) != null) {
continue; // already exists
}
ContributorAgreement a = config.getContributorAgreement(name, true);
agreements.put(rs.getInt(2), a);
a.setRequireContactInformation("Y".equals(rs.getString(3)));
a.setDescription(rs.getString(4));
a.setAgreementUrl(rs.getString(5));
if ("Y".equals(rs.getString(6))) {
a.setAutoVerify(new GroupReference(null, null));
}
}
return agreements;
} finally {
rs.close();
}
}
}
private AccountGroup createGroup(ReviewDb db, String groupName,
AccountGroup.UUID adminGroupUUID, String description)
throws OrmException {
final AccountGroup.Id groupId =
new AccountGroup.Id(db.nextAccountGroupId());
final AccountGroup.NameKey nameKey = new AccountGroup.NameKey(groupName);
final AccountGroup.UUID uuid = GroupUUID.make(groupName, serverUser);
final AccountGroup group = new AccountGroup(nameKey, groupId, uuid);
group.setOwnerGroupUUID(adminGroupUUID);
group.setDescription(description);
final AccountGroupName gn = new AccountGroupName(group);
// first insert the group name to validate that the group name hasn't
// already been used to create another group
db.accountGroupNames().insert(Collections.singleton(gn));
db.accountGroups().insert(Collections.singleton(group));
return group;
}
private List<AccountGroup.UUID> getAdministrateServerGroups(
ProjectConfig cfg) {
List<PermissionRule> rules = cfg.getAccessSection(AccessSection.GLOBAL_CAPABILITIES)
.getPermission(GlobalCapability.ADMINISTRATE_SERVER)
.getRules();
List<AccountGroup.UUID> groups =
Lists.newArrayListWithExpectedSize(rules.size());
for (PermissionRule rule : rules) {
if (rule.getAction() == Action.ALLOW) {
groups.add(rule.getGroup().getUUID());
}
}
if (groups.isEmpty()) {
throw new IllegalStateException("no administrator group found");
}
return groups;
}
private GroupReference getOrCreateGroupForIndividuals(ReviewDb db,
ProjectConfig config, List<AccountGroup.UUID> adminGroupUUIDs,
ContributorAgreement agreement)
throws OrmException {
if (!agreement.getAccepted().isEmpty()) {
return agreement.getAccepted().get(0).getGroup();
}
String name = "CLA Accepted - " + agreement.getName();
AccountGroupName agn =
db.accountGroupNames().get(new AccountGroup.NameKey(name));
AccountGroup ag;
if (agn != null) {
ag = db.accountGroups().get(agn.getId());
if (ag == null) {
throw new IllegalStateException(
"account group name exists but account group does not: " + name);
}
if (!adminGroupUUIDs.contains(ag.getOwnerGroupUUID())) {
throw new IllegalStateException(
"individual group exists with non admin owner group: " + name);
}
} else {
ag = createGroup(db, name, adminGroupUUIDs.get(0),
String.format("Users who have accepted the %s CLA", agreement.getName()));
}
GroupReference group = config.resolve(ag);
agreement.setAccepted(Lists.newArrayList(new PermissionRule(group)));
if (agreement.getAutoVerify() != null) {
agreement.setAutoVerify(group);
}
// Don't allow accounts in the same individual CLA group to see each
// other in same group visibility mode.
List<PermissionRule> sameGroupVisibility =
config.getAccountsSection().getSameGroupVisibility();
PermissionRule rule = new PermissionRule(group);
rule.setDeny();
if (!sameGroupVisibility.contains(rule)) {
sameGroupVisibility.add(rule);
}
return group;
}
private long addAccountAgreements(ReviewDb db, ProjectConfig config,
List<AccountGroup.UUID> adminGroupUUIDs,
Map<Integer, ContributorAgreement> agreements)
throws SQLException, OrmException {
try (Statement stmt = newStatement(db)) {
ResultSet rs = stmt.executeQuery(
"SELECT account_id, cla_id, accepted_on, reviewed_by," +
" reviewed_on, review_comments " +
"FROM account_agreements WHERE status = 'V'");
try {
long minTime = TimeUtil.nowMs();
while (rs.next()) {
Account.Id accountId = new Account.Id(rs.getInt(1));
Account.Id reviewerId = new Account.Id(rs.getInt(4));
if (rs.wasNull()) {
reviewerId = accountId;
}
int claId = rs.getInt(2);
ContributorAgreement agreement = agreements.get(claId);
if (agreement == null) {
continue; // Agreement is invalid
}
Timestamp acceptedOn = rs.getTimestamp(3);
minTime = Math.min(minTime, acceptedOn.getTime());
// Enter Agreement
GroupReference individualGroup =
getOrCreateGroupForIndividuals(db, config, adminGroupUUIDs, agreement);
AccountGroup.Id groupId = db.accountGroups()
.byUUID(individualGroup.getUUID())
.toList()
.get(0)
.getId();
final AccountGroupMember.Key key =
new AccountGroupMember.Key(accountId, groupId);
AccountGroupMember m = db.accountGroupMembers().get(key);
if (m == null) {
m = new AccountGroupMember(key);
db.accountGroupMembersAudit().insert(
Collections.singleton(
new AccountGroupMemberAudit(m, reviewerId, acceptedOn)));
db.accountGroupMembers().insert(Collections.singleton(m));
}
}
return minTime;
} finally {
rs.close();
}
}
}
private static class AccountGroupAgreement {
private AccountGroup.Id groupId;
private int claId;
private Timestamp acceptedOn;
private Account.Id reviewedBy;
private Timestamp reviewedOn;
private String reviewComments;
private long getTime() {
return (reviewedOn == null) ? acceptedOn.getTime() : reviewedOn.getTime();
}
}
private List<AccountGroupAgreement> getAccountGroupAgreements(
ReviewDb db, Map<Integer, ContributorAgreement> agreements)
throws SQLException {
try (Statement stmt = newStatement(db)) {
ResultSet rs = stmt.executeQuery(
"SELECT group_id, cla_id, accepted_on, reviewed_by, reviewed_on, " +
" review_comments " +
"FROM account_group_agreements");
try {
List<AccountGroupAgreement> groupAgreements = Lists.newArrayList();
while (rs.next()) {
AccountGroupAgreement a = new AccountGroupAgreement();
a.groupId = new AccountGroup.Id(rs.getInt(1));
a.claId = rs.getInt(2);
if (!agreements.containsKey(a.claId)) {
continue; // Agreement is invalid
}
a.acceptedOn = rs.getTimestamp(3);
a.reviewedBy = new Account.Id(rs.getInt(4));
if (rs.wasNull()) {
a.reviewedBy = null;
}
a.reviewedOn = rs.getTimestamp(5);
if (rs.wasNull()) {
a.reviewedOn = null;
}
a.reviewComments = rs.getString(6);
if (rs.wasNull()) {
a.reviewComments = null;
}
groupAgreements.add(a);
}
Collections.sort(groupAgreements, new Comparator<AccountGroupAgreement>() {
@Override
public int compare(
AccountGroupAgreement a1, AccountGroupAgreement a2) {
return Long.compare(a1.getTime(), a2.getTime());
}
});
return groupAgreements;
} finally {
rs.close();
}
}
}
}

View File

@ -1,26 +0,0 @@
// Copyright (C) 2012 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.inject.Inject;
import com.google.inject.Provider;
public class Schema_66 extends SchemaVersion {
@Inject
Schema_66(Provider<Schema_65> prior) {
super(prior);
}
}

View File

@ -1,86 +0,0 @@
// Copyright (C) 2012 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.common.collect.Iterables;
import com.google.common.collect.Lists;
import com.google.common.collect.Maps;
import com.google.common.collect.Sets;
import com.google.gerrit.reviewdb.client.AccountGroup;
import com.google.gerrit.reviewdb.server.ReviewDb;
import com.google.gwtorm.server.OrmException;
import com.google.inject.Inject;
import com.google.inject.Provider;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.Statement;
import java.util.List;
import java.util.Map;
import java.util.Map.Entry;
import java.util.Set;
public class Schema_67 extends SchemaVersion {
@Inject
Schema_67(Provider<Schema_66> prior) {
super(prior);
}
@Override
protected void migrateData(ReviewDb db, UpdateUI ui)
throws OrmException, SQLException {
ui.message("Update ownerGroupId to ownerGroupUUID");
// Scan all AccountGroup, and find the ones that need the owner_group_id
// migrated to owner_group_uuid.
Map<AccountGroup.Id, AccountGroup.Id> idMap = Maps.newHashMap();
try (Statement stmt = newStatement(db);
ResultSet rs = stmt.executeQuery(
"SELECT group_id, owner_group_id FROM account_groups"
+ " WHERE owner_group_uuid is NULL or owner_group_uuid =''")) {
while (rs.next()) {
AccountGroup.Id groupId = new AccountGroup.Id(rs.getInt(1));
AccountGroup.Id ownerId = new AccountGroup.Id(rs.getInt(2));
idMap.put(groupId, ownerId);
}
}
// Lookup up all groups by ID.
Set<AccountGroup.Id> all =
Sets.newHashSet(Iterables.concat(idMap.keySet(), idMap.values()));
Map<AccountGroup.Id, AccountGroup> groups = Maps.newHashMap();
com.google.gwtorm.server.ResultSet<AccountGroup> rs =
db.accountGroups().get(all);
try {
for (AccountGroup group : rs) {
groups.put(group.getId(), group);
}
} finally {
rs.close();
}
// Update the ownerGroupUUID.
List<AccountGroup> toUpdate = Lists.newArrayListWithCapacity(idMap.size());
for (Entry<AccountGroup.Id, AccountGroup.Id> entry : idMap.entrySet()) {
AccountGroup group = groups.get(entry.getKey());
AccountGroup owner = groups.get(entry.getValue());
group.setOwnerGroupUUID(owner.getGroupUUID());
toUpdate.add(group);
}
db.accountGroups().update(toUpdate);
}
}

View File

@ -1,56 +0,0 @@
// Copyright (C) 2012 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.reviewdb.server.ReviewDb;
import com.google.inject.Inject;
import com.google.inject.Provider;
import java.sql.SQLException;
import java.sql.Statement;
public class Schema_68 extends SchemaVersion {
@Inject
Schema_68(Provider<Schema_67> prior) {
super(prior);
}
@Override
protected void migrateData(final ReviewDb db, final UpdateUI ui)
throws SQLException {
try (Statement stmt = newStatement(db)) {
stmt.execute("CREATE INDEX submodule_subscription_access_bySubscription"
+ " ON submodule_subscriptions (submodule_project_name, submodule_branch_name)");
} catch (SQLException e) {
// the index creation might have failed because the index exists already,
// in this case the exception can be safely ignored,
// but there are also other possible reasons for an exception here that
// should not be ignored,
// -> ask the user whether to ignore this exception or not
ui.message("warning: Cannot create index for submodule subscriptions");
ui.message(e.getMessage());
if (ui.isBatch()) {
ui.message("you may ignore this warning when running in interactive mode");
throw e;
} else {
final boolean answer = ui.yesno(false, "Ignore warning and proceed with schema upgrade");
if (!answer) {
throw e;
}
}
}
}
}

View File

@ -1,217 +0,0 @@
// Copyright (C) 2012 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.common.base.Strings.isNullOrEmpty;
import com.google.common.base.Preconditions;
import com.google.common.collect.Lists;
import com.google.common.collect.Maps;
import com.google.common.collect.Sets;
import com.google.gerrit.common.data.GroupReference;
import com.google.gerrit.reviewdb.client.AccountGroup;
import com.google.gerrit.reviewdb.client.Project;
import com.google.gerrit.reviewdb.server.ReviewDb;
import com.google.gerrit.server.GerritPersonIdent;
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.server.OrmException;
import com.google.inject.Inject;
import com.google.inject.Provider;
import org.eclipse.jgit.errors.ConfigInvalidException;
import org.eclipse.jgit.errors.RepositoryNotFoundException;
import org.eclipse.jgit.lib.PersonIdent;
import org.eclipse.jgit.lib.Repository;
import java.io.IOException;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.Statement;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Set;
import javax.naming.NamingException;
import javax.naming.ldap.LdapName;
public class Schema_69 extends SchemaVersion {
private final GitRepositoryManager mgr;
private final PersonIdent serverUser;
@Inject
Schema_69(Provider<Schema_68> prior,
GitRepositoryManager mgr,
@GerritPersonIdent PersonIdent serverUser) {
super(prior);
this.mgr = mgr;
this.serverUser = serverUser;
}
@Override
protected void migrateData(ReviewDb db, UpdateUI ui)
throws OrmException, SQLException {
// Find all groups that have an LDAP type.
Map<AccountGroup.UUID, GroupReference> ldapUUIDMap = Maps.newHashMap();
Set<AccountGroup.UUID> toResolve = Sets.newHashSet();
List<AccountGroup.Id> toDelete = Lists.newArrayList();
List<AccountGroup.NameKey> namesToDelete = Lists.newArrayList();
try (Statement stmt = newStatement(db);
ResultSet rs = stmt.executeQuery(
"SELECT group_id, group_uuid, external_name, name FROM account_groups"
+ " WHERE group_type ='LDAP'")) {
while (rs.next()) {
AccountGroup.Id groupId = new AccountGroup.Id(rs.getInt(1));
AccountGroup.UUID groupUUID = new AccountGroup.UUID(rs.getString(2));
AccountGroup.NameKey name = new AccountGroup.NameKey(rs.getString(4));
String dn = rs.getString(3);
if (isNullOrEmpty(dn)) {
// The LDAP group does not have a DN. Determine if the UUID is used.
toResolve.add(groupUUID);
} else {
toDelete.add(groupId);
namesToDelete.add(name);
GroupReference ref = groupReference(dn);
ldapUUIDMap.put(groupUUID, ref);
}
}
} catch (NamingException e) {
throw new RuntimeException(e);
}
if (toDelete.isEmpty() && toResolve.isEmpty()) {
return; // No ldap groups. Nothing to do.
}
ui.message("Update LDAP groups to be GroupReferences.");
// Update the groupOwnerUUID for LDAP groups to point to the new UUID.
List<AccountGroup> toUpdate = Lists.newArrayList();
Set<AccountGroup.UUID> resolveToUpdate = Sets.newHashSet();
Map<AccountGroup.UUID, AccountGroup> resolveGroups = Maps.newHashMap();
for (AccountGroup g : db.accountGroups().all()) {
if (ldapUUIDMap.containsKey(g.getGroupUUID())) {
continue; // Ignore the LDAP groups with a valid DN.
} else if (toResolve.contains(g.getGroupUUID())) {
resolveGroups.put(g.getGroupUUID(), g); // Keep the ones to resolve.
continue;
}
GroupReference ref = ldapUUIDMap.get(g.getOwnerGroupUUID());
if (ref != null) {
// Update the owner group UUID to the new ldap UUID scheme.
g.setOwnerGroupUUID(ref.getUUID());
toUpdate.add(g);
} else if (toResolve.contains(g.getOwnerGroupUUID())) {
// The unresolved group is used as an owner.
// Add to the list of LDAP groups to be made INTERNAL.
resolveToUpdate.add(g.getOwnerGroupUUID());
}
}
toResolve.removeAll(resolveToUpdate);
// Update project.config group references to use the new LDAP GroupReference
for (Project.NameKey name : mgr.list()) {
Repository git;
try {
git = mgr.openRepository(name);
} catch (RepositoryNotFoundException e) {
throw new OrmException(e);
} catch (IOException e) {
throw new OrmException(e);
}
try {
MetaDataUpdate md =
new MetaDataUpdate(GitReferenceUpdated.DISABLED, name, git);
md.getCommitBuilder().setAuthor(serverUser);
md.getCommitBuilder().setCommitter(serverUser);
ProjectConfig config = ProjectConfig.read(md);
// Update the existing refences to the new reference.
boolean updated = false;
for (Map.Entry<AccountGroup.UUID, GroupReference> entry: ldapUUIDMap.entrySet()) {
GroupReference ref = config.getGroup(entry.getKey());
if (ref != null) {
updated = true;
ref.setName(entry.getValue().getName());
ref.setUUID(entry.getValue().getUUID());
config.resolve(ref);
}
}
// Determine if a toResolve group is used and should be made INTERNAL.
Iterator<AccountGroup.UUID> iter = toResolve.iterator();
while (iter.hasNext()) {
AccountGroup.UUID uuid = iter.next();
if (config.getGroup(uuid) != null) {
resolveToUpdate.add(uuid);
iter.remove();
}
}
if (!updated) {
continue;
}
md.setMessage("Switch LDAP group UUIDs to DNs\n");
config.commit(md);
} catch (IOException e) {
throw new OrmException(e);
} catch (ConfigInvalidException e) {
throw new OrmException(e);
} finally {
git.close();
}
}
for (AccountGroup.UUID uuid : resolveToUpdate) {
AccountGroup group = resolveGroups.get(uuid);
ui.message(String.format(
"*** Group has no DN and is in use: %s",
group.getName()));
}
for (AccountGroup.UUID uuid : toResolve) {
AccountGroup group = resolveGroups.get(uuid);
toDelete.add(group.getId());
namesToDelete.add(group.getNameKey());
}
// Update group owners
db.accountGroups().update(toUpdate);
// Delete existing LDAP groups
db.accountGroupNames().deleteKeys(namesToDelete);
db.accountGroups().deleteKeys(toDelete);
}
private static GroupReference groupReference(String dn)
throws NamingException {
LdapName name = new LdapName(dn);
Preconditions.checkState(!name.isEmpty(), "Invalid LDAP dn: %s", dn);
String cn = name.get(name.size() - 1);
int index = cn.indexOf('=');
if (index >= 0) {
cn = cn.substring(index + 1);
}
return new GroupReference(new AccountGroup.UUID("ldap:" + dn), "ldap/" + cn);
}
}

View File

@ -1,25 +0,0 @@
// Copyright (C) 2012 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.inject.Inject;
import com.google.inject.Provider;
public class Schema_70 extends SchemaVersion {
@Inject
protected Schema_70(Provider<Schema_69> prior) {
super(prior);
}
}

View File

@ -1,38 +0,0 @@
// Copyright (C) 2012 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.reviewdb.server.ReviewDb;
import com.google.inject.Inject;
import com.google.inject.Provider;
import java.sql.SQLException;
import java.sql.Statement;
public class Schema_71 extends SchemaVersion {
@Inject
Schema_71(Provider<Schema_70> prior) {
super(prior);
}
@Override
protected void migrateData(final ReviewDb db, final UpdateUI ui)
throws SQLException {
try (Statement stmt = newStatement(db)) {
stmt.executeUpdate("UPDATE account_diff_preferences SET show_line_endings='Y'");
}
}
}

View File

@ -1,25 +0,0 @@
// Copyright (C) 2012 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.inject.Inject;
import com.google.inject.Provider;
public class Schema_72 extends SchemaVersion {
@Inject
Schema_72(Provider<Schema_71> prior) {
super(prior);
}
}

View File

@ -1,37 +0,0 @@
// Copyright (C) 2012 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.reviewdb.server.ReviewDb;
import com.google.inject.Inject;
import com.google.inject.Provider;
import java.sql.SQLException;
import java.sql.Statement;
public class Schema_73 extends SchemaVersion {
@Inject
Schema_73(Provider<Schema_72> prior) {
super(prior);
}
@Override
protected void migrateData(final ReviewDb db, final UpdateUI ui)
throws SQLException {
try (Statement stmt = newStatement(db)) {
stmt.executeUpdate("CREATE INDEX change_messages_byPatchset ON change_messages (patchset_change_id, patchset_patch_set_id )");
}
}
}

View File

@ -1,107 +0,0 @@
// Copyright (C) 2012 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.reviewdb.client.Account;
import com.google.gerrit.reviewdb.client.AccountGroup;
import com.google.gerrit.reviewdb.client.AccountGroupById;
import com.google.gerrit.reviewdb.client.AccountGroupByIdAud;
import com.google.gerrit.reviewdb.server.ReviewDb;
import com.google.gwtorm.server.OrmException;
import com.google.inject.Inject;
import com.google.inject.Provider;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.Statement;
import java.util.ArrayList;
import java.util.HashMap;
/* Handles copying all entries from AccountGroupIncludes(Audit) to the new tables */
public class Schema_74 extends SchemaVersion {
@Inject
Schema_74(Provider<Schema_73> prior) {
super(prior);
}
@Override
protected void migrateData(final ReviewDb db, final UpdateUI ui)
throws SQLException, OrmException {
// Grab all the groups since we don't have the cache available
HashMap<AccountGroup.Id, AccountGroup.UUID> allGroups = new HashMap<>();
for (AccountGroup ag : db.accountGroups().all()) {
allGroups.put(ag.getId(), ag.getGroupUUID());
}
// Initialize some variables
ArrayList<AccountGroupById> newIncludes = new ArrayList<>();
ArrayList<AccountGroupByIdAud> newIncludeAudits = new ArrayList<>();
// Iterate over all entries in account_group_includes
try (Statement oldGroupIncludesStmt = newStatement(db);
ResultSet oldGroupIncludes = oldGroupIncludesStmt.executeQuery(
"SELECT * FROM account_group_includes")) {
while (oldGroupIncludes.next()) {
AccountGroup.Id oldGroupId =
new AccountGroup.Id(oldGroupIncludes.getInt("group_id"));
AccountGroup.Id oldIncludeId =
new AccountGroup.Id(oldGroupIncludes.getInt("include_id"));
AccountGroup.UUID uuidFromIncludeId = allGroups.get(oldIncludeId);
// If we've got an include, but the group no longer exists, don't bother converting
if (uuidFromIncludeId == null) {
ui.message("Skipping group_id = \"" + oldIncludeId.get() +
"\", not a current group");
continue;
}
// Create the new include entry
AccountGroupById destIncludeEntry = new AccountGroupById(
new AccountGroupById.Key(oldGroupId, uuidFromIncludeId));
// Iterate over all the audits (for this group)
try (PreparedStatement oldAuditsQueryStmt = prepareStatement(db,
"SELECT * FROM account_group_includes_audit WHERE group_id=? AND include_id=?")) {
oldAuditsQueryStmt.setInt(1, oldGroupId.get());
oldAuditsQueryStmt.setInt(2, oldIncludeId.get());
try (ResultSet oldGroupIncludeAudits = oldAuditsQueryStmt.executeQuery()) {
while (oldGroupIncludeAudits.next()) {
Account.Id addedBy = new Account.Id(oldGroupIncludeAudits.getInt("added_by"));
int removedBy = oldGroupIncludeAudits.getInt("removed_by");
// Create the new audit entry
AccountGroupByIdAud destAuditEntry =
new AccountGroupByIdAud(destIncludeEntry, addedBy,
oldGroupIncludeAudits.getTimestamp("added_on"));
// If this was a "removed on" entry, note that
if (removedBy > 0) {
destAuditEntry.removed(new Account.Id(removedBy),
oldGroupIncludeAudits.getTimestamp("removed_on"));
}
newIncludeAudits.add(destAuditEntry);
}
}
newIncludes.add(destIncludeEntry);
}
}
}
// Now insert all of the new entries to the database
db.accountGroupById().insert(newIncludes);
db.accountGroupByIdAud().insert(newIncludeAudits);
}
}

View File

@ -1,25 +0,0 @@
// Copyright (C) 2013 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.inject.Inject;
import com.google.inject.Provider;
public class Schema_75 extends SchemaVersion {
@Inject
Schema_75(Provider<Schema_74> prior) {
super(prior);
}
}

View File

@ -1,25 +0,0 @@
// Copyright (C) 2013 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.inject.Inject;
import com.google.inject.Provider;
public class Schema_76 extends SchemaVersion {
@Inject
Schema_76(Provider<Schema_75> prior) {
super(prior);
}
}

View File

@ -1,241 +0,0 @@
// Copyright (C) 2013 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.common.base.Preconditions.checkArgument;
import com.google.common.collect.Lists;
import com.google.common.collect.Maps;
import com.google.gerrit.common.data.LabelType;
import com.google.gerrit.common.data.LabelTypes;
import com.google.gerrit.common.data.LabelValue;
import com.google.gerrit.reviewdb.client.LabelId;
import com.google.gerrit.reviewdb.server.ReviewDb;
import com.google.gerrit.server.GerritPersonIdent;
import com.google.gerrit.server.config.AllProjectsName;
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.schema.sql.DialectH2;
import com.google.gwtorm.schema.sql.DialectMySQL;
import com.google.gwtorm.schema.sql.DialectPostgreSQL;
import com.google.gwtorm.schema.sql.SqlDialect;
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.errors.RepositoryNotFoundException;
import org.eclipse.jgit.lib.PersonIdent;
import org.eclipse.jgit.lib.Repository;
import java.io.IOException;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.Statement;
import java.util.List;
import java.util.Map;
public class Schema_77 extends SchemaVersion {
private final GitRepositoryManager mgr;
private final AllProjectsName allProjects;
private final PersonIdent serverUser;
@Inject
Schema_77(Provider<Schema_76> prior, AllProjectsName allProjects,
GitRepositoryManager mgr, @GerritPersonIdent PersonIdent serverUser) {
super(prior);
this.allProjects = allProjects;
this.mgr = mgr;
this.serverUser = serverUser;
}
@Override
protected void migrateData(ReviewDb db, UpdateUI ui) throws OrmException {
try {
LegacyLabelTypes labelTypes = getLegacyTypes(db);
SqlDialect dialect = ((JdbcSchema) db).getDialect();
if (dialect instanceof DialectH2) {
alterTable(db, "ALTER TABLE %s ALTER COLUMN %s varchar(255)");
} else if (dialect instanceof DialectPostgreSQL) {
alterTable(db, "ALTER TABLE %s ALTER %s TYPE varchar(255)");
} else if (dialect instanceof DialectMySQL) {
alterTable(db, "ALTER TABLE %s MODIFY %s varchar(255) BINARY");
} else {
alterTable(db, "ALTER TABLE %s MODIFY %s varchar(255)");
}
migratePatchSetApprovals(db, labelTypes);
migrateLabelsToAllProjects(labelTypes);
} catch (RepositoryNotFoundException e) {
throw new OrmException(e);
} catch (SQLException e) {
throw new OrmException(e);
} catch (IOException e) {
throw new OrmException(e);
} catch (ConfigInvalidException e) {
throw new OrmException(e);
}
ui.message(
"Migrated label types from database to All-Projects project.config");
}
private void alterTable(ReviewDb db, String sqlFormat) throws SQLException {
try (Statement stmt = newStatement(db)) {
stmt.executeUpdate(
String.format(sqlFormat, "patch_set_approvals", "category_id"));
}
}
private void migrateLabelsToAllProjects(LegacyLabelTypes labelTypes)
throws RepositoryNotFoundException, IOException, ConfigInvalidException {
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);
Map<String, LabelType> configTypes = config.getLabelSections();
List<LabelType> newTypes = Lists.newArrayList();
for (LegacyLabelType type : labelTypes.getLegacyLabelTypes()) {
if (!configTypes.containsKey(type.getName())) {
newTypes.add(type);
}
}
newTypes.addAll(configTypes.values());
configTypes.clear();
for (LabelType type : newTypes) {
configTypes.put(type.getName(), type);
}
md.setMessage("Upgrade to Gerrit Code Review schema 77\n");
config.commit(md);
} finally {
git.close();
}
}
private void migratePatchSetApprovals(ReviewDb db,
LegacyLabelTypes labelTypes) throws SQLException {
try (PreparedStatement stmt = prepareStatement(db,
"UPDATE patch_set_approvals SET category_id = ?, granted=granted"
+ " WHERE category_id = ?")) {
for (LegacyLabelType type : labelTypes.getLegacyLabelTypes()) {
stmt.setString(1, type.getName());
stmt.setString(2, type.getId());
stmt.addBatch();
}
stmt.executeBatch();
}
}
static class LegacyLabelType extends LabelType {
private String id;
private LegacyLabelType(String name, List<LabelValue> values) {
super(name, values);
}
String getId() {
return id;
}
private void setId(String id) {
checkArgument(id.length() <= 4, "Invalid legacy label ID: \"%s\"", id);
this.id = id;
}
}
static class LegacyLabelTypes extends LabelTypes {
private final List<LegacyLabelType> legacyTypes;
private final Map<String, LegacyLabelType> byId;
private LegacyLabelTypes(List<LegacyLabelType> types) {
super(types);
legacyTypes = types;
byId = Maps.newHashMap();
for (LegacyLabelType type : types) {
byId.put(type.getId(), type);
}
}
List<LegacyLabelType> getLegacyLabelTypes() {
return legacyTypes;
}
@Override
public LegacyLabelType byLabel(LabelId labelId) {
LegacyLabelType t = byId.get(labelId.get());
return t != null ? t : (LegacyLabelType) super.byLabel(labelId);
}
LegacyLabelType byId(LabelId id) {
return byId.get(id.get());
}
}
static LegacyLabelTypes getLegacyTypes(ReviewDb db) throws SQLException {
List<LegacyLabelType> types = Lists.newArrayListWithCapacity(2);
try (Statement catStmt = newStatement(db);
ResultSet catRs = catStmt.executeQuery(
"SELECT category_id, name, function_name, copy_min_score"
+ " FROM approval_categories"
+ " ORDER BY position, name");
PreparedStatement valStmt = prepareStatement(db,
"SELECT value, name"
+ " FROM approval_category_values"
+ " WHERE category_id = ?")) {
while (catRs.next()) {
String id = catRs.getString("category_id");
valStmt.setString(1, id);
List<LabelValue> values = Lists.newArrayListWithCapacity(5);
try (ResultSet valRs = valStmt.executeQuery()) {
while (valRs.next()) {
values.add(new LabelValue(
valRs.getShort("value"), valRs.getString("name")));
}
}
LegacyLabelType type =
new LegacyLabelType(getLabelName(catRs.getString("name")), values);
type.setId(id);
type.setFunctionName(catRs.getString("function_name"));
type.setCopyMinScore("Y".equals(catRs.getString("copy_min_score")));
types.add(type);
}
}
return new LegacyLabelTypes(types);
}
private static String getLabelName(String name) {
StringBuilder r = new StringBuilder();
for (int i = 0; i < name.length(); i++) {
char c = name.charAt(i);
if (('0' <= c && c <= '9') //
|| ('a' <= c && c <= 'z') //
|| ('A' <= c && c <= 'Z') //
|| (c == '-')) {
r.append(c);
} else if (c == ' ') {
r.append('-');
}
}
return r.toString();
}
}

View File

@ -1,26 +0,0 @@
// Copyright (C) 2013 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.inject.Inject;
import com.google.inject.Provider;
public class Schema_78 extends SchemaVersion {
@Inject
Schema_78(Provider<Schema_77> prior) {
super(prior);
}
}

View File

@ -1,26 +0,0 @@
// Copyright (C) 2013 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.inject.Inject;
import com.google.inject.Provider;
public class Schema_79 extends SchemaVersion {
@Inject
Schema_79(Provider<Schema_78> prior) {
super(prior);
}
}

View File

@ -1,26 +0,0 @@
// Copyright (C) 2013 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.inject.Inject;
import com.google.inject.Provider;
public class Schema_80 extends SchemaVersion {
@Inject
Schema_80(Provider<Schema_79> prior) {
super(prior);
}
}

View File

@ -1,152 +0,0 @@
// Copyright (C) 2013 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.Permission;
import com.google.gerrit.reviewdb.server.ReviewDb;
import com.google.gerrit.server.GerritPersonIdent;
import com.google.gerrit.server.config.AllProjectsName;
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.server.OrmException;
import com.google.inject.Inject;
import com.google.inject.Provider;
import org.eclipse.jgit.errors.ConfigInvalidException;
import org.eclipse.jgit.errors.RepositoryNotFoundException;
import org.eclipse.jgit.lib.PersonIdent;
import org.eclipse.jgit.lib.Repository;
import java.io.File;
import java.io.FileFilter;
import java.io.IOException;
import java.sql.SQLException;
public class Schema_81 extends SchemaVersion {
private final File pluginsDir;
private final GitRepositoryManager mgr;
private final AllProjectsName allProjects;
private final PersonIdent serverUser;
@Inject
Schema_81(Provider<Schema_80> prior, SitePaths sitePaths,
AllProjectsName allProjects, GitRepositoryManager mgr,
@GerritPersonIdent PersonIdent serverUser) {
super(prior);
this.pluginsDir = sitePaths.plugins_dir;
this.mgr = mgr;
this.allProjects = allProjects;
this.serverUser = serverUser;
}
@Override
protected void migrateData(ReviewDb db, UpdateUI ui) throws OrmException,
SQLException {
try {
migrateStartReplicationCapability(scanForReplicationPlugin());
} catch (IOException | ConfigInvalidException e) {
throw new OrmException(e);
}
}
private File[] scanForReplicationPlugin() {
File[] matches = null;
if (pluginsDir != null && pluginsDir.exists()) {
matches = pluginsDir.listFiles(new FileFilter() {
@Override
public boolean accept(File pathname) {
String n = pathname.getName();
return (n.endsWith(".jar") || n.endsWith(".jar.disabled"))
&& pathname.isFile() && n.contains("replication");
}
});
}
return matches;
}
private void migrateStartReplicationCapability(File[] matches)
throws RepositoryNotFoundException, IOException, ConfigInvalidException {
Description d = new Description();
if (matches == null || matches.length == 0) {
d.what = Description.Action.REMOVE;
} else {
d.what = Description.Action.RENAME;
d.prefix = nameOf(matches[0]);
}
migrateStartReplicationCapability(d);
}
private void migrateStartReplicationCapability(Description d)
throws RepositoryNotFoundException, IOException,
ConfigInvalidException {
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 capabilities =
config.getAccessSection(AccessSection.GLOBAL_CAPABILITIES);
Permission startReplication =
capabilities.getPermission("startReplication");
if (startReplication == null) {
return;
}
String msg = null;
switch (d.what) {
case REMOVE:
capabilities.remove(startReplication);
msg = "Remove startReplication capability, plugin not installed\n";
break;
case RENAME:
capabilities.remove(startReplication);
Permission pluginStartReplication =
capabilities.getPermission(
String.format("%s-startReplication", d.prefix), true);
pluginStartReplication.setRules(startReplication.getRules());
msg = "Rename startReplication capability to match updated plugin\n";
break;
}
config.replace(capabilities);
md.setMessage(msg);
config.commit(md);
} finally {
git.close();
}
}
private static String nameOf(File jar) {
String name = jar.getName();
if (name.endsWith(".disabled")) {
name = name.substring(0, name.lastIndexOf('.'));
}
int ext = name.lastIndexOf('.');
return 0 < ext ? name.substring(0, ext) : name;
}
private static class Description {
private enum Action {
REMOVE, RENAME
}
Action what;
String prefix;
}
}

View File

@ -1,148 +0,0 @@
// Copyright (C) 2013 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.common.collect.ImmutableMap;
import com.google.gerrit.reviewdb.server.ReviewDb;
import com.google.gwtorm.jdbc.JdbcExecutor;
import com.google.gwtorm.jdbc.JdbcSchema;
import com.google.gwtorm.schema.sql.DialectMySQL;
import com.google.gwtorm.schema.sql.SqlDialect;
import com.google.gwtorm.server.OrmException;
import com.google.gwtorm.server.StatementExecutor;
import com.google.inject.Inject;
import com.google.inject.Provider;
import java.sql.SQLException;
import java.sql.Statement;
import java.util.Map;
import java.util.Set;
public class Schema_82 extends SchemaVersion {
private Map<String,String> tables = ImmutableMap.of(
"account_group_includes_by_uuid", "account_group_by_id",
"account_group_includes_by_uuid_audit", "account_group_by_id_aud");
private Map<String,Index> indexes = ImmutableMap.of(
"account_project_watches_byProject",
new Index("account_project_watches", "account_project_watches_byP"),
"patch_set_approvals_closedByUser",
new Index("patch_set_approvals", "patch_set_approvals_closedByU"),
"submodule_subscription_access_bySubscription",
new Index("submodule_subscriptions", "submodule_subscr_acc_byS")
);
@Inject
Schema_82(Provider<Schema_81> prior) {
super(prior);
}
@Override
protected void preUpdateSchema(ReviewDb db) throws OrmException, SQLException {
JdbcSchema s = (JdbcSchema) db;
try (JdbcExecutor e = new JdbcExecutor(s)) {
renameTables(db, s, e);
renameColumn(db, s, e);
}
renameIndexes(db);
}
private void renameTables(final ReviewDb db, final JdbcSchema s,
final JdbcExecutor e) throws OrmException, SQLException {
SqlDialect dialect = ((JdbcSchema) db).getDialect();
final Set<String> existingTables = dialect.listTables(s.getConnection());
for (Map.Entry<String, String> entry : tables.entrySet()) {
// Does source table exist?
if (existingTables.contains(entry.getKey())) {
// Does target table exist?
if (!existingTables.contains(entry.getValue())) {
s.renameTable(e, entry.getKey(), entry.getValue());
}
}
}
}
private void renameColumn(final ReviewDb db, final JdbcSchema s,
final JdbcExecutor e) throws SQLException, OrmException {
SqlDialect dialect = ((JdbcSchema) db).getDialect();
final Set<String> existingColumns =
dialect.listColumns(s.getConnection(), "accounts");
// Does source column exist?
if (!existingColumns.contains("show_username_in_review_category")) {
return;
}
// Does target column exist?
if (existingColumns.contains("show_user_in_review")) {
return;
}
s.renameColumn(e, "accounts", "show_username_in_review_category",
"show_user_in_review");
// MySQL loose check constraint during the column renaming.
// Well it doesn't implemented anyway,
// check constraints are get parsed but do nothing
if (dialect instanceof DialectMySQL) {
try (Statement stmt = newStatement(db)) {
addCheckConstraint(stmt);
}
}
}
private void renameIndexes(ReviewDb db) {
SqlDialect dialect = ((JdbcSchema) db).getDialect();
// Use a new executor so we can ignore errors.
try (StatementExecutor e = newExecutor(db)) {
// MySQL doesn't have alter index stmt, drop & create
if (dialect instanceof DialectMySQL) {
for (Map.Entry<String, Index> entry : indexes.entrySet()) {
dialect.dropIndex(e, entry.getValue().table, entry.getKey());
}
e.execute("CREATE INDEX account_project_watches_byP ON " +
"account_project_watches (project_name)");
e.execute("CREATE INDEX patch_set_approvals_closedByU ON " +
"patch_set_approvals (change_open, account_id, change_sort_key)");
e.execute("CREATE INDEX submodule_subscr_acc_bys ON " +
"submodule_subscriptions (submodule_project_name, " +
"submodule_branch_name)");
} else {
for (Map.Entry<String, Index> entry : indexes.entrySet()) {
e.execute("ALTER INDEX " + entry.getKey() + " RENAME TO "
+ entry.getValue().index);
}
}
} catch (OrmException e) {
// We don't care; better, we could check if index was already renamed, but
// gwtorm didn't expose this functionality at the time this schema upgrade
// was written.
}
}
private void addCheckConstraint(Statement stmt) throws SQLException {
// add check constraint for the destination column
stmt.executeUpdate("ALTER TABLE accounts ADD CONSTRAINT "
+ "show_user_in_review_check CHECK "
+ "(show_user_in_review IN('Y', 'N'))");
}
static class Index {
String table;
String index;
Index(String tableName, String indexName) {
this.table = tableName;
this.index = indexName;
}
}
}

View File

@ -16,11 +16,17 @@ package com.google.gerrit.server.schema;
import com.google.inject.Inject;
import com.google.inject.Provider;
import com.google.inject.ProvisionException;
public class Schema_83 extends SchemaVersion {
@Inject
Schema_83(Provider<Schema_82> prior) {
super(prior);
Schema_83() {
super(new Provider<SchemaVersion>() {
@Override
public SchemaVersion get() {
throw new ProvisionException("Upgrade first to 2.8 or 2.9");
}
});
}
}