blob: 0377b4b6ff459e311a707ea03e91326c9374f709 [file] [log] [blame]
// 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.googlesource.gerrit.plugins.deleteproject.database;
import com.google.common.collect.Lists;
import com.google.gerrit.reviewdb.client.Change;
import com.google.gerrit.reviewdb.client.PatchSet;
import com.google.gerrit.reviewdb.client.Project;
import com.google.gerrit.reviewdb.server.ReviewDb;
import com.google.gerrit.server.index.ChangeIndexer;
import com.google.gerrit.server.query.change.ChangeData;
import com.google.gerrit.server.query.change.InternalChangeQuery;
import com.google.gwtorm.jdbc.JdbcSchema;
import com.google.gwtorm.server.OrmException;
import com.google.gwtorm.server.ResultSet;
import com.google.inject.Inject;
import com.google.inject.Provider;
import com.googlesource.gerrit.plugins.deleteproject.CannotDeleteProjectException;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import java.io.IOException;
import java.sql.Connection;
import java.sql.SQLException;
import java.util.Collection;
import java.util.Collections;
import java.util.List;
public class DatabaseDeleteHandler {
private static final Logger log =
LoggerFactory.getLogger(DatabaseDeleteHandler.class);
private final ReviewDb db;
private final Provider<InternalChangeQuery> queryProvider;
private final ChangeIndexer indexer;
@Inject
public DatabaseDeleteHandler(ReviewDb db,
Provider<InternalChangeQuery> queryProvider,
ChangeIndexer indexer) {
this.db = db;
this.queryProvider = queryProvider;
this.indexer = indexer;
}
public Collection<String> getWarnings(Project project) throws OrmException {
Collection<String> ret = Lists.newArrayList();
// Warn against open changes
List<ChangeData> openChanges =
queryProvider.get().byProjectOpen(project.getNameKey());
if (openChanges.iterator().hasNext()) {
ret.add(project.getName() + " has open changes");
}
return ret;
}
public void delete(Project project) throws OrmException {
// TODO(davido): Why not to use 1.7 features?
// http://docs.oracle.com/javase/specs/jls/se7/html/jls-14.html#jls-14.20.3.2
Connection conn = ((JdbcSchema) db).getConnection();
try {
conn.setAutoCommit(false);
try {
atomicDelete(project);
conn.commit();
} finally {
conn.setAutoCommit(true);
}
} catch (SQLException e) {
try {
conn.rollback();
} catch (SQLException ex) {
throw new OrmException(ex);
}
throw new OrmException(e);
}
}
private final void deleteChanges(List<ChangeData> changeData)
throws OrmException {
for (ChangeData cd : changeData) {
Change.Id id = cd.getId();
ResultSet<PatchSet> patchSets = null;
patchSets = db.patchSets().byChange(id);
if (patchSets != null) {
deleteFromPatchSets(patchSets);
}
// In the future, use schemaVersion to decide what to delete.
db.patchComments().delete(db.patchComments().byChange(id));
db.patchSetApprovals().delete(db.patchSetApprovals().byChange(id));
db.changeMessages().delete(db.changeMessages().byChange(id));
db.starredChanges().delete(db.starredChanges().byChange(id));
db.changes().delete(Collections.singleton(cd.change()));
// Delete from the secondary index
try {
indexer.delete(id);
} catch (IOException e) {
log.error(
String.format("Failed to delete change %s from index", id), e);
}
}
}
private final void deleteFromPatchSets(final ResultSet<PatchSet> patchSets)
throws OrmException {
for (PatchSet patchSet : patchSets) {
db.accountPatchReviews().delete(
db.accountPatchReviews().byPatchSet(patchSet.getId()));
db.patchSets().delete(Collections.singleton(patchSet));
}
}
public void assertCanDelete(Project project)
throws CannotDeleteProjectException, OrmException {
if (db.submoduleSubscriptions().bySubmoduleProject(project.getNameKey())
.iterator().hasNext()) {
throw new CannotDeleteProjectException(
"Project is subscribed by other projects.");
}
}
public void atomicDelete(Project project) throws OrmException {
List<ChangeData> changes =
queryProvider.get().byProject(project.getNameKey());
deleteChanges(changes);
db.accountProjectWatches().delete(
db.accountProjectWatches().byProject(project.getNameKey()));
db.submoduleSubscriptions().delete(
db.submoduleSubscriptions().bySuperProjectProject(
project.getNameKey()));
}
}