Merge branch 'stable-2.8'

* stable-2.8:
  Copy reviewed flag for deleted files
  Refactor ChangesCollection to be injectable
  Documentation: Link from 'Server administration -> Plugins' to plugins
  Minor cleanups in plugin documentation
  Document 'Force Edit' flag of 'Edit Topic Name' access right
This commit is contained in:
Shawn Pearce
2013-11-08 16:13:55 -08:00
10 changed files with 122 additions and 66 deletions

View File

@@ -822,6 +822,10 @@ The change owner, branch owners, project owners, and site administrators
can always edit the topic name (even without having the `Edit Topic Name` can always edit the topic name (even without having the `Edit Topic Name`
access right assigned). access right assigned).
Whether the topic can be edited on closed changes can be controlled
by the 'Force Edit' flag. If this flag is not set the topic can only be
edited on open changes.
Examples of typical roles in a project Examples of typical roles in a project
-------------------------------------- --------------------------------------

View File

@@ -673,16 +673,17 @@ this can be specified by setting `scope = CapabilityScope.CORE`:
UI Extension UI Extension
------------ ------------
Plugins can contribute their own UI actions on core Gerrit pages. Plugins can contribute UI actions on core Gerrit pages. This is useful
This is useful for workflow customization or exposing plugin functionality for workflow customization or exposing plugin functionality through the
through the UI in addition to SSH commands and the REST API. UI in addition to SSH commands and the REST API.
For instance a plugin to integrate Jira with Gerrit changes may contribute its For instance a plugin to integrate Jira with Gerrit changes may
own "File bug" button to allow filing a bug from the change page or plugins to contribute a "File bug" button to allow filing a bug from the change
integrate continuous integration systems may contribute a "Schedule" button to page or plugins to integrate continuous integration systems may
allow a CI build to be scheduled manually from the patch set panel. contribute a "Schedule" button to allow a CI build to be scheduled
manually from the patch set panel.
Two different places on core Gerrit pages are currently supported: Two different places on core Gerrit pages are supported:
* Change screen * Change screen
* Project info screen * Project info screen
@@ -791,7 +792,8 @@ public class Module extends AbstractModule {
} }
---- ----
The module above must be declared in pom.xml for Maven driven plugins: The module above must be declared in the `pom.xml` for Maven driven
plugins:
[source,xml] [source,xml]
---- ----
@@ -800,7 +802,7 @@ The module above must be declared in pom.xml for Maven driven plugins:
</manifestEntries> </manifestEntries>
---- ----
or in the BUCK configuration file for Buck driven plugins: or in the `BUCK` configuration file for Buck driven plugins:
[source,python] [source,python]
---- ----
@@ -855,7 +857,8 @@ public class HttpModule extends HttpPluginModule {
} }
---- ----
The HTTP module above must be declared in pom.xml for Maven driven plugins: The HTTP module above must be declared in the `pom.xml` for Maven
driven plugins:
[source,xml] [source,xml]
---- ----
@@ -864,7 +867,7 @@ The HTTP module above must be declared in pom.xml for Maven driven plugins:
</manifestEntries> </manifestEntries>
---- ----
or in the BUCK configuration file for Buck driven plugins or in the `BUCK` configuration file for Buck driven plugins
[source,python] [source,python]
---- ----
@@ -881,7 +884,7 @@ case.
The following prerequisities must be met, to satisfy the capability check: The following prerequisities must be met, to satisfy the capability check:
* user is authenticated * user is authenticated
* user is a member of the Administrators group, or * user is a member of a group which has the `Administrate Server` capability, or
* user is a member of a group which has the required capability * user is a member of a group which has the required capability
The `apply` method is called when the button is clicked. If `UiAction` is The `apply` method is called when the button is clicked. If `UiAction` is
@@ -901,7 +904,7 @@ can be accessed from any REST client, i. e.:
==== ====
A special case is to bind an endpoint without a view name. This is A special case is to bind an endpoint without a view name. This is
particularly useful for DELETE requests: particularly useful for `DELETE` requests:
[source,java] [source,java]
---- ----

View File

@@ -60,7 +60,7 @@ Index
... How to read stats from the JVM ... How to read stats from the JVM
.. High availability .. High availability
.. Replication .. Replication
.. Plugins .. link:https://gerrit-review.googlesource.com/#/admin/projects/?filter=plugins%252F[Plugins]
.. link:dev-design.html[System Design] .. link:dev-design.html[System Design]
.. link:config-contact.html[User Contact Information] .. link:config-contact.html[User Contact Information]
.. link:config-reverseproxy.html[Reverse Proxy] .. link:config-reverseproxy.html[Reverse Proxy]

View File

@@ -31,6 +31,9 @@ import static com.google.gerrit.common.changes.ListChangesOption.REVIEWED;
import com.google.common.base.Joiner; import com.google.common.base.Joiner;
import com.google.common.base.Objects; import com.google.common.base.Objects;
import com.google.common.cache.CacheBuilder;
import com.google.common.cache.CacheLoader;
import com.google.common.cache.LoadingCache;
import com.google.common.collect.HashBasedTable; import com.google.common.collect.HashBasedTable;
import com.google.common.collect.HashMultimap; import com.google.common.collect.HashMultimap;
import com.google.common.collect.ImmutableList; import com.google.common.collect.ImmutableList;
@@ -64,6 +67,7 @@ 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.PatchSetInfo; import com.google.gerrit.reviewdb.client.PatchSetInfo;
import com.google.gerrit.reviewdb.client.PatchSetInfo.ParentInfo; import com.google.gerrit.reviewdb.client.PatchSetInfo.ParentInfo;
import com.google.gerrit.reviewdb.client.Project;
import com.google.gerrit.reviewdb.client.UserIdentity; import com.google.gerrit.reviewdb.client.UserIdentity;
import com.google.gerrit.reviewdb.server.ReviewDb; import com.google.gerrit.reviewdb.server.ReviewDb;
import com.google.gerrit.server.AnonymousUser; import com.google.gerrit.server.AnonymousUser;
@@ -77,7 +81,8 @@ import com.google.gerrit.server.patch.PatchListNotAvailableException;
import com.google.gerrit.server.patch.PatchSetInfoFactory; import com.google.gerrit.server.patch.PatchSetInfoFactory;
import com.google.gerrit.server.patch.PatchSetInfoNotAvailableException; import com.google.gerrit.server.patch.PatchSetInfoNotAvailableException;
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.NoSuchProjectException;
import com.google.gerrit.server.project.ProjectControl;
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;
import com.google.gwtorm.server.ResultSet; import com.google.gwtorm.server.ResultSet;
@@ -87,6 +92,7 @@ import com.google.inject.Provider;
import org.slf4j.Logger; import org.slf4j.Logger;
import org.slf4j.LoggerFactory; import org.slf4j.LoggerFactory;
import java.io.IOException;
import java.sql.Timestamp; import java.sql.Timestamp;
import java.util.Collection; import java.util.Collection;
import java.util.Collections; import java.util.Collections;
@@ -97,6 +103,7 @@ import java.util.List;
import java.util.Map; import java.util.Map;
import java.util.Set; import java.util.Set;
import java.util.TreeMap; import java.util.TreeMap;
import java.util.concurrent.ExecutionException;
public class ChangeJson { public class ChangeJson {
private static final Logger log = LoggerFactory.getLogger(ChangeJson.class); private static final Logger log = LoggerFactory.getLogger(ChangeJson.class);
@@ -122,7 +129,7 @@ public class ChangeJson {
private final Provider<CurrentUser> userProvider; private final Provider<CurrentUser> userProvider;
private final AnonymousUser anonymous; private final AnonymousUser anonymous;
private final IdentifiedUser.GenericFactory userFactory; private final IdentifiedUser.GenericFactory userFactory;
private final ChangeControl.GenericFactory changeControlGenericFactory; private final ProjectControl.GenericFactory projectControlFactory;
private final PatchSetInfoFactory patchSetInfoFactory; private final PatchSetInfoFactory patchSetInfoFactory;
private final FileInfoJson fileInfoJson; private final FileInfoJson fileInfoJson;
private final AccountInfo.Loader.Factory accountLoaderFactory; private final AccountInfo.Loader.Factory accountLoaderFactory;
@@ -131,20 +138,20 @@ public class ChangeJson {
private final DynamicMap<RestView<ChangeResource>> changes; private final DynamicMap<RestView<ChangeResource>> changes;
private final Revisions revisions; private final Revisions revisions;
private ChangeControl.Factory changeControlUserFactory;
private EnumSet<ListChangesOption> options; private EnumSet<ListChangesOption> options;
private AccountInfo.Loader accountLoader; private AccountInfo.Loader accountLoader;
private ChangeControl lastControl; private ChangeControl lastControl;
private Set<Change.Id> reviewed; private Set<Change.Id> reviewed;
private LoadingCache<Project.NameKey, ProjectControl> projectControls;
@Inject @Inject
ChangeJson( ChangeJson(
Provider<ReviewDb> db, Provider<ReviewDb> db,
LabelNormalizer ln, LabelNormalizer ln,
Provider<CurrentUser> userProvider, Provider<CurrentUser> user,
AnonymousUser au, AnonymousUser au,
IdentifiedUser.GenericFactory uf, IdentifiedUser.GenericFactory uf,
ChangeControl.GenericFactory ccf, ProjectControl.GenericFactory pcf,
PatchSetInfoFactory psi, PatchSetInfoFactory psi,
FileInfoJson fileInfoJson, FileInfoJson fileInfoJson,
AccountInfo.Loader.Factory ailf, AccountInfo.Loader.Factory ailf,
@@ -154,10 +161,10 @@ public class ChangeJson {
Revisions revisions) { Revisions revisions) {
this.db = db; this.db = db;
this.labelNormalizer = ln; this.labelNormalizer = ln;
this.userProvider = userProvider; this.userProvider = user;
this.anonymous = au; this.anonymous = au;
this.userFactory = uf; this.userFactory = uf;
this.changeControlGenericFactory = ccf; this.projectControlFactory = pcf;
this.patchSetInfoFactory = psi; this.patchSetInfoFactory = psi;
this.fileInfoJson = fileInfoJson; this.fileInfoJson = fileInfoJson;
this.accountLoaderFactory = ailf; this.accountLoaderFactory = ailf;
@@ -167,6 +174,15 @@ public class ChangeJson {
this.revisions = revisions; this.revisions = revisions;
options = EnumSet.noneOf(ListChangesOption.class); options = EnumSet.noneOf(ListChangesOption.class);
projectControls = CacheBuilder.newBuilder()
.concurrencyLevel(1)
.build(new CacheLoader<Project.NameKey, ProjectControl>() {
@Override
public ProjectControl load(Project.NameKey key)
throws NoSuchProjectException, IOException {
return projectControlFactory.controlFor(key, userProvider.get());
}
});
} }
public ChangeJson addOption(ListChangesOption o) { public ChangeJson addOption(ListChangesOption o) {
@@ -179,11 +195,6 @@ public class ChangeJson {
return this; return this;
} }
public ChangeJson setChangeControlFactory(ChangeControl.Factory cf) {
changeControlUserFactory = cf;
return this;
}
public ChangeInfo format(ChangeResource rsrc) throws OrmException { public ChangeInfo format(ChangeResource rsrc) throws OrmException {
return format(new ChangeData(rsrc.getControl())); return format(new ChangeData(rsrc.getControl()));
} }
@@ -321,13 +332,12 @@ public class ChangeJson {
} }
try { try {
if (changeControlUserFactory != null) { Change change = cd.change(db);
ctrl = changeControlUserFactory.controlFor(cd.change(db)); if (change == null) {
} else { return null;
ctrl = changeControlGenericFactory.controlFor(cd.change(db),
userProvider.get());
} }
} catch (NoSuchChangeException e) { ctrl = projectControls.get(change.getProject()).controlFor(change);
} catch (ExecutionException e) {
return null; return null;
} }
lastControl = ctrl; lastControl = ctrl;

View File

@@ -23,6 +23,7 @@ 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.CurrentUser;
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.QueryChanges; import com.google.gerrit.server.query.change.QueryChanges;
@@ -37,17 +38,20 @@ import java.util.List;
public class ChangesCollection implements public class ChangesCollection implements
RestCollection<TopLevelResource, ChangeResource> { RestCollection<TopLevelResource, ChangeResource> {
private final Provider<ReviewDb> db; private final Provider<ReviewDb> db;
private final ChangeControl.Factory changeControlFactory; 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;
@Inject @Inject
ChangesCollection( ChangesCollection(
Provider<ReviewDb> dbProvider, Provider<ReviewDb> dbProvider,
ChangeControl.Factory changeControlFactory, Provider<CurrentUser> user,
ChangeControl.GenericFactory changeControlFactory,
Provider<QueryChanges> queryFactory, Provider<QueryChanges> queryFactory,
DynamicMap<RestView<ChangeResource>> views) { DynamicMap<RestView<ChangeResource>> views) {
this.db = dbProvider; this.db = dbProvider;
this.user = user;
this.changeControlFactory = changeControlFactory; this.changeControlFactory = changeControlFactory;
this.queryFactory = queryFactory; this.queryFactory = queryFactory;
this.views = views; this.views = views;
@@ -74,7 +78,7 @@ public class ChangesCollection implements
ChangeControl control; ChangeControl control;
try { try {
control = changeControlFactory.validateFor(changes.get(0)); control = changeControlFactory.validateFor(changes.get(0), user.get());
} catch (NoSuchChangeException e) { } catch (NoSuchChangeException e) {
throw new ResourceNotFoundException(id); throw new ResourceNotFoundException(id);
} }

View File

@@ -37,7 +37,6 @@ import com.google.gerrit.server.change.FileInfoJson.FileInfo;
import com.google.gerrit.server.git.GitRepositoryManager; import com.google.gerrit.server.git.GitRepositoryManager;
import com.google.gerrit.server.patch.PatchList; import com.google.gerrit.server.patch.PatchList;
import com.google.gerrit.server.patch.PatchListCache; import com.google.gerrit.server.patch.PatchListCache;
import com.google.gerrit.server.patch.PatchListEntry;
import com.google.gerrit.server.patch.PatchListNotAvailableException; import com.google.gerrit.server.patch.PatchListNotAvailableException;
import com.google.gwtorm.server.OrmException; import com.google.gwtorm.server.OrmException;
import com.google.inject.Inject; import com.google.inject.Inject;
@@ -45,9 +44,9 @@ import com.google.inject.Provider;
import org.eclipse.jgit.lib.ObjectReader; import org.eclipse.jgit.lib.ObjectReader;
import org.eclipse.jgit.lib.Repository; import org.eclipse.jgit.lib.Repository;
import org.eclipse.jgit.revwalk.RevTree;
import org.eclipse.jgit.revwalk.RevWalk; import org.eclipse.jgit.revwalk.RevWalk;
import org.eclipse.jgit.treewalk.TreeWalk; import org.eclipse.jgit.treewalk.TreeWalk;
import org.eclipse.jgit.treewalk.filter.PathFilterGroup;
import org.kohsuke.args4j.Option; import org.kohsuke.args4j.Option;
import org.slf4j.Logger; import org.slf4j.Logger;
import org.slf4j.LoggerFactory; import org.slf4j.LoggerFactory;
@@ -219,23 +218,49 @@ class Files implements ChildCollection<RevisionResource, FileResource> {
List<String> pathList = Lists.newArrayListWithCapacity(sz); List<String> pathList = Lists.newArrayListWithCapacity(sz);
RevWalk rw = new RevWalk(reader); RevWalk rw = new RevWalk(reader);
RevTree o = rw.parseCommit(oldList.getNewId()).getTree(); TreeWalk tw = new TreeWalk(reader);
RevTree c = rw.parseCommit(curList.getNewId()).getTree(); tw.setFilter(PathFilterGroup.createFromStrings(paths));
for (PatchListEntry p : curList.getPatches()) { tw.setRecursive(true);
String path = p.getNewName(); int o = tw.addTree(rw.parseCommit(oldList.getNewId()).getTree());
if (!Patch.COMMIT_MSG.equals(path) && paths.contains(path)) { int c = tw.addTree(rw.parseCommit(curList.getNewId()).getTree());
TreeWalk tw = TreeWalk.forPath(reader, path, o, c);
if (tw != null int op = -1;
&& tw.getRawMode(0) != 0 if (oldList.getOldId() != null) {
&& tw.getRawMode(1) != 0 op = tw.addTree(rw.parseCommit(oldList.getOldId()).getTree());
&& tw.idEqual(0, 1)) { }
inserts.add(new AccountPatchReview(
new Patch.Key( int cp = -1;
resource.getPatchSet().getId(), if (curList.getOldId() != null) {
path), cp = tw.addTree(rw.parseCommit(curList.getOldId()).getTree());
userId)); }
pathList.add(path);
} while (tw.next()) {
String path = tw.getPathString();
if (tw.getRawMode(o) != 0 && tw.getRawMode(c) != 0
&& tw.idEqual(o, c)
&& paths.contains(path)) {
// File exists in previously reviewed oldList and in curList.
// File content is identical.
inserts.add(new AccountPatchReview(
new Patch.Key(
resource.getPatchSet().getId(),
path),
userId));
pathList.add(path);
} else if (op >= 0 && cp >= 0
&& tw.getRawMode(o) == 0 && tw.getRawMode(c) == 0
&& tw.getRawMode(op) != 0 && tw.getRawMode(cp) != 0
&& tw.idEqual(op, cp)
&& paths.contains(path)) {
// File was deleted in previously reviewed oldList and curList.
// File exists in ancestor of oldList and curList.
// File content is identical in ancestors.
inserts.add(new AccountPatchReview(
new Patch.Key(
resource.getPatchSet().getId(),
path),
userId));
pathList.add(path);
} }
} }
db.get().accountPatchReviews().insert(inserts); db.get().accountPatchReviews().insert(inserts);

View File

@@ -31,6 +31,7 @@ import com.google.gerrit.server.config.FactoryModule;
public class Module extends RestApiModule { public class Module extends RestApiModule {
@Override @Override
protected void configure() { protected void configure() {
bind(ChangesCollection.class);
bind(Revisions.class); bind(Revisions.class);
bind(Reviewers.class); bind(Reviewers.class);
bind(Drafts.class); bind(Drafts.class);

View File

@@ -94,6 +94,15 @@ public class ChangeControl {
return controlFor(change, user); return controlFor(change, user);
} }
public ChangeControl validateFor(Change change, CurrentUser user)
throws NoSuchChangeException, OrmException {
ChangeControl c = controlFor(change, user);
if (!c.isVisible(db.get())) {
throw new NoSuchChangeException(c.getChange().getId());
}
return c;
}
public ChangeControl validateFor(Change.Id id, CurrentUser user) public ChangeControl validateFor(Change.Id id, CurrentUser user)
throws NoSuchChangeException, OrmException { throws NoSuchChangeException, OrmException {
ChangeControl c = controlFor(id, user); ChangeControl c = controlFor(id, user);

View File

@@ -24,7 +24,6 @@ import com.google.gerrit.server.CurrentUser;
import com.google.gerrit.server.IdentifiedUser; import com.google.gerrit.server.IdentifiedUser;
import com.google.gerrit.server.change.ChangeJson; import com.google.gerrit.server.change.ChangeJson;
import com.google.gerrit.server.change.ChangeJson.ChangeInfo; import com.google.gerrit.server.change.ChangeJson.ChangeInfo;
import com.google.gerrit.server.project.ChangeControl;
import com.google.gerrit.server.query.QueryParseException; import com.google.gerrit.server.query.QueryParseException;
import com.google.gwtorm.server.OrmException; import com.google.gwtorm.server.OrmException;
import com.google.inject.Inject; import com.google.inject.Inject;
@@ -82,16 +81,12 @@ public class QueryChanges implements RestReadView<TopLevelResource> {
} }
@Inject @Inject
QueryChanges(ChangeJson json, QueryChanges(ChangeJson json, QueryProcessor qp, Provider<CurrentUser> user) {
QueryProcessor qp,
ChangeControl.Factory cf,
Provider<CurrentUser> user) {
this.json = json; this.json = json;
this.imp = qp; this.imp = qp;
this.user = user; this.user = user;
options = EnumSet.noneOf(ListChangesOption.class); options = EnumSet.noneOf(ListChangesOption.class);
json.setChangeControlFactory(cf);
} }
public void addQuery(String query) { public void addQuery(String query) {

View File

@@ -98,7 +98,8 @@ public class QueryProcessor {
private final ChangeQueryRewriter queryRewriter; private final ChangeQueryRewriter queryRewriter;
private final Provider<ReviewDb> db; private final Provider<ReviewDb> db;
private final GitRepositoryManager repoManager; private final GitRepositoryManager repoManager;
private final ChangeControl.Factory changeControlFactory; private final ChangeControl.GenericFactory changeControlFactory;
private final CurrentUser user;
private final int maxLimit; private final int maxLimit;
private OutputFormat outputFormat = OutputFormat.TEXT; private OutputFormat outputFormat = OutputFormat.TEXT;
@@ -124,13 +125,14 @@ public class QueryProcessor {
ChangeQueryBuilder.Factory queryBuilder, CurrentUser currentUser, ChangeQueryBuilder.Factory queryBuilder, CurrentUser currentUser,
ChangeQueryRewriter queryRewriter, Provider<ReviewDb> db, ChangeQueryRewriter queryRewriter, Provider<ReviewDb> db,
GitRepositoryManager repoManager, GitRepositoryManager repoManager,
ChangeControl.Factory changeControlFactory) { ChangeControl.GenericFactory changeControlFactory) {
this.eventFactory = eventFactory; this.eventFactory = eventFactory;
this.queryBuilder = queryBuilder.create(currentUser); this.queryBuilder = queryBuilder.create(currentUser);
this.queryRewriter = queryRewriter; this.queryRewriter = queryRewriter;
this.db = db; this.db = db;
this.repoManager = repoManager; this.repoManager = repoManager;
this.changeControlFactory = changeControlFactory; this.changeControlFactory = changeControlFactory;
this.user = currentUser;
this.maxLimit = currentUser.getCapabilities() this.maxLimit = currentUser.getCapabilities()
.getRange(GlobalCapability.QUERY_LIMIT) .getRange(GlobalCapability.QUERY_LIMIT)
.getMax(); .getMax();
@@ -303,8 +305,11 @@ public class QueryProcessor {
List<ChangeData> results = queryChanges(queryString); List<ChangeData> results = queryChanges(queryString);
ChangeAttribute c = null; ChangeAttribute c = null;
for (ChangeData d : results) { for (ChangeData d : results) {
LabelTypes labelTypes = changeControlFactory.controlFor(d.getChange()) ChangeControl cc = d.changeControl();
.getLabelTypes(); if (cc == null || cc.getCurrentUser() != user) {
cc = changeControlFactory.controlFor(d.change(db), user);
}
LabelTypes labelTypes = cc.getLabelTypes();
c = eventFactory.asChangeAttribute(d.getChange()); c = eventFactory.asChangeAttribute(d.getChange());
eventFactory.extend(c, d.getChange()); eventFactory.extend(c, d.getChange());
eventFactory.addTrackingIds(c, d.trackingIds(db)); eventFactory.addTrackingIds(c, d.trackingIds(db));
@@ -316,7 +321,7 @@ public class QueryProcessor {
if (includeSubmitRecords) { if (includeSubmitRecords) {
PatchSet.Id psId = d.getChange().currentPatchSetId(); PatchSet.Id psId = d.getChange().currentPatchSetId();
PatchSet patchSet = db.get().patchSets().get(psId); PatchSet patchSet = db.get().patchSets().get(psId);
List<SubmitRecord> submitResult = d.changeControl().canSubmit( // List<SubmitRecord> submitResult = cc.canSubmit( //
db.get(), patchSet, null, false, true, true); db.get(), patchSet, null, false, true, true);
eventFactory.addSubmitRecords(c, submitResult); eventFactory.addSubmitRecords(c, submitResult);
} }