Merge changes from topic 'init-sequences'

* changes:
  AllProjectsCreator: Support customizing first change ID
  AllProjectsCreator: Seed refs/sequences/changes if applicable
This commit is contained in:
David Pursehouse 2017-03-18 01:16:00 +00:00 committed by Gerrit Code Review
commit 0129f08967
4 changed files with 72 additions and 4 deletions

View File

@ -35,6 +35,8 @@ import org.eclipse.jgit.lib.Config;
@SuppressWarnings("deprecation")
@Singleton
public class Sequences {
public static final String CHANGES = "changes";
private final Provider<ReviewDb> db;
private final NotesMigration migration;
private final RepoSequence changeSeq;
@ -54,7 +56,7 @@ public class Sequences {
new RepoSequence(
repoManager,
allProjects,
"changes",
CHANGES,
new RepoSequence.Seed() {
@Override
public int get() throws OrmException {

View File

@ -16,6 +16,8 @@ package com.google.gerrit.server.notedb;
import static com.google.common.base.Preconditions.checkArgument;
import static com.google.common.base.Preconditions.checkNotNull;
import static com.google.gerrit.reviewdb.client.RefNames.REFS;
import static com.google.gerrit.reviewdb.client.RefNames.REFS_SEQUENCES;
import static java.nio.charset.StandardCharsets.UTF_8;
import static org.eclipse.jgit.lib.Constants.OBJ_BLOB;
@ -52,6 +54,7 @@ import org.eclipse.jgit.lib.Ref;
import org.eclipse.jgit.lib.RefUpdate;
import org.eclipse.jgit.lib.Repository;
import org.eclipse.jgit.revwalk.RevWalk;
import org.eclipse.jgit.transport.ReceiveCommand;
/**
* Class for managing an incrementing sequence backed by a git repository.
@ -117,7 +120,15 @@ public class RepoSequence {
Retryer<RefUpdate.Result> retryer) {
this.repoManager = checkNotNull(repoManager, "repoManager");
this.projectName = checkNotNull(projectName, "projectName");
this.refName = RefNames.REFS_SEQUENCES + checkNotNull(name, "name");
checkArgument(
name != null
&& !name.startsWith(REFS)
&& !name.startsWith(REFS_SEQUENCES.substring(REFS.length())),
"name should be a suffix to follow \"refs/sequences/\", got: %s",
name);
this.refName = RefNames.REFS_SEQUENCES + name;
this.seed = checkNotNull(seed, "seed");
checkArgument(batchSize > 0, "expected batchSize > 0, got: %s", batchSize);
@ -265,4 +276,10 @@ public class RepoSequence {
ru.setForceUpdate(true); // Required for non-commitish updates.
return ru.update(rw);
}
public static ReceiveCommand storeNew(ObjectInserter ins, String name, int val)
throws IOException {
ObjectId newId = ins.insert(OBJ_BLOB, Integer.toString(val).getBytes(UTF_8));
return new ReceiveCommand(ObjectId.zeroId(), newId, RefNames.REFS_SEQUENCES + name);
}
}

View File

@ -14,6 +14,8 @@
package com.google.gerrit.server.schema;
import static com.google.common.base.Preconditions.checkArgument;
import static com.google.gerrit.reviewdb.client.RefNames.REFS_SEQUENCES;
import static com.google.gerrit.server.group.SystemGroupBackend.ANONYMOUS_USERS;
import static com.google.gerrit.server.group.SystemGroupBackend.PROJECT_OWNERS;
import static com.google.gerrit.server.group.SystemGroupBackend.REGISTERED_USERS;
@ -35,28 +37,39 @@ import com.google.gerrit.common.data.PermissionRule.Action;
import com.google.gerrit.extensions.client.InheritableBoolean;
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.GerritPersonIdent;
import com.google.gerrit.server.Sequences;
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.gerrit.server.group.SystemGroupBackend;
import com.google.gerrit.server.notedb.NotesMigration;
import com.google.gerrit.server.notedb.RepoSequence;
import com.google.inject.Inject;
import java.io.IOException;
import org.eclipse.jgit.errors.ConfigInvalidException;
import org.eclipse.jgit.errors.RepositoryNotFoundException;
import org.eclipse.jgit.lib.BatchRefUpdate;
import org.eclipse.jgit.lib.Constants;
import org.eclipse.jgit.lib.NullProgressMonitor;
import org.eclipse.jgit.lib.ObjectInserter;
import org.eclipse.jgit.lib.PersonIdent;
import org.eclipse.jgit.lib.RefUpdate;
import org.eclipse.jgit.lib.Repository;
import org.eclipse.jgit.revwalk.RevWalk;
import org.eclipse.jgit.transport.ReceiveCommand;
/** Creates the {@code All-Projects} repository and initial ACLs. */
public class AllProjectsCreator {
private final GitRepositoryManager mgr;
private final AllProjectsName allProjectsName;
private final PersonIdent serverUser;
private final NotesMigration notesMigration;
private String message;
private int firstChangeId = ReviewDb.FIRST_CHANGE_ID;
private GroupReference admin;
private GroupReference batch;
@ -69,10 +82,12 @@ public class AllProjectsCreator {
GitRepositoryManager mgr,
AllProjectsName allProjectsName,
SystemGroupBackend systemGroupBackend,
@GerritPersonIdent PersonIdent serverUser) {
@GerritPersonIdent PersonIdent serverUser,
NotesMigration notesMigration) {
this.mgr = mgr;
this.allProjectsName = allProjectsName;
this.serverUser = serverUser;
this.notesMigration = notesMigration;
this.anonymous = systemGroupBackend.getGroup(ANONYMOUS_USERS);
this.registered = systemGroupBackend.getGroup(REGISTERED_USERS);
@ -94,6 +109,12 @@ public class AllProjectsCreator {
return this;
}
public AllProjectsCreator setFirstChangeIdForNoteDb(int id) {
checkArgument(id > 0, "id must be positive: %s", id);
firstChangeId = id;
return this;
}
public void create() throws IOException, ConfigInvalidException {
try (Repository git = mgr.openRepository(allProjectsName)) {
initAllProjects(git);
@ -112,8 +133,9 @@ public class AllProjectsCreator {
}
private void initAllProjects(Repository git) throws IOException, ConfigInvalidException {
BatchRefUpdate bru = git.getRefDatabase().newBatchUpdate();
try (MetaDataUpdate md =
new MetaDataUpdate(GitReferenceUpdated.DISABLED, allProjectsName, git)) {
new MetaDataUpdate(GitReferenceUpdated.DISABLED, allProjectsName, git, bru)) {
md.getCommitBuilder().setAuthor(serverUser);
md.getCommitBuilder().setCommitter(serverUser);
md.setMessage(
@ -177,6 +199,8 @@ public class AllProjectsCreator {
grant(config, meta, Permission.SUBMIT, admin, owners);
config.commitToNewRef(md, RefNames.REFS_CONFIG);
initSequences(git, bru);
execute(git, bru);
}
}
@ -195,4 +219,27 @@ public class AllProjectsCreator {
c.getLabelSections().put(type.getName(), type);
return type;
}
private void initSequences(Repository git, BatchRefUpdate bru) throws IOException {
if (notesMigration.readChangeSequence()
&& git.exactRef(REFS_SEQUENCES + Sequences.CHANGES) == null) {
// Can't easily reuse the inserter from MetaDataUpdate, but this shouldn't slow down site
// initialization unduly.
try (ObjectInserter ins = git.newObjectInserter()) {
bru.addCommand(RepoSequence.storeNew(ins, Sequences.CHANGES, firstChangeId));
ins.flush();
}
}
}
private void execute(Repository git, BatchRefUpdate bru) throws IOException {
try (RevWalk rw = new RevWalk(git)) {
bru.execute(rw, NullProgressMonitor.INSTANCE);
}
for (ReceiveCommand cmd : bru.getCommands()) {
if (cmd.getResult() != ReceiveCommand.Result.OK) {
throw new IOException("Failed to initialize " + allProjectsName + " refs:\n" + bru);
}
}
}
}

View File

@ -30,6 +30,7 @@ import com.google.gerrit.server.config.GerritServerConfig;
import com.google.gerrit.server.config.SitePaths;
import com.google.gerrit.server.git.GitRepositoryManager;
import com.google.gerrit.server.group.SystemGroupBackend;
import com.google.gerrit.server.notedb.ConfigNotesMigration;
import com.google.gerrit.testutil.InMemoryDatabase;
import com.google.gerrit.testutil.InMemoryH2Type;
import com.google.gerrit.testutil.InMemoryRepositoryManager;
@ -108,6 +109,7 @@ public class SchemaUpdaterTest {
bind(DataSourceType.class).to(InMemoryH2Type.class);
bind(SystemGroupBackend.class);
install(new ConfigNotesMigration.Module());
}
})
.getInstance(SchemaUpdater.class);