Merge changes from topic 'load-changes-via-change-notes-factory'

* changes:
  ScanningChangeCacheImpl: Load changes from notedb if enabled
  ChangeControl.GenericFactory#validateFor: Don't load change from db
  ChangeControl.GenericFactory: Use ChangeNotes.Factory to load change
  Pass project to ChangeData so that it can load the change from notes
  Store project field in change index
  ChangesCollection: Lookup change in index when legacy ID is given
  Always load change notes when they are created
  Load change via notes factory in ConsistencyChecker#checkExpectMergedAs()
  PostReview#forceCallerAsReviewer should set reviewer in notedb
  Use ChangeNotes in more places to load the change
  Load change in ChangeNotes.Factory
  Fix parsing of current patch set from notes branch
  Remove unused method in ChangeDataResultSet
  ChangeJson: Remove unused format(Collection<Change.Id>) method
This commit is contained in:
Dave Borowitz
2016-02-05 17:38:59 +00:00
committed by Gerrit Code Review
76 changed files with 553 additions and 323 deletions

View File

@@ -57,6 +57,7 @@ import com.google.gerrit.server.git.GitRepositoryManager;
import com.google.gerrit.server.git.MetaDataUpdate; import com.google.gerrit.server.git.MetaDataUpdate;
import com.google.gerrit.server.git.ProjectConfig; import com.google.gerrit.server.git.ProjectConfig;
import com.google.gerrit.server.index.ChangeIndexer; import com.google.gerrit.server.index.ChangeIndexer;
import com.google.gerrit.server.notedb.ChangeNotes;
import com.google.gerrit.server.notedb.NotesMigration; import com.google.gerrit.server.notedb.NotesMigration;
import com.google.gerrit.server.project.ProjectCache; import com.google.gerrit.server.project.ProjectCache;
import com.google.gerrit.server.project.Util; import com.google.gerrit.server.project.Util;
@@ -187,6 +188,9 @@ public abstract class AbstractDaemonTest {
@Inject @Inject
protected NotesMigration notesMigration; protected NotesMigration notesMigration;
@Inject
protected ChangeNotes.Factory notesFactory;
@Rule @Rule
public ExpectedException exception = ExpectedException.none(); public ExpectedException exception = ExpectedException.none();
@@ -636,7 +640,8 @@ public abstract class AbstractDaemonTest {
} }
protected PatchSet getPatchSet(PatchSet.Id psId) throws OrmException { protected PatchSet getPatchSet(PatchSet.Id psId) throws OrmException {
return changeDataFactory.create(db, psId.getParentKey()).patchSet(psId); return changeDataFactory.create(db, project, psId.getParentKey())
.patchSet(psId);
} }
protected IdentifiedUser user(TestAccount testAccount) { protected IdentifiedUser user(TestAccount testAccount) {

View File

@@ -273,8 +273,9 @@ public class PushOneCommit {
private void assertReviewers(Change c, TestAccount... expectedReviewers) private void assertReviewers(Change c, TestAccount... expectedReviewers)
throws OrmException { throws OrmException {
Iterable<Account.Id> actualIds = Iterable<Account.Id> actualIds = approvalsUtil
approvalsUtil.getReviewers(db, notesFactory.create(db, c)).values(); .getReviewers(db, notesFactory.create(db, c.getProject(), c.getId()))
.values();
assertThat(actualIds).containsExactlyElementsIn( assertThat(actualIds).containsExactlyElementsIn(
Sets.newHashSet(TestAccount.ids(expectedReviewers))); Sets.newHashSet(TestAccount.ids(expectedReviewers)));
} }

View File

@@ -52,7 +52,7 @@ import com.google.gerrit.extensions.restapi.IdString;
import com.google.gerrit.extensions.restapi.ResourceConflictException; import com.google.gerrit.extensions.restapi.ResourceConflictException;
import com.google.gerrit.reviewdb.client.Patch; import com.google.gerrit.reviewdb.client.Patch;
import com.google.gerrit.reviewdb.client.PatchSet; import com.google.gerrit.reviewdb.client.PatchSet;
import com.google.gerrit.server.ChangeUtil; import com.google.gerrit.server.ChangeFinder;
import com.google.gerrit.server.change.ChangeResource; import com.google.gerrit.server.change.ChangeResource;
import com.google.gerrit.server.change.GetRevisionActions; import com.google.gerrit.server.change.GetRevisionActions;
import com.google.gerrit.server.change.RevisionResource; import com.google.gerrit.server.change.RevisionResource;
@@ -80,7 +80,7 @@ import java.util.Map;
public class RevisionIT extends AbstractDaemonTest { public class RevisionIT extends AbstractDaemonTest {
@Inject @Inject
private ChangeUtil changeUtil; private ChangeFinder changeFinder;
@Inject @Inject
private GetRevisionActions getRevisionActions; private GetRevisionActions getRevisionActions;
@@ -693,7 +693,7 @@ public class RevisionIT extends AbstractDaemonTest {
private RevisionResource parseRevisionResource(PushOneCommit.Result r) private RevisionResource parseRevisionResource(PushOneCommit.Result r)
throws Exception { throws Exception {
PatchSet.Id psId = r.getPatchSetId(); PatchSet.Id psId = r.getPatchSetId();
List<ChangeControl> ctls = changeUtil.findChanges( List<ChangeControl> ctls = changeFinder.find(
Integer.toString(psId.getParentKey().get()), atrScope.get().getUser()); Integer.toString(psId.getParentKey().get()), atrScope.get().getUser());
assertThat(ctls).hasSize(1); assertThat(ctls).hasSize(1);
return revisions.parse( return revisions.parse(

View File

@@ -50,9 +50,6 @@ public class SubmitOnPushIT extends AbstractDaemonTest {
@Inject @Inject
private ApprovalsUtil approvalsUtil; private ApprovalsUtil approvalsUtil;
@Inject
private ChangeNotes.Factory changeNotesFactory;
@Test @Test
public void submitOnPush() throws Exception { public void submitOnPush() throws Exception {
grant(Permission.SUBMIT, project, "refs/for/refs/heads/master"); grant(Permission.SUBMIT, project, "refs/for/refs/heads/master");
@@ -223,8 +220,8 @@ public class SubmitOnPushIT extends AbstractDaemonTest {
private PatchSetApproval getSubmitter(PatchSet.Id patchSetId) private PatchSetApproval getSubmitter(PatchSet.Id patchSetId)
throws OrmException { throws OrmException {
Change c = db.changes().get(patchSetId.getParentKey()); ChangeNotes notes =
ChangeNotes notes = changeNotesFactory.create(db, c).load(); notesFactory.create(db, project, patchSetId.getParentKey()).load();
return approvalsUtil.getSubmitter(db, notes, patchSetId); return approvalsUtil.getSubmitter(db, notes, patchSetId);
} }

View File

@@ -34,6 +34,7 @@ import com.google.gerrit.reviewdb.client.PatchSet;
import com.google.gerrit.reviewdb.client.RefNames; import com.google.gerrit.reviewdb.client.RefNames;
import com.google.gerrit.server.edit.ChangeEditModifier; import com.google.gerrit.server.edit.ChangeEditModifier;
import com.google.gerrit.server.git.ProjectConfig; import com.google.gerrit.server.git.ProjectConfig;
import com.google.gerrit.server.notedb.ChangeNotes;
import com.google.gerrit.server.project.Util; import com.google.gerrit.server.project.Util;
import com.google.inject.Inject; import com.google.inject.Inject;
@@ -186,16 +187,16 @@ public class VisibleRefFilterIT extends AbstractDaemonTest {
allow(Permission.READ, REGISTERED_USERS, "refs/heads/master"); allow(Permission.READ, REGISTERED_USERS, "refs/heads/master");
deny(Permission.READ, REGISTERED_USERS, "refs/heads/branch"); deny(Permission.READ, REGISTERED_USERS, "refs/heads/branch");
Change change1 = db.changes().get(c1); ChangeNotes notes = notesFactory.create(db, project, c1);
PatchSet ps1 = getPatchSet(new PatchSet.Id(c1, 1)); PatchSet ps1 = getPatchSet(new PatchSet.Id(c1, 1));
// Admin's edit is not visible. // Admin's edit is not visible.
setApiUser(admin); setApiUser(admin);
editModifier.createEdit(change1, ps1); editModifier.createEdit(notes.getChange(), ps1);
// User's edit is visible. // User's edit is visible.
setApiUser(user); setApiUser(user);
editModifier.createEdit(change1, ps1); editModifier.createEdit(notes.getChange(), ps1);
assertRefs( assertRefs(
"HEAD", "HEAD",
@@ -213,12 +214,12 @@ public class VisibleRefFilterIT extends AbstractDaemonTest {
deny(Permission.READ, REGISTERED_USERS, "refs/heads/master"); deny(Permission.READ, REGISTERED_USERS, "refs/heads/master");
allow(Permission.READ, REGISTERED_USERS, "refs/heads/branch"); allow(Permission.READ, REGISTERED_USERS, "refs/heads/branch");
Change change1 = db.changes().get(c1); ChangeNotes notes = notesFactory.create(db, project, c1);
PatchSet ps1 = getPatchSet(new PatchSet.Id(c1, 1)); PatchSet ps1 = getPatchSet(new PatchSet.Id(c1, 1));
setApiUser(admin); setApiUser(admin);
editModifier.createEdit(change1, ps1); editModifier.createEdit(notes.getChange(), ps1);
setApiUser(user); setApiUser(user);
editModifier.createEdit(change1, ps1); editModifier.createEdit(notes.getChange(), ps1);
assertRefs( assertRefs(
// Change 1 is visible due to accessDatabase capability, even though // Change 1 is visible due to accessDatabase capability, even though

View File

@@ -313,8 +313,9 @@ public abstract class AbstractSubmit extends AbstractDaemonTest {
protected void assertSubmitter(String changeId, int psId) protected void assertSubmitter(String changeId, int psId)
throws OrmException { throws OrmException {
ChangeNotes cn = notesFactory.create(db, Change c =
getOnlyElement(queryProvider.get().byKeyPrefix(changeId)).change()); getOnlyElement(queryProvider.get().byKeyPrefix(changeId)).change();
ChangeNotes cn = notesFactory.create(db, c.getProject(), c.getId());
PatchSetApproval submitter = approvalsUtil.getSubmitter( PatchSetApproval submitter = approvalsUtil.getSubmitter(
db, cn, new PatchSet.Id(cn.getChangeId(), psId)); db, cn, new PatchSet.Id(cn.getChangeId(), psId));
assertThat(submitter).isNotNull(); assertThat(submitter).isNotNull();
@@ -324,8 +325,9 @@ public abstract class AbstractSubmit extends AbstractDaemonTest {
protected void assertNoSubmitter(String changeId, int psId) protected void assertNoSubmitter(String changeId, int psId)
throws OrmException { throws OrmException {
ChangeNotes cn = notesFactory.create(db, Change c =
getOnlyElement(queryProvider.get().byKeyPrefix(changeId)).change()); getOnlyElement(queryProvider.get().byKeyPrefix(changeId)).change();
ChangeNotes cn = notesFactory.create(db, c.getProject(), c.getId());
PatchSetApproval submitter = approvalsUtil.getSubmitter( PatchSetApproval submitter = approvalsUtil.getSubmitter(
db, cn, new PatchSet.Id(cn.getChangeId(), psId)); db, cn, new PatchSet.Id(cn.getChangeId(), psId));
assertThat(submitter).isNull(); assertThat(submitter).isNull();

View File

@@ -223,7 +223,7 @@ public class ConsistencyCheckerIT extends AbstractDaemonTest {
assertThat(p.status).isEqualTo(ProblemInfo.Status.FIXED); assertThat(p.status).isEqualTo(ProblemInfo.Status.FIXED);
assertThat(p.outcome).isEqualTo("Deleted patch set"); assertThat(p.outcome).isEqualTo("Deleted patch set");
c = db.changes().get(c.getId()); c = notesFactory.create(db, project, c.getId()).getChange();
assertThat(c.currentPatchSetId().get()).isEqualTo(1); assertThat(c.currentPatchSetId().get()).isEqualTo(1);
assertThat(getPatchSet(ps1.getId())).isNotNull(); assertThat(getPatchSet(ps1.getId())).isNotNull();
assertThat(getPatchSet(ps2.getId())).isNull(); assertThat(getPatchSet(ps2.getId())).isNull();
@@ -271,7 +271,7 @@ public class ConsistencyCheckerIT extends AbstractDaemonTest {
assertThat(p.status).isEqualTo(ProblemInfo.Status.FIXED); assertThat(p.status).isEqualTo(ProblemInfo.Status.FIXED);
assertThat(p.outcome).isEqualTo("Deleted patch set"); assertThat(p.outcome).isEqualTo("Deleted patch set");
c = db.changes().get(c.getId()); c = notesFactory.create(db, project, c.getId()).getChange();
assertThat(c.currentPatchSetId().get()).isEqualTo(3); assertThat(c.currentPatchSetId().get()).isEqualTo(3);
assertThat(getPatchSet(ps1.getId())).isNotNull(); assertThat(getPatchSet(ps1.getId())).isNotNull();
assertThat(getPatchSet(ps2.getId())).isNull(); assertThat(getPatchSet(ps2.getId())).isNull();
@@ -299,7 +299,7 @@ public class ConsistencyCheckerIT extends AbstractDaemonTest {
assertThat(p.outcome) assertThat(p.outcome)
.isEqualTo("Cannot delete patch set; no patch sets would remain"); .isEqualTo("Cannot delete patch set; no patch sets would remain");
c = db.changes().get(c.getId()); c = notesFactory.create(db, project, c.getId()).getChange();
assertThat(c.currentPatchSetId().get()).isEqualTo(1); assertThat(c.currentPatchSetId().get()).isEqualTo(1);
assertThat(getPatchSet(ps1.getId())).isNotNull(); assertThat(getPatchSet(ps1.getId())).isNotNull();
} }
@@ -387,7 +387,7 @@ public class ConsistencyCheckerIT extends AbstractDaemonTest {
assertThat(p.status).isEqualTo(ProblemInfo.Status.FIXED); assertThat(p.status).isEqualTo(ProblemInfo.Status.FIXED);
assertThat(p.outcome).isEqualTo("Marked change as merged"); assertThat(p.outcome).isEqualTo("Marked change as merged");
c = db.changes().get(c.getId()); c = notesFactory.create(db, project, c.getId()).getChange();
assertThat(c.getStatus()).isEqualTo(Change.Status.MERGED); assertThat(c.getStatus()).isEqualTo(Change.Status.MERGED);
assertProblems(c); assertProblems(c);
} }
@@ -476,7 +476,7 @@ public class ConsistencyCheckerIT extends AbstractDaemonTest {
assertThat(p.status).isEqualTo(ProblemInfo.Status.FIXED); assertThat(p.status).isEqualTo(ProblemInfo.Status.FIXED);
assertThat(p.outcome).isEqualTo("Inserted as patch set 2"); assertThat(p.outcome).isEqualTo("Inserted as patch set 2");
c = db.changes().get(c.getId()); c = notesFactory.create(db, project, c.getId()).getChange();
PatchSet.Id psId2 = new PatchSet.Id(c.getId(), 2); PatchSet.Id psId2 = new PatchSet.Id(c.getId(), 2);
assertThat(c.currentPatchSetId()).isEqualTo(psId2); assertThat(c.currentPatchSetId()).isEqualTo(psId2);
assertThat(getPatchSet(psId2).getRevision().get()) assertThat(getPatchSet(psId2).getRevision().get())
@@ -518,7 +518,7 @@ public class ConsistencyCheckerIT extends AbstractDaemonTest {
assertThat(p.status).isEqualTo(ProblemInfo.Status.FIXED); assertThat(p.status).isEqualTo(ProblemInfo.Status.FIXED);
assertThat(p.outcome).isEqualTo("Inserted as patch set 2"); assertThat(p.outcome).isEqualTo("Inserted as patch set 2");
c = db.changes().get(c.getId()); c = notesFactory.create(db, project, c.getId()).getChange();
PatchSet.Id psId2 = new PatchSet.Id(c.getId(), 2); PatchSet.Id psId2 = new PatchSet.Id(c.getId(), 2);
assertThat(c.currentPatchSetId()).isEqualTo(psId2); assertThat(c.currentPatchSetId()).isEqualTo(psId2);
assertThat(getPatchSet(psId2).getRevision().get()) assertThat(getPatchSet(psId2).getRevision().get())
@@ -607,6 +607,7 @@ public class ConsistencyCheckerIT extends AbstractDaemonTest {
private Change insertChange() throws Exception { private Change insertChange() throws Exception {
Change c = newChange(project, adminId); Change c = newChange(project, adminId);
db.changes().insert(singleton(c)); db.changes().insert(singleton(c));
indexer.index(db, c);
ChangeUpdate u = changeUpdateFactory.create( ChangeUpdate u = changeUpdateFactory.create(
changeControlFactory.controlFor(c, userFactory.create(adminId))); changeControlFactory.controlFor(c, userFactory.create(adminId)));

View File

@@ -16,6 +16,7 @@ package com.google.gerrit.acceptance.server.change;
import static com.google.common.truth.Truth.assertThat; import static com.google.common.truth.Truth.assertThat;
import static com.google.gerrit.acceptance.GitUtil.pushHead; import static com.google.gerrit.acceptance.GitUtil.pushHead;
import static java.util.concurrent.TimeUnit.SECONDS;
import com.google.common.collect.ImmutableList; import com.google.common.collect.ImmutableList;
import com.google.common.collect.Iterables; import com.google.common.collect.Iterables;
@@ -33,17 +34,34 @@ import com.google.gerrit.server.edit.ChangeEditUtil;
import com.google.gerrit.server.git.BatchUpdate; import com.google.gerrit.server.git.BatchUpdate;
import com.google.gerrit.server.git.BatchUpdate.ChangeContext; import com.google.gerrit.server.git.BatchUpdate.ChangeContext;
import com.google.gerrit.server.query.change.ChangeData; import com.google.gerrit.server.query.change.ChangeData;
import com.google.gerrit.testutil.TestTimeUtil;
import com.google.gwtorm.server.OrmException; import com.google.gwtorm.server.OrmException;
import com.google.inject.Inject; import com.google.inject.Inject;
import org.eclipse.jgit.lib.ObjectId; import org.eclipse.jgit.lib.ObjectId;
import org.eclipse.jgit.revwalk.RevCommit; import org.eclipse.jgit.revwalk.RevCommit;
import org.junit.After;
import org.junit.Before;
import org.junit.Test; import org.junit.Test;
import java.io.IOException; import java.io.IOException;
import java.util.List; import java.util.List;
public class GetRelatedIT extends AbstractDaemonTest { public class GetRelatedIT extends AbstractDaemonTest {
private String systemTimeZone;
@Before
public void setTimeForTesting() {
systemTimeZone = System.setProperty("user.timezone", "US/Eastern");
TestTimeUtil.resetWithClockStep(1, SECONDS);
}
@After
public void resetTime() {
TestTimeUtil.useSystemTime();
System.setProperty("user.timezone", systemTimeZone);
}
@Inject @Inject
private ChangeEditUtil editUtil; private ChangeEditUtil editUtil;
@@ -573,7 +591,8 @@ public class GetRelatedIT extends AbstractDaemonTest {
// Pretend PS1,1 was pushed before the groups field was added. // Pretend PS1,1 was pushed before the groups field was added.
clearGroups(psId1_1); clearGroups(psId1_1);
indexer.index(changeDataFactory.create(db, psId1_1.getParentKey())); indexer.index(
changeDataFactory.create(db, project, psId1_1.getParentKey()));
// PS1,1 has no groups, so disappeared from related changes. // PS1,1 has no groups, so disappeared from related changes.
assertRelated(psId2_1); assertRelated(psId2_1);

View File

@@ -18,7 +18,6 @@ import static com.google.common.truth.Truth.assertThat;
import static com.google.gerrit.server.group.SystemGroupBackend.ANONYMOUS_USERS; import static com.google.gerrit.server.group.SystemGroupBackend.ANONYMOUS_USERS;
import static com.google.gerrit.server.project.Util.category; import static com.google.gerrit.server.project.Util.category;
import static com.google.gerrit.server.project.Util.value; import static com.google.gerrit.server.project.Util.value;
import static com.google.gerrit.testutil.GerritServerTests.isNoteDbTestEnabled;
import com.google.gerrit.acceptance.AbstractDaemonTest; import com.google.gerrit.acceptance.AbstractDaemonTest;
import com.google.gerrit.acceptance.NoHttpd; import com.google.gerrit.acceptance.NoHttpd;
@@ -128,7 +127,7 @@ public class CustomLabelIT extends AbstractDaemonTest {
revision(r).review(new ReviewInput().label(P.getName(), 0)); revision(r).review(new ReviewInput().label(P.getName(), 0));
ChangeInfo c = get(r.getChangeId()); ChangeInfo c = get(r.getChangeId());
LabelInfo q = c.labels.get(P.getName()); LabelInfo q = c.labels.get(P.getName());
assertThat(q.all).hasSize(isNoteDbTestEnabled() ? 1 : 2); assertThat(q.all).hasSize(2);
assertThat(q.disliked).isNull(); assertThat(q.disliked).isNull();
assertThat(q.rejected).isNull(); assertThat(q.rejected).isNull();
assertThat(q.blocking).isNull(); assertThat(q.blocking).isNull();

View File

@@ -18,6 +18,7 @@ import static com.google.common.base.Preconditions.checkNotNull;
import static com.google.common.collect.Iterables.getOnlyElement; import static com.google.common.collect.Iterables.getOnlyElement;
import static com.google.gerrit.server.git.QueueProvider.QueueType.INTERACTIVE; import static com.google.gerrit.server.git.QueueProvider.QueueType.INTERACTIVE;
import static com.google.gerrit.server.index.ChangeField.LEGACY_ID; import static com.google.gerrit.server.index.ChangeField.LEGACY_ID;
import static com.google.gerrit.server.index.ChangeField.PROJECT;
import static com.google.gerrit.server.index.IndexRewriter.CLOSED_STATUSES; import static com.google.gerrit.server.index.IndexRewriter.CLOSED_STATUSES;
import static com.google.gerrit.server.index.IndexRewriter.OPEN_STATUSES; import static com.google.gerrit.server.index.IndexRewriter.OPEN_STATUSES;
import static java.util.concurrent.TimeUnit.MILLISECONDS; import static java.util.concurrent.TimeUnit.MILLISECONDS;
@@ -34,6 +35,7 @@ import com.google.gerrit.common.Nullable;
import com.google.gerrit.reviewdb.client.Account; import com.google.gerrit.reviewdb.client.Account;
import com.google.gerrit.reviewdb.client.Change; import com.google.gerrit.reviewdb.client.Change;
import com.google.gerrit.reviewdb.client.PatchSet; 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.reviewdb.server.ReviewDb;
import com.google.gerrit.server.config.ConfigUtil; import com.google.gerrit.server.config.ConfigUtil;
import com.google.gerrit.server.config.GerritServerConfig; import com.google.gerrit.server.config.GerritServerConfig;
@@ -454,7 +456,9 @@ public class LuceneChangeIndex implements ChangeIndex {
ChangeProtoField.CODEC.decode(cb.bytes, cb.offset, cb.length)); ChangeProtoField.CODEC.decode(cb.bytes, cb.offset, cb.length));
} else { } else {
int id = doc.getField(idFieldName).numericValue().intValue(); int id = doc.getField(idFieldName).numericValue().intValue();
cd = changeDataFactory.create(db.get(), new Change.Id(id)); Project.NameKey project =
new Project.NameKey(doc.getField(PROJECT.getName()).stringValue());
cd = changeDataFactory.create(db.get(), project, new Change.Id(id));
} }
if (fields.contains(PATCH_SET_FIELD)) { if (fields.contains(PATCH_SET_FIELD)) {

View File

@@ -309,8 +309,9 @@ public class ChangeHookRunner implements ChangeHooks, EventDispatcher,
.build()); .build());
} }
private ChangeNotes newNotes(ReviewDb db, Change change) { private ChangeNotes newNotes(ReviewDb db, Change change)
return notesFactory.create(db, change); throws OrmException {
return notesFactory.create(db, change.getProject(), change.getId());
} }
private static Optional<Path> hook(Config config, Path path, String name) { private static Optional<Path> hook(Config config, Path path, String name) {

View File

@@ -0,0 +1,102 @@
// Copyright (C) 2016 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;
import com.google.common.base.Optional;
import com.google.common.collect.ImmutableSet;
import com.google.common.primitives.Ints;
import com.google.gerrit.reviewdb.client.Change;
import com.google.gerrit.server.change.ChangeTriplet;
import com.google.gerrit.server.project.ChangeControl;
import com.google.gerrit.server.query.change.ChangeData;
import com.google.gerrit.server.query.change.InternalChangeQuery;
import com.google.gwtorm.server.OrmException;
import com.google.inject.Inject;
import com.google.inject.Provider;
import com.google.inject.Singleton;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
@Singleton
public class ChangeFinder {
private final Provider<InternalChangeQuery> queryProvider;
@Inject
ChangeFinder(Provider<InternalChangeQuery> queryProvider) {
this.queryProvider = queryProvider;
}
/**
* Find changes matching the given identifier.
*
* @param id change identifier, either a numeric ID, a Change-Id, or
* project~branch~id triplet.
* @param user user to wrap in controls.
* @return possibly-empty list of controls for all matching changes,
* corresponding to the given user; may or may not be visible.
* @throws OrmException if an error occurred querying the database.
*/
public List<ChangeControl> find(String id, CurrentUser user)
throws OrmException {
// Use the index to search for changes, but don't return any stored fields,
// to force rereading in case the index is stale.
InternalChangeQuery query = queryProvider.get()
.setRequestedFields(ImmutableSet.<String> of());
// Try legacy id
if (!id.isEmpty() && id.charAt(0) != '0') {
Integer n = Ints.tryParse(id);
if (n != null) {
return asChangeControls(query.byLegacyChangeId(new Change.Id(n)), user);
}
}
// Try isolated changeId
if (!id.contains("~")) {
return asChangeControls(query.byKeyPrefix(id), user);
}
// Try change triplet
Optional<ChangeTriplet> triplet = ChangeTriplet.parse(id);
if (triplet.isPresent()) {
return asChangeControls(query.byBranchKey(
triplet.get().branch(),
triplet.get().id()),
user);
}
return Collections.emptyList();
}
public List<ChangeControl> find(Change.Id id, CurrentUser user)
throws OrmException {
// Use the index to search for changes, but don't return any stored fields,
// to force rereading in case the index is stale.
InternalChangeQuery query = queryProvider.get()
.setRequestedFields(ImmutableSet.<String> of());
return asChangeControls(query.byLegacyChangeId(id), user);
}
private List<ChangeControl> asChangeControls(List<ChangeData> cds,
CurrentUser user) throws OrmException {
List<ChangeControl> ctls = new ArrayList<>(cds.size());
for (ChangeData cd : cds) {
ctls.add(cd.changeControl(user));
}
return ctls;
}
}

View File

@@ -15,11 +15,7 @@
package com.google.gerrit.server; package com.google.gerrit.server;
import com.google.common.base.Function; import com.google.common.base.Function;
import com.google.common.base.Optional;
import com.google.common.collect.ImmutableList;
import com.google.common.collect.ImmutableSet;
import com.google.common.collect.Ordering; import com.google.common.collect.Ordering;
import com.google.common.primitives.Ints;
import com.google.gerrit.common.TimeUtil; import com.google.gerrit.common.TimeUtil;
import com.google.gerrit.extensions.restapi.ResourceConflictException; import com.google.gerrit.extensions.restapi.ResourceConflictException;
import com.google.gerrit.extensions.restapi.RestApiException; import com.google.gerrit.extensions.restapi.RestApiException;
@@ -30,7 +26,6 @@ import com.google.gerrit.reviewdb.client.Project;
import com.google.gerrit.reviewdb.server.ReviewDb; import com.google.gerrit.reviewdb.server.ReviewDb;
import com.google.gerrit.server.change.ChangeInserter; import com.google.gerrit.server.change.ChangeInserter;
import com.google.gerrit.server.change.ChangeMessages; import com.google.gerrit.server.change.ChangeMessages;
import com.google.gerrit.server.change.ChangeTriplet;
import com.google.gerrit.server.git.BatchUpdate; import com.google.gerrit.server.git.BatchUpdate;
import com.google.gerrit.server.git.GitRepositoryManager; import com.google.gerrit.server.git.GitRepositoryManager;
import com.google.gerrit.server.git.UpdateException; import com.google.gerrit.server.git.UpdateException;
@@ -40,8 +35,6 @@ import com.google.gerrit.server.notedb.ChangeNotes;
import com.google.gerrit.server.notedb.ChangeUpdate; import com.google.gerrit.server.notedb.ChangeUpdate;
import com.google.gerrit.server.project.ChangeControl; import com.google.gerrit.server.project.ChangeControl;
import com.google.gerrit.server.project.NoSuchChangeException; import com.google.gerrit.server.project.NoSuchChangeException;
import com.google.gerrit.server.query.change.ChangeData;
import com.google.gerrit.server.query.change.InternalChangeQuery;
import com.google.gerrit.server.util.IdGenerator; import com.google.gerrit.server.util.IdGenerator;
import com.google.gwtorm.server.OrmException; import com.google.gwtorm.server.OrmException;
import com.google.inject.Inject; import com.google.inject.Inject;
@@ -66,9 +59,7 @@ import org.slf4j.LoggerFactory;
import java.io.IOException; import java.io.IOException;
import java.text.MessageFormat; import java.text.MessageFormat;
import java.util.ArrayList;
import java.util.Collections; import java.util.Collections;
import java.util.List;
import java.util.Map; import java.util.Map;
@Singleton @Singleton
@@ -164,9 +155,7 @@ public class ChangeUtil {
private final Provider<CurrentUser> user; private final Provider<CurrentUser> user;
private final Provider<ReviewDb> db; private final Provider<ReviewDb> db;
private final Sequences seq; private final Sequences seq;
private final Provider<InternalChangeQuery> queryProvider;
private final PatchSetUtil psUtil; private final PatchSetUtil psUtil;
private final ChangeControl.GenericFactory changeControlFactory;
private final RevertedSender.Factory revertedSenderFactory; private final RevertedSender.Factory revertedSenderFactory;
private final ChangeInserter.Factory changeInserterFactory; private final ChangeInserter.Factory changeInserterFactory;
private final GitRepositoryManager gitManager; private final GitRepositoryManager gitManager;
@@ -178,9 +167,7 @@ public class ChangeUtil {
ChangeUtil(Provider<CurrentUser> user, ChangeUtil(Provider<CurrentUser> user,
Provider<ReviewDb> db, Provider<ReviewDb> db,
Sequences seq, Sequences seq,
Provider<InternalChangeQuery> queryProvider,
PatchSetUtil psUtil, PatchSetUtil psUtil,
ChangeControl.GenericFactory changeControlFactory,
RevertedSender.Factory revertedSenderFactory, RevertedSender.Factory revertedSenderFactory,
ChangeInserter.Factory changeInserterFactory, ChangeInserter.Factory changeInserterFactory,
GitRepositoryManager gitManager, GitRepositoryManager gitManager,
@@ -190,9 +177,7 @@ public class ChangeUtil {
this.user = user; this.user = user;
this.db = db; this.db = db;
this.seq = seq; this.seq = seq;
this.queryProvider = queryProvider;
this.psUtil = psUtil; this.psUtil = psUtil;
this.changeControlFactory = changeControlFactory;
this.revertedSenderFactory = revertedSenderFactory; this.revertedSenderFactory = revertedSenderFactory;
this.changeInserterFactory = changeInserterFactory; this.changeInserterFactory = changeInserterFactory;
this.gitManager = gitManager; this.gitManager = gitManager;
@@ -285,7 +270,7 @@ public class ChangeUtil {
} }
try { try {
RevertedSender cm = revertedSenderFactory.create(changeId); RevertedSender cm = revertedSenderFactory.create(project, changeId);
cm.setFrom(user.get().getAccountId()); cm.setFrom(user.get().getAccountId());
cm.setChangeMessage(ins.getChangeMessage()); cm.setChangeMessage(ins.getChangeMessage());
cm.send(); cm.send();
@@ -319,62 +304,6 @@ public class ChangeUtil {
} }
} }
/**
* Find changes matching the given identifier.
*
* @param id change identifier, either a numeric ID, a Change-Id, or
* project~branch~id triplet.
* @param user user to wrap in controls.
* @return possibly-empty list of controls for all matching changes,
* corresponding to the given user; may or may not be visible.
* @throws OrmException if an error occurred querying the database.
*/
public List<ChangeControl> findChanges(String id, CurrentUser user)
throws OrmException {
// Try legacy id
if (!id.isEmpty() && id.charAt(0) != '0') {
Integer n = Ints.tryParse(id);
try {
if (n != null) {
return ImmutableList.of(
changeControlFactory.controlFor(new Change.Id(n), user));
}
} catch (NoSuchChangeException e) {
return Collections.emptyList();
}
}
// Use the index to search for changes, but don't return any stored fields,
// to force rereading in case the index is stale.
InternalChangeQuery query = queryProvider.get()
.setRequestedFields(ImmutableSet.<String> of());
// Try isolated changeId
if (!id.contains("~")) {
return asChangeControls(query.byKeyPrefix(id), user);
}
// Try change triplet
Optional<ChangeTriplet> triplet = ChangeTriplet.parse(id);
if (triplet.isPresent()) {
return asChangeControls(query.byBranchKey(
triplet.get().branch(),
triplet.get().id()),
user);
}
return Collections.emptyList();
}
private List<ChangeControl> asChangeControls(List<ChangeData> cds,
CurrentUser user) throws OrmException {
List<ChangeControl> ctls = new ArrayList<>(cds.size());
for (ChangeData cd : cds) {
ctls.add(cd.changeControl(user));
}
return ctls;
}
public static PatchSet.Id nextPatchSetId(PatchSet.Id id) { public static PatchSet.Id nextPatchSetId(PatchSet.Id id) {
return new PatchSet.Id(id.getParentKey(), id.get() + 1); return new PatchSet.Id(id.getParentKey(), id.get() + 1);
} }

View File

@@ -162,7 +162,8 @@ public class Abandon implements RestModifyView<ChangeResource, AbandonInput>,
@Override @Override
public void postUpdate(Context ctx) throws OrmException { public void postUpdate(Context ctx) throws OrmException {
try { try {
ReplyToChangeSender cm = abandonedSenderFactory.create(change.getId()); ReplyToChangeSender cm =
abandonedSenderFactory.create(ctx.getProject(), change.getId());
if (account != null) { if (account != null) {
cm.setFrom(account.getId()); cm.setFrom(account.getId());
} }

View File

@@ -361,8 +361,8 @@ public class ChangeInserter extends BatchUpdate.InsertChangeOp {
@Override @Override
public void run() { public void run() {
try { try {
CreateChangeSender cm = CreateChangeSender cm = createChangeSenderFactory
createChangeSenderFactory.create(change.getId()); .create(change.getProject(), change.getId());
cm.setFrom(change.getOwner()); cm.setFrom(change.getOwner());
cm.setPatchSet(patchSet, patchSetInfo); cm.setPatchSet(patchSet, patchSetInfo);
cm.setNotify(notify); cm.setNotify(notify);

View File

@@ -96,6 +96,7 @@ import com.google.gerrit.server.api.accounts.GpgApiAdapter;
import com.google.gerrit.server.git.GitRepositoryManager; import com.google.gerrit.server.git.GitRepositoryManager;
import com.google.gerrit.server.git.LabelNormalizer; import com.google.gerrit.server.git.LabelNormalizer;
import com.google.gerrit.server.git.MergeUtil; import com.google.gerrit.server.git.MergeUtil;
import com.google.gerrit.server.notedb.ChangeNotes;
import com.google.gerrit.server.notedb.ReviewerStateInternal; import com.google.gerrit.server.notedb.ReviewerStateInternal;
import com.google.gerrit.server.patch.PatchListNotAvailableException; import com.google.gerrit.server.patch.PatchListNotAvailableException;
import com.google.gerrit.server.project.ChangeControl; import com.google.gerrit.server.project.ChangeControl;
@@ -156,6 +157,7 @@ public class ChangeJson {
private final Provider<ConsistencyChecker> checkerProvider; private final Provider<ConsistencyChecker> checkerProvider;
private final ActionJson actionJson; private final ActionJson actionJson;
private final GpgApiAdapter gpgApi; private final GpgApiAdapter gpgApi;
private final ChangeNotes.Factory changeNotesFactory;
private AccountLoader accountLoader; private AccountLoader accountLoader;
private Map<Change.Id, List<SubmitRecord>> submitRecords; private Map<Change.Id, List<SubmitRecord>> submitRecords;
@@ -181,6 +183,7 @@ public class ChangeJson {
Provider<ConsistencyChecker> checkerProvider, Provider<ConsistencyChecker> checkerProvider,
ActionJson actionJson, ActionJson actionJson,
GpgApiAdapter gpgApi, GpgApiAdapter gpgApi,
ChangeNotes.Factory changeNotesFactory,
@Assisted Set<ListChangesOption> options) { @Assisted Set<ListChangesOption> options) {
this.db = db; this.db = db;
this.labelNormalizer = ln; this.labelNormalizer = ln;
@@ -200,6 +203,7 @@ public class ChangeJson {
this.checkerProvider = checkerProvider; this.checkerProvider = checkerProvider;
this.actionJson = actionJson; this.actionJson = actionJson;
this.gpgApi = gpgApi; this.gpgApi = gpgApi;
this.changeNotesFactory = changeNotesFactory;
this.options = options.isEmpty() this.options = options.isEmpty()
? EnumSet.noneOf(ListChangesOption.class) ? EnumSet.noneOf(ListChangesOption.class)
: EnumSet.copyOf(options); : EnumSet.copyOf(options);
@@ -218,32 +222,18 @@ public class ChangeJson {
return format(changeDataFactory.create(db.get(), change)); return format(changeDataFactory.create(db.get(), change));
} }
public ChangeInfo format(Change.Id id) throws OrmException { public ChangeInfo format(Project.NameKey project, Change.Id id)
Change c; throws OrmException {
ChangeNotes notes;
try { try {
c = db.get().changes().get(id); notes = changeNotesFactory.create(db.get(), project, id);
} catch (OrmException e) { } catch (OrmException e) {
if (!has(CHECK)) { if (!has(CHECK)) {
throw e; throw e;
} }
return checkOnly(changeDataFactory.create(db.get(), id)); return checkOnly(changeDataFactory.create(db.get(), project, id));
} }
return format(changeDataFactory.create(db.get(), c)); return format(changeDataFactory.create(db.get(), notes.getChange()));
}
public List<ChangeInfo> format(Collection<Change.Id> ids) throws OrmException {
List<ChangeData> changes = new ArrayList<>(ids.size());
List<ChangeInfo> ret = new ArrayList<>(ids.size());
ReviewDb reviewDb = db.get();
for (Change.Id id : ids) {
changes.add(changeDataFactory.create(reviewDb, id));
}
accountLoader = accountLoaderFactory.create(has(DETAILED_ACCOUNTS));
for (ChangeData cd : changes) {
ret.add(format(cd, Optional.<PatchSet.Id> absent(), false));
}
accountLoader.fill();
return ret;
} }
public ChangeInfo format(ChangeData cd) throws OrmException { public ChangeInfo format(ChangeData cd) throws OrmException {
@@ -391,7 +381,7 @@ public class ChangeJson {
// If any problems were fixed, the ChangeData needs to be reloaded. // If any problems were fixed, the ChangeData needs to be reloaded.
for (ProblemInfo p : out.problems) { for (ProblemInfo p : out.problems) {
if (p.status == ProblemInfo.Status.FIXED) { if (p.status == ProblemInfo.Status.FIXED) {
cd = changeDataFactory.create(cd.db(), cd.getId()); cd = changeDataFactory.create(cd.db(), cd.getProject(), cd.getId());
break; break;
} }
} }

View File

@@ -25,11 +25,10 @@ import com.google.gerrit.extensions.restapi.RestView;
import com.google.gerrit.extensions.restapi.TopLevelResource; import com.google.gerrit.extensions.restapi.TopLevelResource;
import com.google.gerrit.reviewdb.client.Change; import com.google.gerrit.reviewdb.client.Change;
import com.google.gerrit.reviewdb.server.ReviewDb; import com.google.gerrit.reviewdb.server.ReviewDb;
import com.google.gerrit.server.ChangeUtil; import com.google.gerrit.server.ChangeFinder;
import com.google.gerrit.server.CurrentUser; import com.google.gerrit.server.CurrentUser;
import com.google.gerrit.server.index.ChangeIndexer; import com.google.gerrit.server.index.ChangeIndexer;
import com.google.gerrit.server.project.ChangeControl; import com.google.gerrit.server.project.ChangeControl;
import com.google.gerrit.server.project.NoSuchChangeException;
import com.google.gerrit.server.query.change.QueryChanges; import com.google.gerrit.server.query.change.QueryChanges;
import com.google.gwtorm.server.OrmException; import com.google.gwtorm.server.OrmException;
import com.google.inject.Inject; import com.google.inject.Inject;
@@ -45,10 +44,9 @@ public class ChangesCollection implements
AcceptsPost<TopLevelResource> { AcceptsPost<TopLevelResource> {
private final Provider<ReviewDb> db; private final Provider<ReviewDb> db;
private final Provider<CurrentUser> user; private final Provider<CurrentUser> user;
private final ChangeControl.GenericFactory changeControlFactory;
private final Provider<QueryChanges> queryFactory; private final Provider<QueryChanges> queryFactory;
private final DynamicMap<RestView<ChangeResource>> views; private final DynamicMap<RestView<ChangeResource>> views;
private final ChangeUtil changeUtil; private final ChangeFinder changeFinder;
private final CreateChange createChange; private final CreateChange createChange;
private final ChangeIndexer changeIndexer; private final ChangeIndexer changeIndexer;
@@ -56,18 +54,16 @@ public class ChangesCollection implements
ChangesCollection( ChangesCollection(
Provider<ReviewDb> db, Provider<ReviewDb> db,
Provider<CurrentUser> user, Provider<CurrentUser> user,
ChangeControl.GenericFactory changeControlFactory,
Provider<QueryChanges> queryFactory, Provider<QueryChanges> queryFactory,
DynamicMap<RestView<ChangeResource>> views, DynamicMap<RestView<ChangeResource>> views,
ChangeUtil changeUtil, ChangeFinder changeFinder,
CreateChange createChange, CreateChange createChange,
ChangeIndexer changeIndexer) { ChangeIndexer changeIndexer) {
this.db = db; this.db = db;
this.user = user; this.user = user;
this.changeControlFactory = changeControlFactory;
this.queryFactory = queryFactory; this.queryFactory = queryFactory;
this.views = views; this.views = views;
this.changeUtil = changeUtil; this.changeFinder = changeFinder;
this.createChange = createChange; this.createChange = createChange;
this.changeIndexer = changeIndexer; this.changeIndexer = changeIndexer;
} }
@@ -85,7 +81,8 @@ public class ChangesCollection implements
@Override @Override
public ChangeResource parse(TopLevelResource root, IdString id) public ChangeResource parse(TopLevelResource root, IdString id)
throws ResourceNotFoundException, OrmException { throws ResourceNotFoundException, OrmException {
List<ChangeControl> ctls = changeUtil.findChanges(id.encoded(), user.get()); List<ChangeControl> ctls =
changeFinder.find(id.encoded(), user.get());
if (ctls.isEmpty()) { if (ctls.isEmpty()) {
Integer changeId = Ints.tryParse(id.get()); Integer changeId = Ints.tryParse(id.get());
if (changeId != null) { if (changeId != null) {
@@ -112,15 +109,23 @@ public class ChangesCollection implements
public ChangeResource parse(Change.Id id) public ChangeResource parse(Change.Id id)
throws ResourceNotFoundException, OrmException { throws ResourceNotFoundException, OrmException {
List<ChangeControl> ctls = changeFinder.find(id, user.get());
if (ctls.isEmpty()) {
try { try {
ChangeControl ctl = changeControlFactory.controlFor(id, user.get()); changeIndexer.delete(id);
} catch (IOException e) {
throw new ResourceNotFoundException(toIdString(id).get(), e);
}
throw new ResourceNotFoundException(toIdString(id));
}
if (ctls.size() != 1) {
throw new ResourceNotFoundException("Multiple changes found for " + id);
}
ChangeControl ctl = ctls.get(0);
if (!ctl.isVisible(db.get())) { if (!ctl.isVisible(db.get())) {
throw new ResourceNotFoundException(toIdString(id)); throw new ResourceNotFoundException(toIdString(id));
} }
return new ChangeResource(ctl); return new ChangeResource(ctl);
} catch (NoSuchChangeException e) {
throw new ResourceNotFoundException(toIdString(id));
}
} }
private static IdString toIdString(Change.Id id) { private static IdString toIdString(Change.Id id) {

View File

@@ -84,7 +84,8 @@ public class CherryPick implements RestModifyView<RevisionResource, CherryPickIn
cherryPickChange.cherryPick(revision.getChange(), cherryPickChange.cherryPick(revision.getChange(),
revision.getPatchSet(), input.message, refName, revision.getPatchSet(), input.message, refName,
refControl); refControl);
return json.create(ChangeJson.NO_OPTIONS).format(cherryPickedChangeId); return json.create(ChangeJson.NO_OPTIONS).format(revision.getProject(),
cherryPickedChangeId);
} catch (InvalidChangeOperationException e) { } catch (InvalidChangeOperationException e) {
throw new BadRequestException(e.getMessage()); throw new BadRequestException(e.getMessage());
} catch (IntegrationException | NoSuchChangeException e) { } catch (IntegrationException | NoSuchChangeException e) {

View File

@@ -312,7 +312,7 @@ public class ConsistencyChecker {
objId, String.format("patch set %d", psNum)); objId, String.format("patch set %d", psNum));
if (psCommit == null) { if (psCommit == null) {
if (fix != null && fix.deletePatchSetIfCommitMissing) { if (fix != null && fix.deletePatchSetIfCommitMissing) {
deletePatchSet(lastProblem(), ps.getId()); deletePatchSet(lastProblem(), change.getProject(), ps.getId());
} }
continue; continue;
} else if (refProblem != null && fix != null) { } else if (refProblem != null && fix != null) {
@@ -419,7 +419,9 @@ public class ConsistencyChecker {
continue; continue;
} }
try { try {
Change c = db.get().changes().get(psId.getParentKey()); Change c = notesFactory
.create(db.get(), change.getProject(), psId.getParentKey())
.getChange();
if (c == null || !c.getDest().equals(change.getDest())) { if (c == null || !c.getDest().equals(change.getDest())) {
continue; continue;
} }
@@ -577,17 +579,18 @@ public class ConsistencyChecker {
} }
} }
private void deletePatchSet(ProblemInfo p, PatchSet.Id psId) { private void deletePatchSet(ProblemInfo p, Project.NameKey project,
PatchSet.Id psId) {
ReviewDb db = this.db.get(); ReviewDb db = this.db.get();
Change.Id cid = psId.getParentKey(); Change.Id cid = psId.getParentKey();
try { try {
db.changes().beginTransaction(cid); db.changes().beginTransaction(cid);
try { try {
Change c = db.changes().get(cid); ChangeNotes notes = notesFactory.create(db, project, cid);
Change c = notes.getChange();
if (c == null) { if (c == null) {
throw new OrmException("Change missing: " + cid); throw new OrmException("Change missing: " + cid);
} }
ChangeNotes notes = notesFactory.create(db, c);
if (psId.equals(c.currentPatchSetId())) { if (psId.equals(c.currentPatchSetId())) {
List<PatchSet> all = Lists.newArrayList(db.patchSets().byChange(cid)); List<PatchSet> all = Lists.newArrayList(db.patchSets().byChange(cid));

View File

@@ -33,7 +33,7 @@ import com.google.gerrit.reviewdb.client.PatchSet;
import com.google.gerrit.reviewdb.client.Project; import com.google.gerrit.reviewdb.client.Project;
import com.google.gerrit.reviewdb.client.RefNames; import com.google.gerrit.reviewdb.client.RefNames;
import com.google.gerrit.reviewdb.server.ReviewDb; import com.google.gerrit.reviewdb.server.ReviewDb;
import com.google.gerrit.server.ChangeUtil; import com.google.gerrit.server.ChangeFinder;
import com.google.gerrit.server.CurrentUser; import com.google.gerrit.server.CurrentUser;
import com.google.gerrit.server.GerritPersonIdent; import com.google.gerrit.server.GerritPersonIdent;
import com.google.gerrit.server.IdentifiedUser; import com.google.gerrit.server.IdentifiedUser;
@@ -84,7 +84,7 @@ public class CreateChange implements
private final ProjectsCollection projectsCollection; private final ProjectsCollection projectsCollection;
private final ChangeInserter.Factory changeInserterFactory; private final ChangeInserter.Factory changeInserterFactory;
private final ChangeJson.Factory jsonFactory; private final ChangeJson.Factory jsonFactory;
private final ChangeUtil changeUtil; private final ChangeFinder changeFinder;
private final BatchUpdate.Factory updateFactory; private final BatchUpdate.Factory updateFactory;
private final PatchSetUtil psUtil; private final PatchSetUtil psUtil;
private final boolean allowDrafts; private final boolean allowDrafts;
@@ -98,7 +98,7 @@ public class CreateChange implements
ProjectsCollection projectsCollection, ProjectsCollection projectsCollection,
ChangeInserter.Factory changeInserterFactory, ChangeInserter.Factory changeInserterFactory,
ChangeJson.Factory json, ChangeJson.Factory json,
ChangeUtil changeUtil, ChangeFinder changeFinder,
BatchUpdate.Factory updateFactory, BatchUpdate.Factory updateFactory,
PatchSetUtil psUtil, PatchSetUtil psUtil,
@GerritServerConfig Config config) { @GerritServerConfig Config config) {
@@ -110,7 +110,7 @@ public class CreateChange implements
this.projectsCollection = projectsCollection; this.projectsCollection = projectsCollection;
this.changeInserterFactory = changeInserterFactory; this.changeInserterFactory = changeInserterFactory;
this.jsonFactory = json; this.jsonFactory = json;
this.changeUtil = changeUtil; this.changeFinder = changeFinder;
this.updateFactory = updateFactory; this.updateFactory = updateFactory;
this.psUtil = psUtil; this.psUtil = psUtil;
this.allowDrafts = config.getBoolean("change", "allowDrafts", true); this.allowDrafts = config.getBoolean("change", "allowDrafts", true);
@@ -162,7 +162,7 @@ public class CreateChange implements
ObjectId parentCommit; ObjectId parentCommit;
List<String> groups; List<String> groups;
if (input.baseChange != null) { if (input.baseChange != null) {
List<ChangeControl> ctls = changeUtil.findChanges( List<ChangeControl> ctls = changeFinder.find(
input.baseChange, rsrc.getControl().getUser()); input.baseChange, rsrc.getControl().getUser());
if (ctls.size() != 1) { if (ctls.size() != 1) {
throw new InvalidChangeOperationException( throw new InvalidChangeOperationException(
@@ -217,7 +217,7 @@ public class CreateChange implements
bu.execute(); bu.execute();
} }
ChangeJson json = jsonFactory.create(ChangeJson.NO_OPTIONS); ChangeJson json = jsonFactory.create(ChangeJson.NO_OPTIONS);
return Response.created(json.format(changeId)); return Response.created(json.format(project, changeId));
} }
} }

View File

@@ -105,7 +105,8 @@ public class EmailReviewComments implements Runnable, RequestContext {
RequestContext old = requestContext.setContext(this); RequestContext old = requestContext.setContext(this);
try { try {
CommentSender cm = commentSenderFactory.create(notes.getChangeId()); CommentSender cm = commentSenderFactory.create(notes.getProjectName(),
notes.getChangeId());
cm.setFrom(authorId); cm.setFrom(authorId);
cm.setPatchSet(patchSet, cm.setPatchSet(patchSet,
patchSetInfoFactory.get(notes.getProjectName(), patchSet)); patchSetInfoFactory.get(notes.getProjectName(), patchSet));

View File

@@ -259,7 +259,7 @@ public class PatchSetInserter extends BatchUpdate.Op {
if (sendMail) { if (sendMail) {
try { try {
ReplacePatchSetSender cm = replacePatchSetFactory.create( ReplacePatchSetSender cm = replacePatchSetFactory.create(
change.getId()); ctx.getProject(), change.getId());
cm.setFrom(ctx.getUser().getAccountId()); cm.setFrom(ctx.getUser().getAccountId());
cm.setPatchSet(patchSet, patchSetInfo); cm.setPatchSet(patchSet, patchSetInfo);
cm.setChangeMessage(changeMessage); cm.setChangeMessage(changeMessage);

View File

@@ -600,6 +600,8 @@ public class PostReview implements RestModifyView<RevisionResource, ReviewInput>
ups.add(c); ups.add(c);
} }
} }
ctx.getUpdate(ctx.getChange().currentPatchSetId())
.putReviewer(user.getAccountId(), REVIEWER);
} }
private Map<String, PatchSetApproval> scanLabels(ChangeContext ctx, private Map<String, PatchSetApproval> scanLabels(ChangeContext ctx,

View File

@@ -248,7 +248,7 @@ public class PostReviewers implements RestModifyView<ChangeResource, AddReviewer
update.commit(); update.commit();
CheckedFuture<?, IOException> indexFuture = CheckedFuture<?, IOException> indexFuture =
indexer.indexAsync(rsrc.getId()); indexer.indexAsync(rsrc.getProject(), rsrc.getId());
result.reviewers = Lists.newArrayListWithCapacity(added.size()); result.reviewers = Lists.newArrayListWithCapacity(added.size());
for (PatchSetApproval psa : added) { for (PatchSetApproval psa : added) {
// New reviewers have value 0, don't bother normalizing. // New reviewers have value 0, don't bother normalizing.
@@ -286,7 +286,8 @@ public class PostReviewers implements RestModifyView<ChangeResource, AddReviewer
} }
if (!toMail.isEmpty()) { if (!toMail.isEmpty()) {
try { try {
AddReviewerSender cm = addReviewerSenderFactory.create(change.getId()); AddReviewerSender cm = addReviewerSenderFactory
.create(change.getProject(), change.getId());
cm.setFrom(userId); cm.setFrom(userId);
cm.addReviewers(toMail); cm.addReviewers(toMail);
cm.send(); cm.send();

View File

@@ -245,7 +245,7 @@ public class PublishDraftPatchSet implements RestModifyView<RevisionResource, In
private void sendCreateChange(Context ctx) throws EmailException { private void sendCreateChange(Context ctx) throws EmailException {
CreateChangeSender cm = CreateChangeSender cm =
createChangeSenderFactory.create(change.getId()); createChangeSenderFactory.create(ctx.getProject(), change.getId());
cm.setFrom(ctx.getUser().getAccountId()); cm.setFrom(ctx.getUser().getAccountId());
cm.setPatchSet(patchSet, patchSetInfo); cm.setPatchSet(patchSet, patchSetInfo);
cm.addReviewers(recipients.getReviewers()); cm.addReviewers(recipients.getReviewers());
@@ -262,7 +262,7 @@ public class PublishDraftPatchSet implements RestModifyView<RevisionResource, In
ctx.getWhen(), psId); ctx.getWhen(), psId);
msg.setMessage("Uploaded patch set " + psId.get() + "."); msg.setMessage("Uploaded patch set " + psId.get() + ".");
ReplacePatchSetSender cm = ReplacePatchSetSender cm =
replacePatchSetFactory.create(change.getId()); replacePatchSetFactory.create(ctx.getProject(), change.getId());
cm.setFrom(accountId); cm.setFrom(accountId);
cm.setPatchSet(patchSet, patchSetInfo); cm.setPatchSet(patchSet, patchSetInfo);
cm.setChangeMessage(msg); cm.setChangeMessage(msg);

View File

@@ -36,6 +36,7 @@ import com.google.gerrit.server.git.BatchUpdate;
import com.google.gerrit.server.git.GitRepositoryManager; import com.google.gerrit.server.git.GitRepositoryManager;
import com.google.gerrit.server.git.UpdateException; import com.google.gerrit.server.git.UpdateException;
import com.google.gerrit.server.git.validators.CommitValidators; import com.google.gerrit.server.git.validators.CommitValidators;
import com.google.gerrit.server.notedb.ChangeNotes;
import com.google.gerrit.server.project.ChangeControl; import com.google.gerrit.server.project.ChangeControl;
import com.google.gerrit.server.query.change.ChangeData; import com.google.gerrit.server.query.change.ChangeData;
import com.google.gerrit.server.query.change.InternalChangeQuery; import com.google.gerrit.server.query.change.InternalChangeQuery;
@@ -68,6 +69,7 @@ public class Rebase implements RestModifyView<RevisionResource, RebaseInput>,
private final RebaseChangeOp.Factory rebaseFactory; private final RebaseChangeOp.Factory rebaseFactory;
private final RebaseUtil rebaseUtil; private final RebaseUtil rebaseUtil;
private final ChangeJson.Factory json; private final ChangeJson.Factory json;
private final ChangeNotes.Factory notesFactory;
private final Provider<ReviewDb> dbProvider; private final Provider<ReviewDb> dbProvider;
private final Provider<InternalChangeQuery> queryProvider; private final Provider<InternalChangeQuery> queryProvider;
private final PatchSetUtil psUtil; private final PatchSetUtil psUtil;
@@ -78,6 +80,7 @@ public class Rebase implements RestModifyView<RevisionResource, RebaseInput>,
RebaseChangeOp.Factory rebaseFactory, RebaseChangeOp.Factory rebaseFactory,
RebaseUtil rebaseUtil, RebaseUtil rebaseUtil,
ChangeJson.Factory json, ChangeJson.Factory json,
ChangeNotes.Factory notesFactory,
Provider<ReviewDb> dbProvider, Provider<ReviewDb> dbProvider,
Provider<InternalChangeQuery> queryProvider, Provider<InternalChangeQuery> queryProvider,
PatchSetUtil psUtil) { PatchSetUtil psUtil) {
@@ -86,6 +89,7 @@ public class Rebase implements RestModifyView<RevisionResource, RebaseInput>,
this.rebaseFactory = rebaseFactory; this.rebaseFactory = rebaseFactory;
this.rebaseUtil = rebaseUtil; this.rebaseUtil = rebaseUtil;
this.json = json; this.json = json;
this.notesFactory = notesFactory;
this.dbProvider = dbProvider; this.dbProvider = dbProvider;
this.queryProvider = queryProvider; this.queryProvider = queryProvider;
this.psUtil = psUtil; this.psUtil = psUtil;
@@ -120,7 +124,7 @@ public class Rebase implements RestModifyView<RevisionResource, RebaseInput>,
.setValidatePolicy(CommitValidators.Policy.GERRIT)); .setValidatePolicy(CommitValidators.Policy.GERRIT));
bu.execute(); bu.execute();
} }
return json.create(OPTIONS).format(change.getId()); return json.create(OPTIONS).format(change.getProject(), change.getId());
} }
private String findBaseRev(RevWalk rw, RevisionResource rsrc, private String findBaseRev(RevWalk rw, RevisionResource rsrc,
@@ -236,11 +240,9 @@ public class Rebase implements RestModifyView<RevisionResource, RebaseInput>,
if (rsrc.getChange().getId().equals(id)) { if (rsrc.getChange().getId().equals(id)) {
return rsrc.getControl(); return rsrc.getControl();
} }
Change c = dbProvider.get().changes().get(id); ChangeNotes notes =
if (c == null) { notesFactory.create(dbProvider.get(), rsrc.getProject(), id);
return null; return rsrc.getControl().getProjectControl().controlFor(notes);
}
return rsrc.getControl().getProjectControl().controlFor(c);
} }
private boolean hasOneParent(RevWalk rw, PatchSet ps) throws IOException { private boolean hasOneParent(RevWalk rw, PatchSet ps) throws IOException {

View File

@@ -150,7 +150,8 @@ public class Restore implements RestModifyView<ChangeResource, RestoreInput>,
@Override @Override
public void postUpdate(Context ctx) throws OrmException { public void postUpdate(Context ctx) throws OrmException {
try { try {
ReplyToChangeSender cm = restoredSenderFactory.create(change.getId()); ReplyToChangeSender cm =
restoredSenderFactory.create(ctx.getProject(), change.getId());
cm.setFrom(caller.getAccountId()); cm.setFrom(caller.getAccountId());
cm.setChangeMessage(message); cm.setChangeMessage(message);
cm.send(); cm.send();

View File

@@ -76,7 +76,8 @@ public class Revert implements RestModifyView<ChangeResource, RevertInput>,
} catch (NoSuchChangeException e) { } catch (NoSuchChangeException e) {
throw new ResourceNotFoundException(e.getMessage()); throw new ResourceNotFoundException(e.getMessage());
} }
return json.create(ChangeJson.NO_OPTIONS).format(revertedChangeId); return json.create(ChangeJson.NO_OPTIONS).format(req.getProject(),
revertedChangeId);
} }
@Override @Override

View File

@@ -32,6 +32,7 @@ import com.google.gerrit.extensions.webui.UiAction;
import com.google.gerrit.reviewdb.client.Change; import com.google.gerrit.reviewdb.client.Change;
import com.google.gerrit.reviewdb.client.ChangeMessage; import com.google.gerrit.reviewdb.client.ChangeMessage;
import com.google.gerrit.reviewdb.client.PatchSet; import com.google.gerrit.reviewdb.client.PatchSet;
import com.google.gerrit.reviewdb.client.Project;
import com.google.gerrit.reviewdb.client.RevId; import com.google.gerrit.reviewdb.client.RevId;
import com.google.gerrit.reviewdb.server.ReviewDb; import com.google.gerrit.reviewdb.server.ReviewDb;
import com.google.gerrit.server.ChangeMessagesUtil; import com.google.gerrit.server.ChangeMessagesUtil;
@@ -44,6 +45,7 @@ import com.google.gerrit.server.git.ChangeSet;
import com.google.gerrit.server.git.GitRepositoryManager; import com.google.gerrit.server.git.GitRepositoryManager;
import com.google.gerrit.server.git.MergeOp; import com.google.gerrit.server.git.MergeOp;
import com.google.gerrit.server.git.MergeSuperSet; import com.google.gerrit.server.git.MergeSuperSet;
import com.google.gerrit.server.notedb.ChangeNotes;
import com.google.gerrit.server.project.ChangeControl; import com.google.gerrit.server.project.ChangeControl;
import com.google.gerrit.server.project.NoSuchChangeException; import com.google.gerrit.server.project.NoSuchChangeException;
import com.google.gerrit.server.query.change.ChangeData; import com.google.gerrit.server.query.change.ChangeData;
@@ -116,6 +118,7 @@ public class Submit implements RestModifyView<RevisionResource, SubmitInput>,
private final ChangeData.Factory changeDataFactory; private final ChangeData.Factory changeDataFactory;
private final ChangeMessagesUtil cmUtil; private final ChangeMessagesUtil cmUtil;
private final ChangeControl.GenericFactory changeControlFactory; private final ChangeControl.GenericFactory changeControlFactory;
private final ChangeNotes.Factory changeNotesFactory;
private final Provider<MergeOp> mergeOpProvider; private final Provider<MergeOp> mergeOpProvider;
private final MergeSuperSet mergeSuperSet; private final MergeSuperSet mergeSuperSet;
private final AccountsCollection accounts; private final AccountsCollection accounts;
@@ -135,6 +138,7 @@ public class Submit implements RestModifyView<RevisionResource, SubmitInput>,
ChangeData.Factory changeDataFactory, ChangeData.Factory changeDataFactory,
ChangeMessagesUtil cmUtil, ChangeMessagesUtil cmUtil,
ChangeControl.GenericFactory changeControlFactory, ChangeControl.GenericFactory changeControlFactory,
ChangeNotes.Factory changeNotesFactory,
Provider<MergeOp> mergeOpProvider, Provider<MergeOp> mergeOpProvider,
MergeSuperSet mergeSuperSet, MergeSuperSet mergeSuperSet,
AccountsCollection accounts, AccountsCollection accounts,
@@ -146,6 +150,7 @@ public class Submit implements RestModifyView<RevisionResource, SubmitInput>,
this.changeDataFactory = changeDataFactory; this.changeDataFactory = changeDataFactory;
this.cmUtil = cmUtil; this.cmUtil = cmUtil;
this.changeControlFactory = changeControlFactory; this.changeControlFactory = changeControlFactory;
this.changeNotesFactory = changeNotesFactory;
this.mergeOpProvider = mergeOpProvider; this.mergeOpProvider = mergeOpProvider;
this.mergeSuperSet = mergeSuperSet; this.mergeSuperSet = mergeSuperSet;
this.accounts = accounts; this.accounts = accounts;
@@ -203,7 +208,8 @@ public class Submit implements RestModifyView<RevisionResource, SubmitInput>,
try (MergeOp op = mergeOpProvider.get()) { try (MergeOp op = mergeOpProvider.get()) {
ReviewDb db = dbProvider.get(); ReviewDb db = dbProvider.get();
op.merge(db, change, caller, true, input); op.merge(db, change, caller, true, input);
change = db.changes().get(change.getId()); change = changeNotesFactory
.create(db, change.getProject(), change.getId()).getChange();
} }
if (change == null) { if (change == null) {
@@ -227,17 +233,18 @@ public class Submit implements RestModifyView<RevisionResource, SubmitInput>,
/** /**
* @param cs set of changes to be submitted at once * @param cs set of changes to be submitted at once
* @param project the name of the project
* @param identifiedUser the user who is checking to submit * @param identifiedUser the user who is checking to submit
* @return a reason why any of the changes is not submittable or null * @return a reason why any of the changes is not submittable or null
*/ */
private String problemsForSubmittingChangeset( private String problemsForSubmittingChangeset(ChangeSet cs,
ChangeSet cs, IdentifiedUser identifiedUser) { Project.NameKey project, IdentifiedUser identifiedUser) {
try { try {
@SuppressWarnings("resource") @SuppressWarnings("resource")
ReviewDb db = dbProvider.get(); ReviewDb db = dbProvider.get();
for (PatchSet.Id psId : cs.patchIds()) { for (PatchSet.Id psId : cs.patchIds()) {
ChangeControl changeControl = changeControlFactory ChangeControl changeControl = changeControlFactory
.controlFor(psId.getParentKey(), identifiedUser); .controlFor(project, psId.getParentKey(), identifiedUser);
ChangeData c = changeDataFactory.create(db, changeControl); ChangeData c = changeDataFactory.create(db, changeControl);
if (!changeControl.isVisible(db)) { if (!changeControl.isVisible(db)) {
@@ -337,7 +344,7 @@ public class Submit implements RestModifyView<RevisionResource, SubmitInput>,
&& topicSize > 1; && topicSize > 1;
String submitProblems = problemsForSubmittingChangeset(cs, String submitProblems = problemsForSubmittingChangeset(cs,
resource.getUser()); resource.getProject(), resource.getUser());
if (submitProblems != null) { if (submitProblems != null) {
return new UiAction.Description() return new UiAction.Description()
.setLabel(treatWithTopic .setLabel(treatWithTopic

View File

@@ -496,7 +496,7 @@ public class EventFactory {
p.author = asAccountAttribute(author.getAccount()); p.author = asAccountAttribute(author.getAccount());
} }
Change change = db.changes().get(pId.getParentKey()); Change change = notes.getChange();
List<Patch> list = List<Patch> list =
patchListCache.get(change, patchSet).toPatchList(pId); patchListCache.get(change, patchSet).toPatchList(pId);
for (Patch pe : list) { for (Patch pe : list) {
@@ -506,7 +506,7 @@ public class EventFactory {
} }
} }
p.kind = changeKindCache.getChangeKind(db, change, patchSet); p.kind = changeKindCache.getChangeKind(db, change, patchSet);
} catch (OrmException | IOException e) { } catch (IOException e) {
log.error("Cannot load patch set data for " + patchSet.getId(), e); log.error("Cannot load patch set data for " + patchSet.getId(), e);
} catch (PatchSetInfoNotAvailableException e) { } catch (PatchSetInfoNotAvailableException e) {
log.error(String.format("Cannot get authorEmail for %s.", pId), e); log.error(String.format("Cannot get authorEmail for %s.", pId), e);

View File

@@ -615,7 +615,7 @@ public class BatchUpdate implements AutoCloseable {
bmdu.commit(); bmdu.commit();
} }
} }
indexFutures.add(indexer.indexAsync(id)); indexFutures.add(indexer.indexAsync(ctx.getProject(), id));
} }
} }
} catch (Exception e) { } catch (Exception e) {
@@ -635,9 +635,6 @@ public class BatchUpdate implements AutoCloseable {
ChangeNotes notes = changeNotesFactory.createForNew(c); ChangeNotes notes = changeNotesFactory.createForNew(c);
ChangeContext ctx = new ChangeContext( ChangeContext ctx = new ChangeContext(
changeControlFactory.controlFor(notes, user), new BatchUpdateReviewDb(db)); changeControlFactory.controlFor(notes, user), new BatchUpdateReviewDb(db));
if (notesMigration.readChanges()) {
ctx.getNotes().load();
}
return ctx; return ctx;
} }

View File

@@ -17,6 +17,7 @@ package com.google.gerrit.server.git;
import com.google.gerrit.common.Nullable; import com.google.gerrit.common.Nullable;
import com.google.gerrit.reviewdb.client.Account; import com.google.gerrit.reviewdb.client.Account;
import com.google.gerrit.reviewdb.client.Change; import com.google.gerrit.reviewdb.client.Change;
import com.google.gerrit.reviewdb.client.Project;
import com.google.gerrit.reviewdb.server.ReviewDb; import com.google.gerrit.reviewdb.server.ReviewDb;
import com.google.gerrit.server.CurrentUser; import com.google.gerrit.server.CurrentUser;
import com.google.gerrit.server.mail.MergedSender; import com.google.gerrit.server.mail.MergedSender;
@@ -39,7 +40,8 @@ public class EmailMerge implements Runnable, RequestContext {
private static final Logger log = LoggerFactory.getLogger(EmailMerge.class); private static final Logger log = LoggerFactory.getLogger(EmailMerge.class);
public interface Factory { public interface Factory {
EmailMerge create(Change.Id changeId, Account.Id submitter); EmailMerge create(Project.NameKey project, Change.Id changeId,
Account.Id submitter);
} }
private final ExecutorService sendEmailsExecutor; private final ExecutorService sendEmailsExecutor;
@@ -47,6 +49,7 @@ public class EmailMerge implements Runnable, RequestContext {
private final SchemaFactory<ReviewDb> schemaFactory; private final SchemaFactory<ReviewDb> schemaFactory;
private final ThreadLocalRequestContext requestContext; private final ThreadLocalRequestContext requestContext;
private final Project.NameKey project;
private final Change.Id changeId; private final Change.Id changeId;
private final Account.Id submitter; private final Account.Id submitter;
private ReviewDb db; private ReviewDb db;
@@ -56,12 +59,14 @@ public class EmailMerge implements Runnable, RequestContext {
MergedSender.Factory mergedSenderFactory, MergedSender.Factory mergedSenderFactory,
SchemaFactory<ReviewDb> schemaFactory, SchemaFactory<ReviewDb> schemaFactory,
ThreadLocalRequestContext requestContext, ThreadLocalRequestContext requestContext,
@Assisted Project.NameKey project,
@Assisted Change.Id changeId, @Assisted Change.Id changeId,
@Assisted @Nullable Account.Id submitter) { @Assisted @Nullable Account.Id submitter) {
this.sendEmailsExecutor = executor; this.sendEmailsExecutor = executor;
this.mergedSenderFactory = mergedSenderFactory; this.mergedSenderFactory = mergedSenderFactory;
this.schemaFactory = schemaFactory; this.schemaFactory = schemaFactory;
this.requestContext = requestContext; this.requestContext = requestContext;
this.project = project;
this.changeId = changeId; this.changeId = changeId;
this.submitter = submitter; this.submitter = submitter;
} }
@@ -74,7 +79,7 @@ public class EmailMerge implements Runnable, RequestContext {
public void run() { public void run() {
RequestContext old = requestContext.setContext(this); RequestContext old = requestContext.setContext(this);
try { try {
MergedSender cm = mergedSenderFactory.create(changeId); MergedSender cm = mergedSenderFactory.create(project, changeId);
if (submitter != null) { if (submitter != null) {
cm.setFrom(submitter); cm.setFrom(submitter);
} }

View File

@@ -31,8 +31,8 @@ import com.google.common.collect.Multimaps;
import com.google.common.collect.SetMultimap; import com.google.common.collect.SetMultimap;
import com.google.common.collect.Sets; import com.google.common.collect.Sets;
import com.google.common.collect.SortedSetMultimap; import com.google.common.collect.SortedSetMultimap;
import com.google.gerrit.reviewdb.client.Change;
import com.google.gerrit.reviewdb.client.PatchSet; 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.reviewdb.server.ReviewDb;
import com.google.gerrit.server.PatchSetUtil; import com.google.gerrit.server.PatchSetUtil;
import com.google.gerrit.server.change.RevisionResource; import com.google.gerrit.server.change.RevisionResource;
@@ -115,18 +115,15 @@ public class GroupCollector {
public static GroupCollector create(Multimap<ObjectId, Ref> changeRefsById, public static GroupCollector create(Multimap<ObjectId, Ref> changeRefsById,
final ReviewDb db, final PatchSetUtil psUtil, final ReviewDb db, final PatchSetUtil psUtil,
final ChangeNotes.Factory notesFactory) { final ChangeNotes.Factory notesFactory, final Project.NameKey project) {
return new GroupCollector( return new GroupCollector(
transformRefs(changeRefsById), transformRefs(changeRefsById),
new Lookup() { new Lookup() {
@Override @Override
public List<String> lookup(PatchSet.Id psId) throws OrmException { public List<String> lookup(PatchSet.Id psId) throws OrmException {
// TODO(dborowitz): Shouldn't have to look up Change. // TODO(dborowitz): Reuse open repository from caller.
Change c = db.changes().get(psId.getParentKey()); ChangeNotes notes =
if (c == null) { notesFactory.create(db, project, psId.getParentKey());
return null;
}
ChangeNotes notes = notesFactory.create(db, c);
PatchSet ps = psUtil.get(db, notes, psId); PatchSet ps = psUtil.get(db, notes, psId);
return ps != null ? ps.getGroups() : null; return ps != null ? ps.getGroups() : null;
} }

View File

@@ -83,7 +83,8 @@ public class MergeSuperSet {
public ChangeSet completeChangeSet(ReviewDb db, Change change) public ChangeSet completeChangeSet(ReviewDb db, Change change)
throws MissingObjectException, IncorrectObjectTypeException, IOException, throws MissingObjectException, IncorrectObjectTypeException, IOException,
OrmException { OrmException {
ChangeData cd = changeDataFactory.create(db, change.getId()); ChangeData cd =
changeDataFactory.create(db, change.getProject(), change.getId());
if (Submit.wholeTopicEnabled(cfg)) { if (Submit.wholeTopicEnabled(cfg)) {
return completeChangeSetIncludingTopics(db, new ChangeSet(cd)); return completeChangeSetIncludingTopics(db, new ChangeSet(cd));
} else { } else {
@@ -101,7 +102,7 @@ public class MergeSuperSet {
try (Repository repo = repoManager.openRepository(project); try (Repository repo = repoManager.openRepository(project);
RevWalk rw = CodeReviewCommit.newRevWalk(repo)) { RevWalk rw = CodeReviewCommit.newRevWalk(repo)) {
for (Change.Id cId : pc.get(project)) { for (Change.Id cId : pc.get(project)) {
ChangeData cd = changeDataFactory.create(db, cId); ChangeData cd = changeDataFactory.create(db, project, cId);
SubmitTypeRecord str = cd.submitTypeRecord(); SubmitTypeRecord str = cd.submitTypeRecord();
if (!str.isOk()) { if (!str.isOk()) {

View File

@@ -1486,7 +1486,8 @@ public class ReceiveCommits {
final Change changeEnt; final Change changeEnt;
try { try {
changeEnt = db.changes().get(changeId); changeEnt =
notesFactory.create(db, project.getNameKey(), changeId).getChange();
} catch (OrmException e) { } catch (OrmException e) {
log.error("Cannot lookup existing change " + changeId, e); log.error("Cannot lookup existing change " + changeId, e);
reject(cmd, "database error"); reject(cmd, "database error");
@@ -1526,8 +1527,8 @@ public class ReceiveCommits {
newChanges = Lists.newArrayList(); newChanges = Lists.newArrayList();
SetMultimap<ObjectId, Ref> existing = changeRefsById(); SetMultimap<ObjectId, Ref> existing = changeRefsById();
GroupCollector groupCollector = GroupCollector groupCollector = GroupCollector.create(refsById, db, psUtil,
GroupCollector.create(refsById, db, psUtil, notesFactory); notesFactory, project.getNameKey());
rp.getRevWalk().reset(); rp.getRevWalk().reset();
rp.getRevWalk().sort(RevSort.TOPO); rp.getRevWalk().sort(RevSort.TOPO);
@@ -1837,7 +1838,8 @@ public class ReceiveCommits {
changeCtl.getUser().asIdentifiedUser(), false, null); changeCtl.getUser().asIdentifiedUser(), false, null);
} }
addMessage(""); addMessage("");
Change c = db.changes().get(rsrc.getChange().getId()); Change c = notesFactory
.create(db, project.getNameKey(), rsrc.getChange().getId()).getChange();
switch (c.getStatus()) { switch (c.getStatus()) {
case MERGED: case MERGED:
addMessage("Change " + c.getChangeId() + " merged."); addMessage("Change " + c.getChangeId() + " merged.");
@@ -2377,8 +2379,8 @@ public class ReceiveCommits {
@Override @Override
public void run() { public void run() {
try { try {
ReplacePatchSetSender cm = ReplacePatchSetSender cm = replacePatchSetFactory
replacePatchSetFactory.create(change.getId()); .create(project.getNameKey(), change.getId());
cm.setFrom(me); cm.setFrom(me);
cm.setPatchSet(newPatchSet, info); cm.setPatchSet(newPatchSet, info);
cm.setChangeMessage(msg); cm.setChangeMessage(msg);
@@ -2721,7 +2723,8 @@ public class ReceiveCommits {
String refName = cmd.getRefName(); String refName = cmd.getRefName();
Change.Id cid = psi.getParentKey(); Change.Id cid = psi.getParentKey();
Change change = db.changes().get(cid); Change change =
notesFactory.create(db, project.getNameKey(), cid).getChange();
ChangeControl ctl = projectControl.controlFor(change); ChangeControl ctl = projectControl.controlFor(change);
PatchSet ps = psUtil.get(db, ctl.getNotes(), psi); PatchSet ps = psUtil.get(db, ctl.getNotes(), psi);
if (change == null || ps == null) { if (change == null || ps == null) {
@@ -2816,8 +2819,8 @@ public class ReceiveCommits {
@Override @Override
public void run() { public void run() {
try { try {
MergedSender cm = MergedSender cm = mergedSenderFactory.create(project.getNameKey(),
mergedSenderFactory.create(ps.getId().getParentKey()); ps.getId().getParentKey());
cm.setFrom(user.getAccountId()); cm.setFrom(user.getAccountId());
cm.setPatchSet(ps, info); cm.setPatchSet(ps, info);
cm.send(); cm.send();

View File

@@ -24,6 +24,8 @@ import com.google.gerrit.reviewdb.client.Project;
import com.google.gerrit.reviewdb.client.RefNames; import com.google.gerrit.reviewdb.client.RefNames;
import com.google.gerrit.reviewdb.server.ReviewDb; import com.google.gerrit.reviewdb.server.ReviewDb;
import com.google.gerrit.server.cache.CacheModule; import com.google.gerrit.server.cache.CacheModule;
import com.google.gerrit.server.notedb.ChangeNotes;
import com.google.gerrit.server.notedb.NotesMigration;
import com.google.gerrit.server.util.ManualRequestContext; import com.google.gerrit.server.util.ManualRequestContext;
import com.google.gerrit.server.util.OneOffRequestContext; import com.google.gerrit.server.util.OneOffRequestContext;
import com.google.gwtorm.server.OrmException; import com.google.gwtorm.server.OrmException;
@@ -86,12 +88,18 @@ public class ScanningChangeCacheImpl implements ChangeCache {
static class Loader extends CacheLoader<Project.NameKey, List<Change>> { static class Loader extends CacheLoader<Project.NameKey, List<Change>> {
private final GitRepositoryManager repoManager; private final GitRepositoryManager repoManager;
private final NotesMigration notesMigration;
private final ChangeNotes.Factory notesFactory;
private final OneOffRequestContext requestContext; private final OneOffRequestContext requestContext;
@Inject @Inject
Loader(GitRepositoryManager repoManager, Loader(GitRepositoryManager repoManager,
NotesMigration notesMigration,
ChangeNotes.Factory notesFactory,
OneOffRequestContext requestContext) { OneOffRequestContext requestContext) {
this.repoManager = repoManager; this.repoManager = repoManager;
this.notesMigration = notesMigration;
this.notesFactory = notesFactory;
this.requestContext = requestContext; this.requestContext = requestContext;
} }
@@ -99,13 +107,23 @@ public class ScanningChangeCacheImpl implements ChangeCache {
public List<Change> load(Project.NameKey key) throws Exception { public List<Change> load(Project.NameKey key) throws Exception {
try (Repository repo = repoManager.openRepository(key); try (Repository repo = repoManager.openRepository(key);
ManualRequestContext ctx = requestContext.open()) { ManualRequestContext ctx = requestContext.open()) {
return scan(repo, ctx.getReviewDbProvider().get()); return scan(notesMigration, notesFactory, repo,
ctx.getReviewDbProvider().get(), key);
}
} }
} }
public static List<Change> scan(NotesMigration notesMigration,
ChangeNotes.Factory notesFactory, Repository repo, ReviewDb db,
Project.NameKey project) throws OrmException, IOException {
if (!notesMigration.readChanges()) {
return scanDb(repo, db);
} }
public static List<Change> scan(Repository repo, ReviewDb db) return scanNotedb(notesFactory, repo, db, project);
}
public static List<Change> scanDb(Repository repo, ReviewDb db)
throws OrmException, IOException { throws OrmException, IOException {
Map<String, Ref> refs = Map<String, Ref> refs =
repo.getRefDatabase().getRefs(RefNames.REFS_CHANGES); repo.getRefDatabase().getRefs(RefNames.REFS_CHANGES);
@@ -124,4 +142,19 @@ public class ScanningChangeCacheImpl implements ChangeCache {
} }
return changes; return changes;
} }
public static List<Change> scanNotedb(ChangeNotes.Factory notesFactory,
Repository repo, ReviewDb db, Project.NameKey project)
throws OrmException, IOException {
Map<String, Ref> refs =
repo.getRefDatabase().getRefs(RefNames.REFS_CHANGES);
List<Change> changes = new ArrayList<>(refs.size());
for (Ref r : refs.values()) {
Change.Id id = Change.Id.fromRef(r.getName());
if (id != null) {
changes.add(notesFactory.create(db, project, id).getChange());
}
}
return changes;
}
} }

View File

@@ -481,7 +481,8 @@ abstract class SubmitStrategyOp extends BatchUpdate.Op {
// Assume the change must have been merged at this point, otherwise we would // Assume the change must have been merged at this point, otherwise we would
// have failed fast in one of the other steps. // have failed fast in one of the other steps.
try { try {
args.mergedSenderFactory.create(getId(), submitter.getAccountId()) args.mergedSenderFactory
.create(ctx.getProject(), getId(), submitter.getAccountId())
.sendAsync(); .sendAsync();
} catch (Exception e) { } catch (Exception e) {
log.error("Cannot email merged notification for " + getId(), e); log.error("Cannot email merged notification for " + getId(), e);

View File

@@ -108,7 +108,7 @@ public class ChangeField {
/** Project containing the change. */ /** Project containing the change. */
public static final FieldDef<ChangeData, String> PROJECT = public static final FieldDef<ChangeData, String> PROJECT =
new FieldDef.Single<ChangeData, String>( new FieldDef.Single<ChangeData, String>(
ChangeQueryBuilder.FIELD_PROJECT, FieldType.EXACT, false) { ChangeQueryBuilder.FIELD_PROJECT, FieldType.EXACT, true) {
@Override @Override
public String get(ChangeData input, FillArgs args) public String get(ChangeData input, FillArgs args)
throws OrmException { throws OrmException {

View File

@@ -21,6 +21,7 @@ import com.google.common.util.concurrent.Futures;
import com.google.common.util.concurrent.ListenableFuture; import com.google.common.util.concurrent.ListenableFuture;
import com.google.common.util.concurrent.ListeningExecutorService; import com.google.common.util.concurrent.ListeningExecutorService;
import com.google.gerrit.reviewdb.client.Change; import com.google.gerrit.reviewdb.client.Change;
import com.google.gerrit.reviewdb.client.Project;
import com.google.gerrit.reviewdb.server.ReviewDb; import com.google.gerrit.reviewdb.server.ReviewDb;
import com.google.gerrit.server.CurrentUser; import com.google.gerrit.server.CurrentUser;
import com.google.gerrit.server.query.change.ChangeData; import com.google.gerrit.server.query.change.ChangeData;
@@ -128,9 +129,10 @@ public class ChangeIndexer {
* @param id change to index. * @param id change to index.
* @return future for the indexing task. * @return future for the indexing task.
*/ */
public CheckedFuture<?, IOException> indexAsync(Change.Id id) { public CheckedFuture<?, IOException> indexAsync(Project.NameKey project,
Change.Id id) {
return executor != null return executor != null
? submit(new IndexTask(id)) ? submit(new IndexTask(project, id))
: Futures.<Object, IOException> immediateCheckedFuture(null); : Futures.<Object, IOException> immediateCheckedFuture(null);
} }
@@ -140,10 +142,11 @@ public class ChangeIndexer {
* @param ids changes to index. * @param ids changes to index.
* @return future for completing indexing of all changes. * @return future for completing indexing of all changes.
*/ */
public CheckedFuture<?, IOException> indexAsync(Collection<Change.Id> ids) { public CheckedFuture<?, IOException> indexAsync(Project.NameKey project,
Collection<Change.Id> ids) {
List<ListenableFuture<?>> futures = new ArrayList<>(ids.size()); List<ListenableFuture<?>> futures = new ArrayList<>(ids.size());
for (Change.Id id : ids) { for (Change.Id id : ids) {
futures.add(indexAsync(id)); futures.add(indexAsync(project, id));
} }
return allAsList(futures); return allAsList(futures);
} }
@@ -201,9 +204,11 @@ public class ChangeIndexer {
} }
private class IndexTask implements Callable<Void> { private class IndexTask implements Callable<Void> {
private final Project.NameKey project;
private final Change.Id id; private final Change.Id id;
private IndexTask(Change.Id id) { private IndexTask(Project.NameKey project, Change.Id id) {
this.project = project;
this.id = id; this.id = id;
} }
@@ -237,8 +242,8 @@ public class ChangeIndexer {
}; };
RequestContext oldCtx = context.setContext(newCtx); RequestContext oldCtx = context.setContext(newCtx);
try { try {
ChangeData cd = changeDataFactory.create( ChangeData cd = changeDataFactory
newCtx.getReviewDbProvider().get(), id); .create(newCtx.getReviewDbProvider().get(), project, id);
index(cd); index(cd);
return null; return null;
} finally { } finally {

View File

@@ -67,6 +67,7 @@ public class ChangeSchemas {
ChangeField.AUTHOR, ChangeField.AUTHOR,
ChangeField.COMMITTER); ChangeField.COMMITTER);
@Deprecated
static final Schema<ChangeData> V26 = schema( static final Schema<ChangeData> V26 = schema(
ChangeField.LEGACY_ID, ChangeField.LEGACY_ID,
ChangeField.ID, ChangeField.ID,
@@ -104,6 +105,8 @@ public class ChangeSchemas {
ChangeField.COMMITTER, ChangeField.COMMITTER,
ChangeField.DRAFTBY); ChangeField.DRAFTBY);
static final Schema<ChangeData> V27 = schema(V26.getFields().values());
private static Schema<ChangeData> schema(Collection<FieldDef<ChangeData, ?>> fields) { private static Schema<ChangeData> schema(Collection<FieldDef<ChangeData, ?>> fields) {
return new Schema<>(ImmutableList.copyOf(fields)); return new Schema<>(ImmutableList.copyOf(fields));
} }

View File

@@ -37,6 +37,8 @@ import com.google.gerrit.server.git.GitRepositoryManager;
import com.google.gerrit.server.git.MergeUtil; import com.google.gerrit.server.git.MergeUtil;
import com.google.gerrit.server.git.MultiProgressMonitor; import com.google.gerrit.server.git.MultiProgressMonitor;
import com.google.gerrit.server.git.MultiProgressMonitor.Task; import com.google.gerrit.server.git.MultiProgressMonitor.Task;
import com.google.gerrit.server.notedb.ChangeNotes;
import com.google.gerrit.server.notedb.NotesMigration;
import com.google.gerrit.server.git.ScanningChangeCacheImpl; import com.google.gerrit.server.git.ScanningChangeCacheImpl;
import com.google.gerrit.server.patch.PatchListLoader; import com.google.gerrit.server.patch.PatchListLoader;
import com.google.gerrit.server.query.change.ChangeData; import com.google.gerrit.server.query.change.ChangeData;
@@ -116,6 +118,8 @@ public class SiteIndexer {
private final GitRepositoryManager repoManager; private final GitRepositoryManager repoManager;
private final ListeningExecutorService executor; private final ListeningExecutorService executor;
private final ChangeIndexer.Factory indexerFactory; private final ChangeIndexer.Factory indexerFactory;
private final NotesMigration notesMigration;
private final ChangeNotes.Factory notesFactory;
private final ThreeWayMergeStrategy mergeStrategy; private final ThreeWayMergeStrategy mergeStrategy;
private int numChanges = -1; private int numChanges = -1;
@@ -129,12 +133,16 @@ public class SiteIndexer {
GitRepositoryManager repoManager, GitRepositoryManager repoManager,
@IndexExecutor(BATCH) ListeningExecutorService executor, @IndexExecutor(BATCH) ListeningExecutorService executor,
ChangeIndexer.Factory indexerFactory, ChangeIndexer.Factory indexerFactory,
NotesMigration notesMigration,
ChangeNotes.Factory notesFactory,
@GerritServerConfig Config config) { @GerritServerConfig Config config) {
this.schemaFactory = schemaFactory; this.schemaFactory = schemaFactory;
this.changeDataFactory = changeDataFactory; this.changeDataFactory = changeDataFactory;
this.repoManager = repoManager; this.repoManager = repoManager;
this.executor = executor; this.executor = executor;
this.indexerFactory = indexerFactory; this.indexerFactory = indexerFactory;
this.notesMigration = notesMigration;
this.notesFactory = notesFactory;
this.mergeStrategy = MergeUtil.getMergeStrategy(config); this.mergeStrategy = MergeUtil.getMergeStrategy(config);
} }
@@ -238,7 +246,8 @@ public class SiteIndexer {
try (Repository repo = repoManager.openRepository(project); try (Repository repo = repoManager.openRepository(project);
ReviewDb db = schemaFactory.open()) { ReviewDb db = schemaFactory.open()) {
Map<String, Ref> refs = repo.getRefDatabase().getRefs(ALL); Map<String, Ref> refs = repo.getRefDatabase().getRefs(ALL);
for (Change c : ScanningChangeCacheImpl.scan(repo, db)) { for (Change c : ScanningChangeCacheImpl.scan(notesMigration,
notesFactory, repo, db, project)) {
Ref r = refs.get(c.currentPatchSetId().toRefName()); Ref r = refs.get(c.currentPatchSetId().toRefName());
if (r != null) { if (r != null) {
byId.put(r.getObjectId(), changeDataFactory.create(db, c)); byId.put(r.getObjectId(), changeDataFactory.create(db, c));

View File

@@ -17,6 +17,7 @@ package com.google.gerrit.server.mail;
import com.google.gerrit.common.errors.EmailException; import com.google.gerrit.common.errors.EmailException;
import com.google.gerrit.reviewdb.client.AccountProjectWatch.NotifyType; import com.google.gerrit.reviewdb.client.AccountProjectWatch.NotifyType;
import com.google.gerrit.reviewdb.client.Change; import com.google.gerrit.reviewdb.client.Change;
import com.google.gerrit.reviewdb.client.Project;
import com.google.gwtorm.server.OrmException; import com.google.gwtorm.server.OrmException;
import com.google.inject.Inject; import com.google.inject.Inject;
import com.google.inject.assistedinject.Assisted; import com.google.inject.assistedinject.Assisted;
@@ -26,13 +27,15 @@ public class AbandonedSender extends ReplyToChangeSender {
public static interface Factory extends public static interface Factory extends
ReplyToChangeSender.Factory<AbandonedSender> { ReplyToChangeSender.Factory<AbandonedSender> {
@Override @Override
AbandonedSender create(Change.Id change); AbandonedSender create(Project.NameKey project, Change.Id change);
} }
@Inject @Inject
public AbandonedSender(EmailArguments ea, @Assisted Change.Id id) public AbandonedSender(EmailArguments ea,
@Assisted Project.NameKey project,
@Assisted Change.Id id)
throws OrmException { throws OrmException {
super(ea, "abandon", newChangeData(ea, id)); super(ea, "abandon", newChangeData(ea, project, id));
} }
@Override @Override

View File

@@ -16,6 +16,7 @@ package com.google.gerrit.server.mail;
import com.google.gerrit.common.errors.EmailException; import com.google.gerrit.common.errors.EmailException;
import com.google.gerrit.reviewdb.client.Change; import com.google.gerrit.reviewdb.client.Change;
import com.google.gerrit.reviewdb.client.Project;
import com.google.gwtorm.server.OrmException; import com.google.gwtorm.server.OrmException;
import com.google.inject.Inject; import com.google.inject.Inject;
import com.google.inject.assistedinject.Assisted; import com.google.inject.assistedinject.Assisted;
@@ -23,13 +24,15 @@ import com.google.inject.assistedinject.Assisted;
/** Asks a user to review a change. */ /** Asks a user to review a change. */
public class AddReviewerSender extends NewChangeSender { public class AddReviewerSender extends NewChangeSender {
public static interface Factory { public static interface Factory {
AddReviewerSender create(Change.Id id); AddReviewerSender create(Project.NameKey project, Change.Id id);
} }
@Inject @Inject
public AddReviewerSender(EmailArguments ea, @Assisted Change.Id id) public AddReviewerSender(EmailArguments ea,
@Assisted Project.NameKey project,
@Assisted Change.Id id)
throws OrmException { throws OrmException {
super(ea, newChangeData(ea, id)); super(ea, newChangeData(ea, project, id));
} }
@Override @Override

View File

@@ -26,6 +26,7 @@ import com.google.gerrit.reviewdb.client.ChangeMessage;
import com.google.gerrit.reviewdb.client.Patch; import com.google.gerrit.reviewdb.client.Patch;
import com.google.gerrit.reviewdb.client.PatchSet; import com.google.gerrit.reviewdb.client.PatchSet;
import com.google.gerrit.reviewdb.client.PatchSetInfo; import com.google.gerrit.reviewdb.client.PatchSetInfo;
import com.google.gerrit.reviewdb.client.Project;
import com.google.gerrit.server.IdentifiedUser; import com.google.gerrit.server.IdentifiedUser;
import com.google.gerrit.server.mail.ProjectWatch.Watchers; import com.google.gerrit.server.mail.ProjectWatch.Watchers;
import com.google.gerrit.server.patch.PatchList; import com.google.gerrit.server.patch.PatchList;
@@ -56,8 +57,9 @@ import java.util.TreeSet;
public abstract class ChangeEmail extends NotificationEmail { public abstract class ChangeEmail extends NotificationEmail {
private static final Logger log = LoggerFactory.getLogger(ChangeEmail.class); private static final Logger log = LoggerFactory.getLogger(ChangeEmail.class);
protected static ChangeData newChangeData(EmailArguments ea, Change.Id id) { protected static ChangeData newChangeData(EmailArguments ea,
return ea.changeDataFactory.create(ea.db.get(), id); Project.NameKey project, Change.Id id) {
return ea.changeDataFactory.create(ea.db.get(), project, id);
} }
protected final Change change; protected final Change change;

View File

@@ -27,6 +27,7 @@ import com.google.gerrit.reviewdb.client.CommentRange;
import com.google.gerrit.reviewdb.client.Patch; import com.google.gerrit.reviewdb.client.Patch;
import com.google.gerrit.reviewdb.client.PatchLineComment; import com.google.gerrit.reviewdb.client.PatchLineComment;
import com.google.gerrit.reviewdb.client.PatchSet; import com.google.gerrit.reviewdb.client.PatchSet;
import com.google.gerrit.reviewdb.client.Project;
import com.google.gerrit.server.PatchLineCommentsUtil; import com.google.gerrit.server.PatchLineCommentsUtil;
import com.google.gerrit.server.patch.PatchFile; import com.google.gerrit.server.patch.PatchFile;
import com.google.gerrit.server.patch.PatchList; import com.google.gerrit.server.patch.PatchList;
@@ -52,7 +53,7 @@ public class CommentSender extends ReplyToChangeSender {
.getLogger(CommentSender.class); .getLogger(CommentSender.class);
public static interface Factory { public static interface Factory {
CommentSender create(Change.Id id); CommentSender create(Project.NameKey project, Change.Id id);
} }
private List<PatchLineComment> inlineComments = Collections.emptyList(); private List<PatchLineComment> inlineComments = Collections.emptyList();
@@ -61,8 +62,9 @@ public class CommentSender extends ReplyToChangeSender {
@Inject @Inject
public CommentSender(EmailArguments ea, public CommentSender(EmailArguments ea,
PatchLineCommentsUtil plcUtil, PatchLineCommentsUtil plcUtil,
@Assisted Project.NameKey project,
@Assisted Change.Id id) throws OrmException { @Assisted Change.Id id) throws OrmException {
super(ea, "comment", newChangeData(ea, id)); super(ea, "comment", newChangeData(ea, project, id));
this.plcUtil = plcUtil; this.plcUtil = plcUtil;
} }

View File

@@ -19,6 +19,7 @@ import com.google.gerrit.common.errors.EmailException;
import com.google.gerrit.reviewdb.client.Account; import com.google.gerrit.reviewdb.client.Account;
import com.google.gerrit.reviewdb.client.AccountProjectWatch.NotifyType; import com.google.gerrit.reviewdb.client.AccountProjectWatch.NotifyType;
import com.google.gerrit.reviewdb.client.Change; import com.google.gerrit.reviewdb.client.Change;
import com.google.gerrit.reviewdb.client.Project;
import com.google.gerrit.server.mail.ProjectWatch.Watchers; import com.google.gerrit.server.mail.ProjectWatch.Watchers;
import com.google.gwtorm.server.OrmException; import com.google.gwtorm.server.OrmException;
import com.google.inject.Inject; import com.google.inject.Inject;
@@ -33,13 +34,15 @@ public class CreateChangeSender extends NewChangeSender {
LoggerFactory.getLogger(CreateChangeSender.class); LoggerFactory.getLogger(CreateChangeSender.class);
public static interface Factory { public static interface Factory {
CreateChangeSender create(Change.Id id); CreateChangeSender create(Project.NameKey project, Change.Id id);
} }
@Inject @Inject
public CreateChangeSender(EmailArguments ea, @Assisted Change.Id id) public CreateChangeSender(EmailArguments ea,
@Assisted Project.NameKey project,
@Assisted Change.Id id)
throws OrmException { throws OrmException {
super(ea, newChangeData(ea, id)); super(ea, newChangeData(ea, project, id));
} }
@Override @Override

View File

@@ -16,6 +16,7 @@ package com.google.gerrit.server.mail;
import com.google.gerrit.common.errors.EmailException; import com.google.gerrit.common.errors.EmailException;
import com.google.gerrit.reviewdb.client.Change; import com.google.gerrit.reviewdb.client.Change;
import com.google.gerrit.reviewdb.client.Project;
import com.google.gwtorm.server.OrmException; import com.google.gwtorm.server.OrmException;
import com.google.inject.Inject; import com.google.inject.Inject;
import com.google.inject.assistedinject.Assisted; import com.google.inject.assistedinject.Assisted;
@@ -23,13 +24,15 @@ import com.google.inject.assistedinject.Assisted;
/** Send notice about a change failing to merged. */ /** Send notice about a change failing to merged. */
public class MergeFailSender extends ReplyToChangeSender { public class MergeFailSender extends ReplyToChangeSender {
public static interface Factory { public static interface Factory {
MergeFailSender create(Change.Id id); MergeFailSender create(Project.NameKey project, Change.Id id);
} }
@Inject @Inject
public MergeFailSender(EmailArguments ea, @Assisted Change.Id id) public MergeFailSender(EmailArguments ea,
@Assisted Project.NameKey project,
@Assisted Change.Id id)
throws OrmException { throws OrmException {
super(ea, "merge-failed", newChangeData(ea, id)); super(ea, "merge-failed", newChangeData(ea, project, id));
} }
@Override @Override

View File

@@ -24,6 +24,7 @@ import com.google.gerrit.reviewdb.client.Account;
import com.google.gerrit.reviewdb.client.AccountProjectWatch.NotifyType; import com.google.gerrit.reviewdb.client.AccountProjectWatch.NotifyType;
import com.google.gerrit.reviewdb.client.Change; import com.google.gerrit.reviewdb.client.Change;
import com.google.gerrit.reviewdb.client.PatchSetApproval; import com.google.gerrit.reviewdb.client.PatchSetApproval;
import com.google.gerrit.reviewdb.client.Project;
import com.google.gwtorm.server.OrmException; import com.google.gwtorm.server.OrmException;
import com.google.inject.Inject; import com.google.inject.Inject;
import com.google.inject.assistedinject.Assisted; import com.google.inject.assistedinject.Assisted;
@@ -31,15 +32,17 @@ import com.google.inject.assistedinject.Assisted;
/** Send notice about a change successfully merged. */ /** Send notice about a change successfully merged. */
public class MergedSender extends ReplyToChangeSender { public class MergedSender extends ReplyToChangeSender {
public static interface Factory { public static interface Factory {
MergedSender create(Change.Id id); MergedSender create(Project.NameKey project, Change.Id id);
} }
private final LabelTypes labelTypes; private final LabelTypes labelTypes;
@Inject @Inject
public MergedSender(EmailArguments ea, @Assisted Change.Id id) public MergedSender(EmailArguments ea,
@Assisted Project.NameKey project,
@Assisted Change.Id id)
throws OrmException { throws OrmException {
super(ea, "merged", newChangeData(ea, id)); super(ea, "merged", newChangeData(ea, project, id));
labelTypes = changeData.changeControl().getLabelTypes(); labelTypes = changeData.changeControl().getLabelTypes();
} }

View File

@@ -18,6 +18,7 @@ import com.google.gerrit.common.errors.EmailException;
import com.google.gerrit.reviewdb.client.Account; import com.google.gerrit.reviewdb.client.Account;
import com.google.gerrit.reviewdb.client.AccountProjectWatch.NotifyType; import com.google.gerrit.reviewdb.client.AccountProjectWatch.NotifyType;
import com.google.gerrit.reviewdb.client.Change; import com.google.gerrit.reviewdb.client.Change;
import com.google.gerrit.reviewdb.client.Project;
import com.google.gwtorm.server.OrmException; import com.google.gwtorm.server.OrmException;
import com.google.inject.Inject; import com.google.inject.Inject;
import com.google.inject.assistedinject.Assisted; import com.google.inject.assistedinject.Assisted;
@@ -31,16 +32,18 @@ import java.util.Set;
/** Send notice of new patch sets for reviewers. */ /** Send notice of new patch sets for reviewers. */
public class ReplacePatchSetSender extends ReplyToChangeSender { public class ReplacePatchSetSender extends ReplyToChangeSender {
public static interface Factory { public static interface Factory {
ReplacePatchSetSender create(Change.Id id); ReplacePatchSetSender create(Project.NameKey project, Change.Id id);
} }
private final Set<Account.Id> reviewers = new HashSet<>(); private final Set<Account.Id> reviewers = new HashSet<>();
private final Set<Account.Id> extraCC = new HashSet<>(); private final Set<Account.Id> extraCC = new HashSet<>();
@Inject @Inject
public ReplacePatchSetSender(EmailArguments ea, @Assisted Change.Id id) public ReplacePatchSetSender(EmailArguments ea,
@Assisted Project.NameKey project,
@Assisted Change.Id id)
throws OrmException { throws OrmException {
super(ea, "newpatchset", newChangeData(ea, id)); super(ea, "newpatchset", newChangeData(ea, project, id));
} }
public void addReviewers(final Collection<Account.Id> cc) { public void addReviewers(final Collection<Account.Id> cc) {

View File

@@ -16,13 +16,14 @@ package com.google.gerrit.server.mail;
import com.google.gerrit.common.errors.EmailException; import com.google.gerrit.common.errors.EmailException;
import com.google.gerrit.reviewdb.client.Change; import com.google.gerrit.reviewdb.client.Change;
import com.google.gerrit.reviewdb.client.Project;
import com.google.gerrit.server.query.change.ChangeData; import com.google.gerrit.server.query.change.ChangeData;
import com.google.gwtorm.server.OrmException; import com.google.gwtorm.server.OrmException;
/** Alert a user to a reply to a change, usually commentary made during review. */ /** Alert a user to a reply to a change, usually commentary made during review. */
public abstract class ReplyToChangeSender extends ChangeEmail { public abstract class ReplyToChangeSender extends ChangeEmail {
public static interface Factory<T extends ReplyToChangeSender> { public static interface Factory<T extends ReplyToChangeSender> {
T create(Change.Id id); T create(Project.NameKey project, Change.Id id);
} }
protected ReplyToChangeSender(EmailArguments ea, String mc, ChangeData cd) protected ReplyToChangeSender(EmailArguments ea, String mc, ChangeData cd)

View File

@@ -17,6 +17,7 @@ package com.google.gerrit.server.mail;
import com.google.gerrit.common.errors.EmailException; import com.google.gerrit.common.errors.EmailException;
import com.google.gerrit.reviewdb.client.AccountProjectWatch.NotifyType; import com.google.gerrit.reviewdb.client.AccountProjectWatch.NotifyType;
import com.google.gerrit.reviewdb.client.Change; import com.google.gerrit.reviewdb.client.Change;
import com.google.gerrit.reviewdb.client.Project;
import com.google.gwtorm.server.OrmException; import com.google.gwtorm.server.OrmException;
import com.google.inject.Inject; import com.google.inject.Inject;
import com.google.inject.assistedinject.Assisted; import com.google.inject.assistedinject.Assisted;
@@ -26,13 +27,15 @@ public class RestoredSender extends ReplyToChangeSender {
public static interface Factory extends public static interface Factory extends
ReplyToChangeSender.Factory<RestoredSender> { ReplyToChangeSender.Factory<RestoredSender> {
@Override @Override
RestoredSender create(Change.Id id); RestoredSender create(Project.NameKey project, Change.Id id);
} }
@Inject @Inject
public RestoredSender(EmailArguments ea, @Assisted Change.Id id) public RestoredSender(EmailArguments ea,
@Assisted Project.NameKey project,
@Assisted Change.Id id)
throws OrmException { throws OrmException {
super(ea, "restore", newChangeData(ea, id)); super(ea, "restore", newChangeData(ea, project, id));
} }
@Override @Override

View File

@@ -17,6 +17,7 @@ package com.google.gerrit.server.mail;
import com.google.gerrit.common.errors.EmailException; import com.google.gerrit.common.errors.EmailException;
import com.google.gerrit.reviewdb.client.AccountProjectWatch.NotifyType; import com.google.gerrit.reviewdb.client.AccountProjectWatch.NotifyType;
import com.google.gerrit.reviewdb.client.Change; import com.google.gerrit.reviewdb.client.Change;
import com.google.gerrit.reviewdb.client.Project;
import com.google.gwtorm.server.OrmException; import com.google.gwtorm.server.OrmException;
import com.google.inject.Inject; import com.google.inject.Inject;
import com.google.inject.assistedinject.Assisted; import com.google.inject.assistedinject.Assisted;
@@ -24,13 +25,15 @@ import com.google.inject.assistedinject.Assisted;
/** Send notice about a change being reverted. */ /** Send notice about a change being reverted. */
public class RevertedSender extends ReplyToChangeSender { public class RevertedSender extends ReplyToChangeSender {
public static interface Factory { public static interface Factory {
RevertedSender create(Change.Id id); RevertedSender create(Project.NameKey project, Change.Id id);
} }
@Inject @Inject
public RevertedSender(EmailArguments ea, @Assisted Change.Id id) public RevertedSender(EmailArguments ea,
@Assisted Project.NameKey project,
@Assisted Change.Id id)
throws OrmException { throws OrmException {
super(ea, "revert", newChangeData(ea, id)); super(ea, "revert", newChangeData(ea, project, id));
} }
@Override @Override

View File

@@ -50,7 +50,7 @@ public abstract class AbstractChangeNotes<T> extends VersionedMetaData {
if (loaded) { if (loaded) {
return self(); return self();
} }
if (!migration.enabled()) { if (!migration.enabled() || changeId == null) {
loadDefaults(); loadDefaults();
return self(); return self();
} }

View File

@@ -116,16 +116,27 @@ public class ChangeNotes extends AbstractChangeNotes<ChangeNotes> {
this.allUsersProvider = allUsersProvider; this.allUsersProvider = allUsersProvider;
} }
public ChangeNotes create(@SuppressWarnings("unused") ReviewDb db, public ChangeNotes create(ReviewDb db, Project.NameKey project,
Change change) { Change.Id changeId) throws OrmException {
return new ChangeNotes(repoManager, migration, allUsersProvider, change); Change change = db.changes().get(changeId);
// TODO: Throw NoSuchChangeException when the change is not found in the
// database
return new ChangeNotes(repoManager, migration, allUsersProvider, project,
change).load();
} }
public ChangeNotes createForNew(Change change) { public ChangeNotes createFromIndexedChange(Change change) {
return new ChangeNotes(repoManager, migration, allUsersProvider, change); return new ChangeNotes(repoManager, migration, allUsersProvider,
change.getProject(), change);
}
public ChangeNotes createForNew(Change change) throws OrmException {
return new ChangeNotes(repoManager, migration, allUsersProvider,
change.getProject(), change).load();
} }
} }
private final Project.NameKey project;
private final Change change; private final Change change;
private ImmutableSortedMap<PatchSet.Id, PatchSet> patchSets; private ImmutableSortedMap<PatchSet.Id, PatchSet> patchSets;
private ImmutableListMultimap<PatchSet.Id, PatchSetApproval> approvals; private ImmutableListMultimap<PatchSet.Id, PatchSetApproval> approvals;
@@ -147,10 +158,12 @@ public class ChangeNotes extends AbstractChangeNotes<ChangeNotes> {
@VisibleForTesting @VisibleForTesting
public ChangeNotes(GitRepositoryManager repoManager, NotesMigration migration, public ChangeNotes(GitRepositoryManager repoManager, NotesMigration migration,
AllUsersNameProvider allUsersProvider, Change change) { AllUsersNameProvider allUsersProvider, Project.NameKey project,
super(repoManager, migration, change.getId()); Change change) {
super(repoManager, migration, change != null ? change.getId() : null);
this.allUsers = allUsersProvider.get(); this.allUsers = allUsersProvider.get();
this.change = new Change(change); this.project = project;
this.change = change != null ? new Change(change) : null;
} }
public Change getChange() { public Change getChange() {
@@ -283,7 +296,7 @@ public class ChangeNotes extends AbstractChangeNotes<ChangeNotes> {
return; return;
} }
try (RevWalk walk = new RevWalk(reader); try (RevWalk walk = new RevWalk(reader);
ChangeNotesParser parser = new ChangeNotesParser(change.getProject(), ChangeNotesParser parser = new ChangeNotesParser(project,
change.getId(), rev, walk, repoManager)) { change.getId(), rev, walk, repoManager)) {
parser.parseAll(); parser.parseAll();
@@ -297,7 +310,7 @@ public class ChangeNotes extends AbstractChangeNotes<ChangeNotes> {
noteMap = parser.noteMap; noteMap = parser.noteMap;
revisionNotes = parser.revisionNotes; revisionNotes = parser.revisionNotes;
change.setKey(new Change.Key(parser.changeId)); change.setKey(new Change.Key(parser.changeId));
change.setDest(new Branch.NameKey(getProjectName(), parser.branch)); change.setDest(new Branch.NameKey(project, parser.branch));
change.setTopic(Strings.emptyToNull(parser.topic)); change.setTopic(Strings.emptyToNull(parser.topic));
change.setCreatedOn(parser.createdOn); change.setCreatedOn(parser.createdOn);
change.setLastUpdatedOn(parser.lastUpdatedOn); change.setLastUpdatedOn(parser.lastUpdatedOn);
@@ -352,6 +365,6 @@ public class ChangeNotes extends AbstractChangeNotes<ChangeNotes> {
@Override @Override
public Project.NameKey getProjectName() { public Project.NameKey getProjectName() {
return getChange().getProject(); return project;
} }
} }

View File

@@ -207,7 +207,7 @@ class ChangeNotesParser implements AutoCloseable {
} }
PatchSet.Id psId = parsePatchSetId(commit); PatchSet.Id psId = parsePatchSetId(commit);
if (currentPatchSetId == null) { if (currentPatchSetId == null || psId.get() > currentPatchSetId.get()) {
currentPatchSetId = psId; currentPatchSetId = psId;
} }

View File

@@ -29,6 +29,7 @@ import com.google.gerrit.reviewdb.client.PatchSetApproval;
import com.google.gerrit.reviewdb.client.Project; import com.google.gerrit.reviewdb.client.Project;
import com.google.gerrit.reviewdb.server.ReviewDb; import com.google.gerrit.reviewdb.server.ReviewDb;
import com.google.gerrit.server.ApprovalsUtil; import com.google.gerrit.server.ApprovalsUtil;
import com.google.gerrit.server.ChangeFinder;
import com.google.gerrit.server.CurrentUser; import com.google.gerrit.server.CurrentUser;
import com.google.gerrit.server.notedb.ChangeNotes; import com.google.gerrit.server.notedb.ChangeNotes;
import com.google.gerrit.server.query.change.ChangeData; import com.google.gerrit.server.query.change.ChangeData;
@@ -46,20 +47,24 @@ public class ChangeControl {
public static class GenericFactory { public static class GenericFactory {
private final ProjectControl.GenericFactory projectControl; private final ProjectControl.GenericFactory projectControl;
private final Provider<ReviewDb> db; private final Provider<ReviewDb> db;
private final ChangeNotes.Factory notesFactory;
private final ChangeFinder changeFinder;
@Inject @Inject
GenericFactory(ProjectControl.GenericFactory p, Provider<ReviewDb> d) { GenericFactory(
ProjectControl.GenericFactory p,
Provider<ReviewDb> d,
ChangeNotes.Factory n,
ChangeFinder f) {
projectControl = p; projectControl = p;
db = d; db = d;
notesFactory = n;
changeFinder = f;
} }
public ChangeControl controlFor(Change.Id changeId, CurrentUser user) public ChangeControl controlFor(Project.NameKey project, Change.Id changeId,
throws NoSuchChangeException, OrmException { CurrentUser user) throws NoSuchChangeException, OrmException {
Change change = db.get().changes().get(changeId); return controlFor(notesFactory.create(db.get(), project, changeId), user);
if (change == null) {
throw new NoSuchChangeException(changeId);
}
return controlFor(change, user);
} }
public ChangeControl controlFor(Change change, CurrentUser user) public ChangeControl controlFor(Change change, CurrentUser user)
@@ -87,11 +92,11 @@ public class ChangeControl {
public ChangeControl validateFor(Change.Id changeId, CurrentUser user) public ChangeControl validateFor(Change.Id changeId, CurrentUser user)
throws NoSuchChangeException, OrmException { throws NoSuchChangeException, OrmException {
Change change = db.get().changes().get(changeId); List<ChangeControl> ctls = changeFinder.find(changeId, user);
if (change == null) { if (ctls.size() != 1) {
throw new NoSuchChangeException(changeId); throw new NoSuchChangeException(changeId);
} }
return validateFor(change, user); return validateFor(ctls.get(0).getChange(), user);
} }
public ChangeControl validateFor(Change change, CurrentUser user) public ChangeControl validateFor(Change change, CurrentUser user)
@@ -121,10 +126,10 @@ public class ChangeControl {
this.approvalsUtil = approvalsUtil; this.approvalsUtil = approvalsUtil;
} }
@SuppressWarnings("unused") ChangeControl create(RefControl refControl, Project.NameKey project,
ChangeControl create(RefControl refControl, Change change) Change.Id changeId) throws OrmException {
throws OrmException { return create(refControl,
return create(refControl, notesFactory.create(db, change)); notesFactory.create(db, project, changeId));
} }
ChangeControl create(RefControl refControl, ChangeNotes notes) { ChangeControl create(RefControl refControl, ChangeNotes notes) {

View File

@@ -195,7 +195,8 @@ public class ProjectControl {
} }
public ChangeControl controlFor(Change change) throws OrmException { public ChangeControl controlFor(Change change) throws OrmException {
return changeControlFactory.create(controlForRef(change.getDest()), change); return changeControlFactory.create(controlForRef(change.getDest()),
change.getProject(), change.getId());
} }
public ChangeControl controlFor(ChangeNotes notes) { public ChangeControl controlFor(ChangeNotes notes) {

View File

@@ -33,6 +33,7 @@ import com.google.gerrit.reviewdb.client.Patch;
import com.google.gerrit.reviewdb.client.PatchLineComment; import com.google.gerrit.reviewdb.client.PatchLineComment;
import com.google.gerrit.reviewdb.client.PatchSet; import com.google.gerrit.reviewdb.client.PatchSet;
import com.google.gerrit.reviewdb.client.PatchSetApproval; import com.google.gerrit.reviewdb.client.PatchSetApproval;
import com.google.gerrit.reviewdb.client.Project;
import com.google.gerrit.reviewdb.client.RefNames; import com.google.gerrit.reviewdb.client.RefNames;
import com.google.gerrit.reviewdb.server.ReviewDb; import com.google.gerrit.reviewdb.server.ReviewDb;
import com.google.gerrit.server.ApprovalsUtil; import com.google.gerrit.server.ApprovalsUtil;
@@ -269,7 +270,7 @@ public class ChangeData {
} }
public interface Factory { public interface Factory {
ChangeData create(ReviewDb db, Change.Id id); ChangeData create(ReviewDb db, Project.NameKey project, Change.Id id);
ChangeData create(ReviewDb db, Change c); ChangeData create(ReviewDb db, Change c);
ChangeData create(ReviewDb db, ChangeControl c); ChangeData create(ReviewDb db, ChangeControl c);
} }
@@ -283,9 +284,10 @@ public class ChangeData {
* @param id change ID * @param id change ID
* @return instance for testing. * @return instance for testing.
*/ */
public static ChangeData createForTest(Change.Id id, int currentPatchSetId) { public static ChangeData createForTest(Project.NameKey project, Change.Id id,
int currentPatchSetId) {
ChangeData cd = new ChangeData(null, null, null, null, null, null, null, ChangeData cd = new ChangeData(null, null, null, null, null, null, null,
null, null, null, null, null, null, null, id); null, null, null, null, null, null, null, project, id);
cd.currentPatchSet = new PatchSet(new PatchSet.Id(id, currentPatchSetId)); cd.currentPatchSet = new PatchSet(new PatchSet.Id(id, currentPatchSetId));
return cd; return cd;
} }
@@ -305,6 +307,7 @@ public class ChangeData {
private final NotesMigration notesMigration; private final NotesMigration notesMigration;
private final MergeabilityCache mergeabilityCache; private final MergeabilityCache mergeabilityCache;
private final Change.Id legacyId; private final Change.Id legacyId;
private final Project.NameKey project;
private ChangeDataSource returnedBySource; private ChangeDataSource returnedBySource;
private Change change; private Change change;
private ChangeNotes notes; private ChangeNotes notes;
@@ -345,6 +348,7 @@ public class ChangeData {
NotesMigration notesMigration, NotesMigration notesMigration,
MergeabilityCache mergeabilityCache, MergeabilityCache mergeabilityCache,
@Assisted ReviewDb db, @Assisted ReviewDb db,
@Assisted Project.NameKey project,
@Assisted Change.Id id) { @Assisted Change.Id id) {
this.db = db; this.db = db;
this.repoManager = repoManager; this.repoManager = repoManager;
@@ -360,7 +364,8 @@ public class ChangeData {
this.patchListCache = patchListCache; this.patchListCache = patchListCache;
this.notesMigration = notesMigration; this.notesMigration = notesMigration;
this.mergeabilityCache = mergeabilityCache; this.mergeabilityCache = mergeabilityCache;
legacyId = id; this.project = project;
this.legacyId = id;
} }
@AssistedInject @AssistedInject
@@ -396,6 +401,7 @@ public class ChangeData {
this.mergeabilityCache = mergeabilityCache; this.mergeabilityCache = mergeabilityCache;
legacyId = c.getId(); legacyId = c.getId();
change = c; change = c;
project = c.getProject();
} }
@AssistedInject @AssistedInject
@@ -433,6 +439,7 @@ public class ChangeData {
change = c.getChange(); change = c.getChange();
changeControl = c; changeControl = c;
notes = c.getNotes(); notes = c.getNotes();
project = notes.getProjectName();
} }
public ReviewDb db() { public ReviewDb db() {
@@ -536,6 +543,10 @@ public class ChangeData {
return legacyId; return legacyId;
} }
public Project.NameKey getProject() {
return project;
}
boolean fastIsVisibleTo(CurrentUser user) { boolean fastIsVisibleTo(CurrentUser user) {
return visibleTo == user; return visibleTo == user;
} }
@@ -566,7 +577,8 @@ public class ChangeData {
if (change != null) { if (change != null) {
changeControl = changeControlFactory.controlFor(change, user); changeControl = changeControlFactory.controlFor(change, user);
} else { } else {
changeControl = changeControlFactory.controlFor(legacyId, user); changeControl =
changeControlFactory.controlFor(project, legacyId, user);
} }
} catch (NoSuchChangeException e) { } catch (NoSuchChangeException e) {
throw new OrmException(e); throw new OrmException(e);
@@ -591,13 +603,17 @@ public class ChangeData {
} }
public Change reloadChange() throws OrmException { public Change reloadChange() throws OrmException {
change = db.changes().get(legacyId); notes = notesFactory.create(db, project, legacyId);
change = notes.getChange();
if (change == null) {
throw new OrmException("Unable to load change " + legacyId);
}
return change; return change;
} }
public ChangeNotes notes() throws OrmException { public ChangeNotes notes() throws OrmException {
if (notes == null) { if (notes == null) {
notes = notesFactory.create(db, change()); notes = notesFactory.create(db, project, legacyId);
} }
return notes; return notes;
} }
@@ -680,7 +696,7 @@ public class ChangeData {
return false; return false;
} }
String sha1 = ps.getRevision().get(); String sha1 = ps.getRevision().get();
try (Repository repo = repoManager.openRepository(change().getProject()); try (Repository repo = repoManager.openRepository(project);
RevWalk walk = new RevWalk(repo)) { RevWalk walk = new RevWalk(repo)) {
RevCommit c = walk.parseCommit(ObjectId.fromString(sha1)); RevCommit c = walk.parseCommit(ObjectId.fromString(sha1));
commitMessage = c.getFullMessage(); commitMessage = c.getFullMessage();
@@ -789,7 +805,7 @@ public class ChangeData {
if (ps == null || !changeControl().isPatchVisible(ps, db)) { if (ps == null || !changeControl().isPatchVisible(ps, db)) {
return null; return null;
} }
try (Repository repo = repoManager.openRepository(c.getProject())) { try (Repository repo = repoManager.openRepository(project)) {
Ref ref = repo.getRefDatabase().exactRef(c.getDest().get()); Ref ref = repo.getRefDatabase().exactRef(c.getDest().get());
SubmitTypeRecord str = submitTypeRecord(); SubmitTypeRecord str = submitTypeRecord();
if (!str.isOk()) { if (!str.isOk()) {
@@ -798,7 +814,7 @@ public class ChangeData {
return false; return false;
} }
String mergeStrategy = mergeUtilFactory String mergeStrategy = mergeUtilFactory
.create(projectCache.get(c.getProject())) .create(projectCache.get(project))
.mergeStrategyName(); .mergeStrategyName();
mergeable = mergeabilityCache.get( mergeable = mergeabilityCache.get(
ObjectId.fromString(ps.getRevision().get()), ObjectId.fromString(ps.getRevision().get()),
@@ -819,7 +835,7 @@ public class ChangeData {
} }
editsByUser = new HashSet<>(); editsByUser = new HashSet<>();
Change.Id id = change.getId(); Change.Id id = change.getId();
try (Repository repo = repoManager.openRepository(change.getProject())) { try (Repository repo = repoManager.openRepository(project)) {
for (String ref for (String ref
: repo.getRefDatabase().getRefs(RefNames.REFS_USERS).keySet()) { : repo.getRefDatabase().getRefs(RefNames.REFS_USERS).keySet()) {
if (Change.Id.fromEditRefPart(ref).equals(id)) { if (Change.Id.fromEditRefPart(ref).equals(id)) {

View File

@@ -15,7 +15,6 @@
package com.google.gerrit.server.query.change; package com.google.gerrit.server.query.change;
import com.google.gerrit.reviewdb.client.Change; import com.google.gerrit.reviewdb.client.Change;
import com.google.gerrit.reviewdb.client.PatchSet;
import com.google.gerrit.reviewdb.server.ReviewDb; import com.google.gerrit.reviewdb.server.ReviewDb;
import com.google.gwtorm.server.ResultSet; import com.google.gwtorm.server.ResultSet;
import com.google.inject.Provider; import com.google.inject.Provider;
@@ -36,16 +35,6 @@ abstract class ChangeDataResultSet<T> extends AbstractResultSet<ChangeData> {
}; };
} }
static ResultSet<ChangeData> patchSet(final ChangeData.Factory factory,
final Provider<ReviewDb> db, final ResultSet<PatchSet> rs) {
return new ChangeDataResultSet<PatchSet>(rs, false) {
@Override
ChangeData convert(PatchSet t) {
return factory.create(db.get(), t.getId().getParentKey());
}
};
}
private final ResultSet<T> source; private final ResultSet<T> source;
private final boolean unique; private final boolean unique;

View File

@@ -57,6 +57,7 @@ import com.google.gerrit.server.index.IndexCollection;
import com.google.gerrit.server.index.IndexConfig; import com.google.gerrit.server.index.IndexConfig;
import com.google.gerrit.server.index.IndexRewriter; import com.google.gerrit.server.index.IndexRewriter;
import com.google.gerrit.server.index.Schema; import com.google.gerrit.server.index.Schema;
import com.google.gerrit.server.notedb.ChangeNotes;
import com.google.gerrit.server.patch.PatchListCache; import com.google.gerrit.server.patch.PatchListCache;
import com.google.gerrit.server.project.ChangeControl; import com.google.gerrit.server.project.ChangeControl;
import com.google.gerrit.server.project.ListChildProjects; import com.google.gerrit.server.project.ListChildProjects;
@@ -161,6 +162,7 @@ public class ChangeQueryBuilder extends QueryBuilder<ChangeData> {
final IdentifiedUser.GenericFactory userFactory; final IdentifiedUser.GenericFactory userFactory;
final CapabilityControl.Factory capabilityControlFactory; final CapabilityControl.Factory capabilityControlFactory;
final ChangeControl.GenericFactory changeControlGenericFactory; final ChangeControl.GenericFactory changeControlGenericFactory;
final ChangeNotes.Factory notesFactory;
final ChangeData.Factory changeDataFactory; final ChangeData.Factory changeDataFactory;
final FieldDef.FillArgs fillArgs; final FieldDef.FillArgs fillArgs;
final PatchLineCommentsUtil plcUtil; final PatchLineCommentsUtil plcUtil;
@@ -192,6 +194,7 @@ public class ChangeQueryBuilder extends QueryBuilder<ChangeData> {
Provider<CurrentUser> self, Provider<CurrentUser> self,
CapabilityControl.Factory capabilityControlFactory, CapabilityControl.Factory capabilityControlFactory,
ChangeControl.GenericFactory changeControlGenericFactory, ChangeControl.GenericFactory changeControlGenericFactory,
ChangeNotes.Factory notesFactory,
ChangeData.Factory changeDataFactory, ChangeData.Factory changeDataFactory,
FieldDef.FillArgs fillArgs, FieldDef.FillArgs fillArgs,
PatchLineCommentsUtil plcUtil, PatchLineCommentsUtil plcUtil,
@@ -211,12 +214,11 @@ public class ChangeQueryBuilder extends QueryBuilder<ChangeData> {
Provider<ListMembers> listMembers, Provider<ListMembers> listMembers,
@GerritServerConfig Config cfg) { @GerritServerConfig Config cfg) {
this(db, queryProvider, rewriter, opFactories, userFactory, self, this(db, queryProvider, rewriter, opFactories, userFactory, self,
capabilityControlFactory, changeControlGenericFactory, capabilityControlFactory, changeControlGenericFactory, notesFactory,
changeDataFactory, fillArgs, plcUtil, accountResolver, groupBackend, changeDataFactory, fillArgs, plcUtil, accountResolver, groupBackend,
allProjectsName, allUsersName, patchListCache, repoManager, allProjectsName, allUsersName, patchListCache, repoManager,
projectCache, listChildProjects, submitDryRun, projectCache, listChildProjects, submitDryRun, conflictsCache,
conflictsCache, trackingFooters, trackingFooters, indexes != null ? indexes.getSearchIndex() : null,
indexes != null ? indexes.getSearchIndex() : null,
indexConfig, listMembers, indexConfig, listMembers,
cfg == null ? true : cfg.getBoolean("change", "allowDrafts", true)); cfg == null ? true : cfg.getBoolean("change", "allowDrafts", true));
} }
@@ -230,6 +232,7 @@ public class ChangeQueryBuilder extends QueryBuilder<ChangeData> {
Provider<CurrentUser> self, Provider<CurrentUser> self,
CapabilityControl.Factory capabilityControlFactory, CapabilityControl.Factory capabilityControlFactory,
ChangeControl.GenericFactory changeControlGenericFactory, ChangeControl.GenericFactory changeControlGenericFactory,
ChangeNotes.Factory notesFactory,
ChangeData.Factory changeDataFactory, ChangeData.Factory changeDataFactory,
FieldDef.FillArgs fillArgs, FieldDef.FillArgs fillArgs,
PatchLineCommentsUtil plcUtil, PatchLineCommentsUtil plcUtil,
@@ -255,6 +258,7 @@ public class ChangeQueryBuilder extends QueryBuilder<ChangeData> {
this.userFactory = userFactory; this.userFactory = userFactory;
this.self = self; this.self = self;
this.capabilityControlFactory = capabilityControlFactory; this.capabilityControlFactory = capabilityControlFactory;
this.notesFactory = notesFactory;
this.changeControlGenericFactory = changeControlGenericFactory; this.changeControlGenericFactory = changeControlGenericFactory;
this.changeDataFactory = changeDataFactory; this.changeDataFactory = changeDataFactory;
this.fillArgs = fillArgs; this.fillArgs = fillArgs;
@@ -279,7 +283,7 @@ public class ChangeQueryBuilder extends QueryBuilder<ChangeData> {
Arguments asUser(CurrentUser otherUser) { Arguments asUser(CurrentUser otherUser) {
return new Arguments(db, queryProvider, rewriter, opFactories, userFactory, return new Arguments(db, queryProvider, rewriter, opFactories, userFactory,
Providers.of(otherUser), Providers.of(otherUser),
capabilityControlFactory, changeControlGenericFactory, capabilityControlFactory, changeControlGenericFactory, notesFactory,
changeDataFactory, fillArgs, plcUtil, accountResolver, groupBackend, changeDataFactory, fillArgs, plcUtil, accountResolver, groupBackend,
allProjectsName, allUsersName, patchListCache, repoManager, allProjectsName, allUsersName, patchListCache, repoManager,
projectCache, listChildProjects, submitDryRun, projectCache, listChildProjects, submitDryRun,
@@ -729,9 +733,8 @@ public class ChangeQueryBuilder extends QueryBuilder<ChangeData> {
} }
public Predicate<ChangeData> visibleto(CurrentUser user) { public Predicate<ChangeData> visibleto(CurrentUser user) {
return new IsVisibleToPredicate(args.db, // return new IsVisibleToPredicate(args.db, args.notesFactory,
args.changeControlGenericFactory, // args.changeControlGenericFactory, user);
user);
} }
public Predicate<ChangeData> is_visible() throws QueryParseException { public Predicate<ChangeData> is_visible() throws QueryParseException {

View File

@@ -57,8 +57,10 @@ class HasDraftByLegacyPredicate extends OperatorPredicate<ChangeData> implements
} }
List<ChangeData> r = new ArrayList<>(ids.size()); List<ChangeData> r = new ArrayList<>(ids.size());
for (Change.Id id : ids) { // TODO Don't load the changes directly from the database, but provide
r.add(args.changeDataFactory.create(args.db.get(), id)); // project name + change ID to changeDataFactory, or delete this predicate.
for (Change c : args.db.get().changes().get(ids)) {
r.add(args.changeDataFactory.create(args.db.get(), c));
} }
return new ListResultSet<>(r); return new ListResultSet<>(r);
} }

View File

@@ -118,6 +118,10 @@ public class InternalChangeQuery {
return query(new ChangeIdPredicate(prefix)); return query(new ChangeIdPredicate(prefix));
} }
public List<ChangeData> byLegacyChangeId(Change.Id id) throws OrmException {
return query(new LegacyChangeIdPredicate(id));
}
public List<ChangeData> byBranchKey(Branch.NameKey branch, Change.Key key) public List<ChangeData> byBranchKey(Branch.NameKey branch, Change.Key key)
throws OrmException { throws OrmException {
return query(and( return query(and(

View File

@@ -17,6 +17,7 @@ package com.google.gerrit.server.query.change;
import com.google.gerrit.reviewdb.client.Change; import com.google.gerrit.reviewdb.client.Change;
import com.google.gerrit.reviewdb.server.ReviewDb; import com.google.gerrit.reviewdb.server.ReviewDb;
import com.google.gerrit.server.CurrentUser; import com.google.gerrit.server.CurrentUser;
import com.google.gerrit.server.notedb.ChangeNotes;
import com.google.gerrit.server.project.ChangeControl; import com.google.gerrit.server.project.ChangeControl;
import com.google.gerrit.server.project.NoSuchChangeException; import com.google.gerrit.server.project.NoSuchChangeException;
import com.google.gerrit.server.query.OperatorPredicate; import com.google.gerrit.server.query.OperatorPredicate;
@@ -36,13 +37,15 @@ class IsVisibleToPredicate extends OperatorPredicate<ChangeData> {
} }
private final Provider<ReviewDb> db; private final Provider<ReviewDb> db;
private final ChangeNotes.Factory notesFactory;
private final ChangeControl.GenericFactory changeControl; private final ChangeControl.GenericFactory changeControl;
private final CurrentUser user; private final CurrentUser user;
IsVisibleToPredicate(Provider<ReviewDb> db, IsVisibleToPredicate(Provider<ReviewDb> db, ChangeNotes.Factory notesFactory,
ChangeControl.GenericFactory changeControlFactory, CurrentUser user) { ChangeControl.GenericFactory changeControlFactory, CurrentUser user) {
super(ChangeQueryBuilder.FIELD_VISIBLETO, describe(user)); super(ChangeQueryBuilder.FIELD_VISIBLETO, describe(user));
this.db = db; this.db = db;
this.notesFactory = notesFactory;
this.changeControl = changeControlFactory; this.changeControl = changeControlFactory;
this.user = user; this.user = user;
} }
@@ -58,7 +61,8 @@ class IsVisibleToPredicate extends OperatorPredicate<ChangeData> {
return false; return false;
} }
ChangeControl cc = changeControl.controlFor(c, user); ChangeNotes notes = notesFactory.createFromIndexedChange(c);
ChangeControl cc = changeControl.controlFor(notes, user);
if (cc.isVisible(db.get())) { if (cc.isVisible(db.get())) {
cd.cacheVisibleTo(cc); cd.cacheVisibleTo(cc);
return true; return true;

View File

@@ -15,11 +15,14 @@
package com.google.gerrit.server.query.change; package com.google.gerrit.server.query.change;
import static com.google.common.base.Preconditions.checkArgument; import static com.google.common.base.Preconditions.checkArgument;
import static com.google.gerrit.server.index.ChangeField.CHANGE;
import static com.google.gerrit.server.index.ChangeField.PROJECT;
import com.google.auto.value.AutoValue; import com.google.auto.value.AutoValue;
import com.google.common.collect.ImmutableSet; import com.google.common.collect.ImmutableSet;
import com.google.gerrit.server.index.IndexConfig; import com.google.gerrit.server.index.IndexConfig;
import java.util.HashSet;
import java.util.Set; import java.util.Set;
@AutoValue @AutoValue
@@ -28,6 +31,14 @@ public abstract class QueryOptions {
Set<String> fields) { Set<String> fields) {
checkArgument(start >= 0, "start must be nonnegative: %s", start); checkArgument(start >= 0, "start must be nonnegative: %s", start);
checkArgument(limit > 0, "limit must be positive: %s", limit); checkArgument(limit > 0, "limit must be positive: %s", limit);
// Always include project since it is needed to load the change from notedb.
if (!fields.contains(CHANGE.getName())
&& !fields.contains(PROJECT.getName())) {
fields = new HashSet<>(fields);
fields.add(PROJECT.getName());
}
return new AutoValue_QueryOptions(config, start, limit, return new AutoValue_QueryOptions(config, start, limit,
ImmutableSet.copyOf(fields)); ImmutableSet.copyOf(fields));
} }

View File

@@ -31,6 +31,7 @@ import com.google.gerrit.server.index.IndexCollection;
import com.google.gerrit.server.index.IndexConfig; import com.google.gerrit.server.index.IndexConfig;
import com.google.gerrit.server.index.IndexPredicate; import com.google.gerrit.server.index.IndexPredicate;
import com.google.gerrit.server.index.IndexRewriter; import com.google.gerrit.server.index.IndexRewriter;
import com.google.gerrit.server.notedb.ChangeNotes;
import com.google.gerrit.server.project.ChangeControl; import com.google.gerrit.server.project.ChangeControl;
import com.google.gerrit.server.query.Predicate; import com.google.gerrit.server.query.Predicate;
import com.google.gerrit.server.query.QueryParseException; import com.google.gerrit.server.query.QueryParseException;
@@ -48,6 +49,7 @@ public class QueryProcessor {
private final Provider<ReviewDb> db; private final Provider<ReviewDb> db;
private final Provider<CurrentUser> userProvider; private final Provider<CurrentUser> userProvider;
private final ChangeControl.GenericFactory changeControlFactory; private final ChangeControl.GenericFactory changeControlFactory;
private final ChangeNotes.Factory notesFactory;
private final IndexCollection indexes; private final IndexCollection indexes;
private final IndexRewriter rewriter; private final IndexRewriter rewriter;
private final IndexConfig indexConfig; private final IndexConfig indexConfig;
@@ -62,6 +64,7 @@ public class QueryProcessor {
QueryProcessor(Provider<ReviewDb> db, QueryProcessor(Provider<ReviewDb> db,
Provider<CurrentUser> userProvider, Provider<CurrentUser> userProvider,
ChangeControl.GenericFactory changeControlFactory, ChangeControl.GenericFactory changeControlFactory,
ChangeNotes.Factory notesFactory,
IndexCollection indexes, IndexCollection indexes,
IndexRewriter rewriter, IndexRewriter rewriter,
IndexConfig indexConfig, IndexConfig indexConfig,
@@ -69,6 +72,7 @@ public class QueryProcessor {
this.db = db; this.db = db;
this.userProvider = userProvider; this.userProvider = userProvider;
this.changeControlFactory = changeControlFactory; this.changeControlFactory = changeControlFactory;
this.notesFactory = notesFactory;
this.indexes = indexes; this.indexes = indexes;
this.rewriter = rewriter; this.rewriter = rewriter;
this.indexConfig = indexConfig; this.indexConfig = indexConfig;
@@ -138,7 +142,8 @@ public class QueryProcessor {
Timer0.Context context = metrics.executionTime.start(); Timer0.Context context = metrics.executionTime.start();
Predicate<ChangeData> visibleToMe = enforceVisibility Predicate<ChangeData> visibleToMe = enforceVisibility
? new IsVisibleToPredicate(db, changeControlFactory, userProvider.get()) ? new IsVisibleToPredicate(db, notesFactory, changeControlFactory,
userProvider.get())
: null; : null;
int cnt = queries.size(); int cnt = queries.size();

View File

@@ -355,7 +355,7 @@ public class WalkSorterTest {
throws Exception { throws Exception {
Project.NameKey project = tr.getRepository().getDescription().getProject(); Project.NameKey project = tr.getRepository().getDescription().getProject();
Change c = TestChanges.newChange(project, userId); Change c = TestChanges.newChange(project, userId);
ChangeData cd = ChangeData.createForTest(c.getId(), 1); ChangeData cd = ChangeData.createForTest(project, c.getId(), 1);
cd.setChange(c); cd.setChange(c);
cd.currentPatchSet().setRevision(new RevId(id.name())); cd.currentPatchSet().setRevision(new RevId(id.name()));
cd.setPatchSets(ImmutableList.of(cd.currentPatchSet())); cd.setPatchSets(ImmutableList.of(cd.currentPatchSet()));

View File

@@ -27,7 +27,7 @@ public class FakeQueryBuilder extends ChangeQueryBuilder {
FakeQueryBuilder.class), FakeQueryBuilder.class),
new ChangeQueryBuilder.Arguments(null, null, null, null, null, null, new ChangeQueryBuilder.Arguments(null, null, null, null, null, null,
null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null,
null, null, indexes, null, null, null, null, null, null)); null, null, null, indexes, null, null, null, null, null, null));
} }
@Operator @Operator

View File

@@ -186,7 +186,8 @@ public class AbstractChangeNotesTest extends GerritBaseTests {
} }
protected ChangeNotes newNotes(Change c) throws OrmException { protected ChangeNotes newNotes(Change c) throws OrmException {
return new ChangeNotes(repoManager, MIGRATION, allUsers, c).load(); return new ChangeNotes(repoManager, MIGRATION, allUsers, c.getProject(), c)
.load();
} }
protected static SubmitRecord submitRecord(String status, protected static SubmitRecord submitRecord(String status,

View File

@@ -633,6 +633,14 @@ public class ChangeNotesTest extends AbstractChangeNotesTest {
assertThat(ps2.getRevision().get()).isEqualTo(commit.name()); assertThat(ps2.getRevision().get()).isEqualTo(commit.name());
assertThat(ps2.getUploader()).isEqualTo(otherUser.getAccountId()); assertThat(ps2.getUploader()).isEqualTo(otherUser.getAccountId());
assertThat(ps2.getCreatedOn()).isEqualTo(update.getWhen()); assertThat(ps2.getCreatedOn()).isEqualTo(update.getWhen());
// comment on ps1, current patch set is still ps2
update = newUpdate(c, changeOwner);
update.setPatchSetId(ps1.getId());
update.setChangeMessage("Comment on old patch set.");
update.commit();
notes = newNotes(c);
assertThat(notes.getChange().currentPatchSetId()).isEqualTo(ps2.getId());
} }
@Test @Test

View File

@@ -20,6 +20,7 @@ import static com.google.gerrit.extensions.client.ListChangesOption.REVIEWED;
import static java.util.concurrent.TimeUnit.HOURS; import static java.util.concurrent.TimeUnit.HOURS;
import static java.util.concurrent.TimeUnit.MILLISECONDS; import static java.util.concurrent.TimeUnit.MILLISECONDS;
import static java.util.concurrent.TimeUnit.MINUTES; import static java.util.concurrent.TimeUnit.MINUTES;
import static java.util.concurrent.TimeUnit.SECONDS;
import static org.junit.Assert.fail; import static org.junit.Assert.fail;
import com.google.common.base.Function; import com.google.common.base.Function;
@@ -59,6 +60,7 @@ import com.google.gerrit.server.git.BatchUpdate;
import com.google.gerrit.server.git.validators.CommitValidators; import com.google.gerrit.server.git.validators.CommitValidators;
import com.google.gerrit.server.index.ChangeField; import com.google.gerrit.server.index.ChangeField;
import com.google.gerrit.server.index.IndexCollection; import com.google.gerrit.server.index.IndexCollection;
import com.google.gerrit.server.notedb.ChangeNotes;
import com.google.gerrit.server.notedb.NotesMigration; import com.google.gerrit.server.notedb.NotesMigration;
import com.google.gerrit.server.project.ProjectControl; import com.google.gerrit.server.project.ProjectControl;
import com.google.gerrit.server.project.RefControl; import com.google.gerrit.server.project.RefControl;
@@ -110,6 +112,7 @@ public abstract class AbstractQueryChangesTest extends GerritServerTests {
@Inject protected InMemoryRepositoryManager repoManager; @Inject protected InMemoryRepositoryManager repoManager;
@Inject protected InternalChangeQuery internalChangeQuery; @Inject protected InternalChangeQuery internalChangeQuery;
@Inject protected NotesMigration notesMigration; @Inject protected NotesMigration notesMigration;
@Inject protected ChangeNotes.Factory notesFactory;
@Inject protected PatchSetInserter.Factory patchSetFactory; @Inject protected PatchSetInserter.Factory patchSetFactory;
@Inject protected ProjectControl.GenericFactory projectControlFactory; @Inject protected ProjectControl.GenericFactory projectControlFactory;
@Inject protected QueryProcessor queryProcessor; @Inject protected QueryProcessor queryProcessor;
@@ -720,6 +723,8 @@ public abstract class AbstractQueryChangesTest extends GerritServerTests {
@Test @Test
public void updatedOrderWithSubMinuteResolution() throws Exception { public void updatedOrderWithSubMinuteResolution() throws Exception {
TestTimeUtil.resetWithClockStep(1, SECONDS);
TestRepository<Repo> repo = createProject("repo"); TestRepository<Repo> repo = createProject("repo");
ChangeInserter ins1 = newChange(repo); ChangeInserter ins1 = newChange(repo);
Change change1 = insert(repo, ins1); Change change1 = insert(repo, ins1);
@@ -731,7 +736,8 @@ public abstract class AbstractQueryChangesTest extends GerritServerTests {
gApi.changes().id(change1.getId().get()).current() gApi.changes().id(change1.getId().get()).current()
.review(new ReviewInput()); .review(new ReviewInput());
change1 = db.changes().get(change1.getId()); change1 = notesFactory.create(db, change1.getProject(), change1.getId())
.getChange();
assertThat(lastUpdatedMs(change1)).isGreaterThan(lastUpdatedMs(change2)); assertThat(lastUpdatedMs(change1)).isGreaterThan(lastUpdatedMs(change2));
assertThat(lastUpdatedMs(change1) - lastUpdatedMs(change2)) assertThat(lastUpdatedMs(change1) - lastUpdatedMs(change2))

View File

@@ -28,9 +28,9 @@ import org.junit.Test;
public class ChangeDataTest { public class ChangeDataTest {
@Test @Test
public void setPatchSetsClearsCurrentPatchSet() throws Exception { public void setPatchSetsClearsCurrentPatchSet() throws Exception {
ChangeData cd = ChangeData.createForTest(new Change.Id(1), 1); Project.NameKey project = new Project.NameKey("project");
cd.setChange(TestChanges.newChange( ChangeData cd = ChangeData.createForTest(project, new Change.Id(1), 1);
new Project.NameKey("project"), new Account.Id(1000))); cd.setChange(TestChanges.newChange(project, new Account.Id(1000)));
PatchSet curr1 = cd.currentPatchSet(); PatchSet curr1 = cd.currentPatchSet();
int currId = curr1.getId().get(); int currId = curr1.getId().get();
PatchSet ps1 = new PatchSet(new PatchSet.Id(cd.getId(), currId + 1)); PatchSet ps1 = new PatchSet(new PatchSet.Id(cd.getId(), currId + 1));

View File

@@ -18,6 +18,7 @@ import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertTrue; import static org.junit.Assert.assertTrue;
import com.google.gerrit.reviewdb.client.Change; import com.google.gerrit.reviewdb.client.Change;
import com.google.gerrit.reviewdb.client.Project;
import com.google.gwtorm.server.OrmException; import com.google.gwtorm.server.OrmException;
import org.junit.Test; import org.junit.Test;
@@ -84,7 +85,8 @@ public class RegexPathPredicateTest {
private static ChangeData change(String... files) throws OrmException { private static ChangeData change(String... files) throws OrmException {
Arrays.sort(files); Arrays.sort(files);
ChangeData cd = ChangeData.createForTest(new Change.Id(1), 1); ChangeData cd = ChangeData.createForTest(new Project.NameKey("project"),
new Change.Id(1), 1);
cd.setCurrentFilePaths(Arrays.asList(files)); cd.setCurrentFilePaths(Arrays.asList(files));
return cd; return cd;
} }

View File

@@ -139,7 +139,8 @@ public class TestChanges {
expect(ctl.getChange()).andStubReturn(c); expect(ctl.getChange()).andStubReturn(c);
expect(ctl.getProject()).andStubReturn(new Project(c.getProject())); expect(ctl.getProject()).andStubReturn(new Project(c.getProject()));
expect(ctl.getUser()).andStubReturn(user); expect(ctl.getUser()).andStubReturn(user);
ChangeNotes notes = new ChangeNotes(repoManager, migration, allUsers, c) ChangeNotes notes =
new ChangeNotes(repoManager, migration, allUsers, c.getProject(), c)
.load(); .load();
expect(ctl.getNotes()).andStubReturn(notes); expect(ctl.getNotes()).andStubReturn(notes);
expect(ctl.getId()).andStubReturn(c.getId()); expect(ctl.getId()).andStubReturn(c.getId());

View File

@@ -127,7 +127,7 @@ public class PatchSetParser {
if (c == null) { if (c == null) {
throw error("\"" + changeId + "\" no such change"); throw error("\"" + changeId + "\" no such change");
} }
return notesFactory.create(db.get(), c); return notesFactory.create(db.get(), c.getProject(), changeId);
} }
private static boolean inProject(Change change, private static boolean inProject(Change change,

View File

@@ -20,7 +20,7 @@ import com.google.gerrit.reviewdb.client.Account;
import com.google.gerrit.reviewdb.client.Change; import com.google.gerrit.reviewdb.client.Change;
import com.google.gerrit.reviewdb.client.Project; import com.google.gerrit.reviewdb.client.Project;
import com.google.gerrit.reviewdb.server.ReviewDb; import com.google.gerrit.reviewdb.server.ReviewDb;
import com.google.gerrit.server.ChangeUtil; import com.google.gerrit.server.ChangeFinder;
import com.google.gerrit.server.CurrentUser; import com.google.gerrit.server.CurrentUser;
import com.google.gerrit.server.change.ChangeResource; import com.google.gerrit.server.change.ChangeResource;
import com.google.gerrit.server.change.ChangesCollection; import com.google.gerrit.server.change.ChangesCollection;
@@ -94,7 +94,7 @@ public class SetReviewersCommand extends SshCommand {
private ChangesCollection changesCollection; private ChangesCollection changesCollection;
@Inject @Inject
private ChangeUtil changeUtil; private ChangeFinder changeFinder;
private Set<Account.Id> toRemove = new HashSet<>(); private Set<Account.Id> toRemove = new HashSet<>();
@@ -165,7 +165,7 @@ public class SetReviewersCommand extends SshCommand {
private void addChangeImpl(String id) throws UnloggedFailure, OrmException { private void addChangeImpl(String id) throws UnloggedFailure, OrmException {
List<ChangeControl> matched = List<ChangeControl> matched =
changeUtil.findChanges(id, userProvider.get()); changeFinder.find(id, userProvider.get());
List<ChangeControl> toAdd = new ArrayList<>(changes.size()); List<ChangeControl> toAdd = new ArrayList<>(changes.size());
for (ChangeControl ctl : matched) { for (ChangeControl ctl : matched) {
if (!changes.containsKey(ctl.getId()) && inProject(ctl.getProject()) if (!changes.containsKey(ctl.getId()) && inProject(ctl.getProject())