Add schema migration to delete user branches for which no account exists
Before change I4fde3560c we didn't delete the user branch when an account was deleted. This means we may have collected some orphaned user branches and the schema migration cleans them up. After change I4fde3560c we should not get any new orphaned user branches, so this is a one time cleanup. Change-Id: I1d592ba7a724da8b910888832dbbe9059b2a788c Signed-off-by: Edwin Kempin <ekempin@google.com>
This commit is contained in:
@@ -225,22 +225,27 @@ public class AccountsUpdate {
|
||||
|
||||
private void deleteUserBranch(Account.Id accountId) throws IOException {
|
||||
try (Repository repo = repoManager.openRepository(allUsersName)) {
|
||||
String refName = RefNames.refsUsers(accountId);
|
||||
Ref ref = repo.exactRef(refName);
|
||||
if (ref == null) {
|
||||
return;
|
||||
}
|
||||
deleteUserBranch(repo, committerIdent, accountId);
|
||||
}
|
||||
}
|
||||
|
||||
RefUpdate ru = repo.updateRef(refName);
|
||||
ru.setExpectedOldObjectId(ref.getObjectId());
|
||||
ru.setNewObjectId(ObjectId.zeroId());
|
||||
ru.setForceUpdate(true);
|
||||
ru.setRefLogIdent(committerIdent);
|
||||
ru.setRefLogMessage("Delete Account", true);
|
||||
Result result = ru.delete();
|
||||
if (result != Result.FORCED) {
|
||||
throw new IOException(String.format("Failed to delete ref %s: %s", refName, result.name()));
|
||||
}
|
||||
public static void deleteUserBranch(
|
||||
Repository repo, PersonIdent refLogIdent, Account.Id accountId) throws IOException {
|
||||
String refName = RefNames.refsUsers(accountId);
|
||||
Ref ref = repo.exactRef(refName);
|
||||
if (ref == null) {
|
||||
return;
|
||||
}
|
||||
|
||||
RefUpdate ru = repo.updateRef(refName);
|
||||
ru.setExpectedOldObjectId(ref.getObjectId());
|
||||
ru.setNewObjectId(ObjectId.zeroId());
|
||||
ru.setForceUpdate(true);
|
||||
ru.setRefLogIdent(refLogIdent);
|
||||
ru.setRefLogMessage("Delete Account", true);
|
||||
Result result = ru.delete();
|
||||
if (result != Result.FORCED) {
|
||||
throw new IOException(String.format("Failed to delete ref %s: %s", refName, result.name()));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -35,7 +35,7 @@ import java.util.concurrent.TimeUnit;
|
||||
/** A version of the database schema. */
|
||||
public abstract class SchemaVersion {
|
||||
/** The current schema version. */
|
||||
public static final Class<Schema_146> C = Schema_146.class;
|
||||
public static final Class<Schema_147> C = Schema_147.class;
|
||||
|
||||
public static int getBinaryVersion() {
|
||||
return guessVersion(C);
|
||||
|
||||
@@ -0,0 +1,75 @@
|
||||
// Copyright (C) 2017 The Android Open Source Project
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
package com.google.gerrit.server.schema;
|
||||
|
||||
import static java.util.stream.Collectors.toSet;
|
||||
|
||||
import com.google.gerrit.reviewdb.client.Account;
|
||||
import com.google.gerrit.reviewdb.client.RefNames;
|
||||
import com.google.gerrit.reviewdb.server.ReviewDb;
|
||||
import com.google.gerrit.server.GerritPersonIdent;
|
||||
import com.google.gerrit.server.account.AccountsUpdate;
|
||||
import com.google.gerrit.server.config.AllUsersName;
|
||||
import com.google.gerrit.server.git.GitRepositoryManager;
|
||||
import com.google.gwtorm.server.OrmException;
|
||||
import com.google.inject.Inject;
|
||||
import com.google.inject.Provider;
|
||||
import java.io.IOException;
|
||||
import java.sql.SQLException;
|
||||
import java.util.Objects;
|
||||
import java.util.Set;
|
||||
import org.eclipse.jgit.lib.PersonIdent;
|
||||
import org.eclipse.jgit.lib.Repository;
|
||||
|
||||
/** Delete user branches for which no account exists. */
|
||||
public class Schema_147 extends SchemaVersion {
|
||||
private final GitRepositoryManager repoManager;
|
||||
private final AllUsersName allUsersName;
|
||||
private final PersonIdent serverIdent;
|
||||
|
||||
@Inject
|
||||
Schema_147(
|
||||
Provider<Schema_146> prior,
|
||||
GitRepositoryManager repoManager,
|
||||
AllUsersName allUsersName,
|
||||
@GerritPersonIdent PersonIdent serverIdent) {
|
||||
super(prior);
|
||||
this.repoManager = repoManager;
|
||||
this.allUsersName = allUsersName;
|
||||
this.serverIdent = serverIdent;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void migrateData(ReviewDb db, UpdateUI ui) throws OrmException, SQLException {
|
||||
try (Repository repo = repoManager.openRepository(allUsersName)) {
|
||||
Set<Account.Id> accountIdsFromReviewDb =
|
||||
db.accounts().all().toList().stream().map(a -> a.getId()).collect(toSet());
|
||||
Set<Account.Id> accountIdsFromUserBranches =
|
||||
repo.getRefDatabase()
|
||||
.getRefs(RefNames.REFS_USERS)
|
||||
.values()
|
||||
.stream()
|
||||
.map(r -> Account.Id.fromRef(r.getName()))
|
||||
.filter(Objects::nonNull)
|
||||
.collect(toSet());
|
||||
accountIdsFromUserBranches.removeAll(accountIdsFromReviewDb);
|
||||
for (Account.Id accountId : accountIdsFromUserBranches) {
|
||||
AccountsUpdate.deleteUserBranch(repo, serverIdent, accountId);
|
||||
}
|
||||
} catch (IOException e) {
|
||||
throw new OrmException("Failed to delete user branches for non-existing accounts.", e);
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user