Simplify patch display to a single RPC

A long time ago I thought it might make sense to make the RPCs for
patch display two parts.  The first part was a static patchScript
that only returns the file content, and thus could be infinitely
cacheable on edge proxies because the content never changes.
The second part was supposed to be a dynamic comment list, showing
the current comments in the file.

This didn't really work out.

The static patchScript code actually had to know what comments
existed at display time, in order to ensure sufficient context
lines were packaged for the client.  I also never got around to
teaching gwtjsonrpc how to perform cached GET requests.  Even if
we did, access control rules within a project could change the READ
permission from being public readable to being private, which would
mean edge proxies might still had that private data.

As it turns out, we can simplify the entire code base by putting
the two together as a single RPC.  We no longer need to perform an
RPC join in order to display the result in PatchScreen, and we can
cut in half the number of database queries required, as we used to
be doing the comment loading work twice per screen display.

Change-Id: Ic1a129ff507da0bbe97ca03ce31c566981ed3855
Signed-off-by: Shawn O. Pearce <sop@google.com>
This commit is contained in:
Shawn O. Pearce 2010-02-23 18:45:33 -08:00
parent 3c7c33d01a
commit 31e7c6d4d8
9 changed files with 136 additions and 283 deletions

View File

@ -14,7 +14,6 @@
package com.google.gerrit.common.data;
import com.google.gerrit.reviewdb.Patch;
import com.google.gerrit.reviewdb.PatchLineComment;
import com.google.gerrit.reviewdb.PatchSet;
@ -25,9 +24,8 @@ import java.util.List;
import java.util.Map;
public class CommentDetail {
protected List<PatchLineComment> commentsA;
protected List<PatchLineComment> commentsB;
protected List<Patch> history;
protected List<PatchLineComment> a;
protected List<PatchLineComment> b;
protected AccountInfoCache accounts;
private transient PatchSet.Id idA;
@ -35,12 +33,11 @@ public class CommentDetail {
private transient Map<Integer, List<PatchLineComment>> forA;
private transient Map<Integer, List<PatchLineComment>> forB;
public CommentDetail(final PatchSet.Id a, final PatchSet.Id b) {
commentsA = new ArrayList<PatchLineComment>();
commentsB = new ArrayList<PatchLineComment>();
idA = a;
idB = b;
public CommentDetail(final PatchSet.Id idA, final PatchSet.Id idB) {
this.a = new ArrayList<PatchLineComment>();
this.b = new ArrayList<PatchLineComment>();
this.idA = idA;
this.idB = idB;
}
protected CommentDetail() {
@ -51,19 +48,19 @@ public class CommentDetail {
switch (p.getSide()) {
case 0:
if (idA == null && idB.equals(psId)) {
commentsA.add(p);
a.add(p);
return true;
}
break;
case 1:
if (idA != null && idA.equals(psId)) {
commentsA.add(p);
a.add(p);
return true;
}
if (idB.equals(psId)) {
commentsB.add(p);
b.add(p);
return true;
}
break;
@ -75,28 +72,20 @@ public class CommentDetail {
accounts = a;
}
public void setHistory(final List<Patch> h) {
history = h;
}
public AccountInfoCache getAccounts() {
return accounts;
}
public List<Patch> getHistory() {
return history;
}
public List<PatchLineComment> getCommentsA() {
return commentsA;
return a;
}
public List<PatchLineComment> getCommentsB() {
return commentsB;
return b;
}
public boolean isEmpty() {
return commentsA.isEmpty() && commentsB.isEmpty();
return a.isEmpty() && b.isEmpty();
}
public List<PatchLineComment> getForA(final int lineNbr) {
@ -104,7 +93,7 @@ public class CommentDetail {
return Collections.emptyList();
}
if (forA == null) {
forA = index(commentsA);
forA = index(a);
}
return get(forA, lineNbr);
}
@ -114,7 +103,7 @@ public class CommentDetail {
return Collections.emptyList();
}
if (forB == null) {
forB = index(commentsB);
forB = index(b);
}
return get(forB, lineNbr);
}

View File

@ -36,9 +36,6 @@ public interface PatchDetailService extends RemoteJsonService {
void patchScript(Patch.Key key, PatchSet.Id a, PatchSet.Id b,
PatchScriptSettings settings, AsyncCallback<PatchScript> callback);
void patchComments(Patch.Key key, PatchSet.Id a, PatchSet.Id b,
AsyncCallback<CommentDetail> callback);
@SignInRequired
void saveDraft(PatchLineComment comment,
AsyncCallback<PatchLineComment> callback);

View File

@ -22,6 +22,7 @@ import com.google.gerrit.prettify.common.PrettySettings;
import com.google.gerrit.prettify.common.SparseFileContent;
import com.google.gerrit.prettify.common.SparseHtmlFile;
import com.google.gerrit.reviewdb.Change;
import com.google.gerrit.reviewdb.Patch;
import org.eclipse.jgit.diff.Edit;
@ -40,11 +41,13 @@ public class PatchScript {
protected List<Edit> edits;
protected DisplayMethod displayMethodA;
protected DisplayMethod displayMethodB;
protected CommentDetail comments;
protected List<Patch> history;
public PatchScript(final Change.Key ck, final List<String> h,
final PatchScriptSettings s, final SparseFileContent ca,
final SparseFileContent cb, final List<Edit> e, final DisplayMethod ma,
final DisplayMethod mb) {
final DisplayMethod mb, final CommentDetail cd, final List<Patch> hist) {
changeId = ck;
header = h;
settings = s;
@ -53,6 +56,8 @@ public class PatchScript {
edits = e;
displayMethodA = ma;
displayMethodB = mb;
comments = cd;
history = hist;
}
protected PatchScript() {
@ -74,6 +79,14 @@ public class PatchScript {
return header;
}
public CommentDetail getCommentDetail() {
return comments;
}
public List<Patch> getHistory() {
return history;
}
public int getContext() {
return settings.getContext();
}

View File

@ -23,11 +23,11 @@ import com.google.gerrit.client.changes.ChangeScreen;
import com.google.gerrit.client.changes.PatchTable;
import com.google.gerrit.client.changes.Util;
import com.google.gerrit.client.rpc.GerritCallback;
import com.google.gerrit.client.rpc.ScreenLoadCallback;
import com.google.gerrit.client.ui.ChangeLink;
import com.google.gerrit.client.ui.InlineHyperlink;
import com.google.gerrit.client.ui.Screen;
import com.google.gerrit.common.PageLinks;
import com.google.gerrit.common.data.CommentDetail;
import com.google.gerrit.common.data.PatchScript;
import com.google.gerrit.common.data.PatchScriptSettings;
import com.google.gerrit.common.data.PatchSetDetail;
@ -138,8 +138,6 @@ public abstract class PatchScreen extends Screen {
private AbstractPatchContentTable contentTable;
private int rpcSequence;
private PatchScript script;
private CommentDetail comments;
/** The index of the file we are currently looking at among the fileList */
private int patchIndex;
@ -405,15 +403,12 @@ public abstract class PatchScreen extends Screen {
protected void refresh(final boolean isFirst) {
final int rpcseq = ++rpcSequence;
script = null;
comments = null;
PatchUtil.DETAIL_SVC.patchScript(patchKey, idSideA, idSideB,
scriptSettings, new GerritCallback<PatchScript>() {
public void onSuccess(final PatchScript result) {
scriptSettings, new ScreenLoadCallback<PatchScript>(this) {
@Override
protected void preDisplay(final PatchScript result) {
if (rpcSequence == rpcseq) {
script = result;
onResult(isFirst);
onResult(result, isFirst);
}
}
@ -424,83 +419,54 @@ public abstract class PatchScreen extends Screen {
}
}
});
PatchUtil.DETAIL_SVC.patchComments(patchKey, idSideA, idSideB,
new GerritCallback<CommentDetail>() {
public void onSuccess(final CommentDetail result) {
if (rpcSequence == rpcseq) {
comments = result;
onResult(isFirst);
}
}
@Override
public void onFailure(Throwable caught) {
// Ignore no such entity, the patch script RPC above would
// also notice the problem and report it.
//
if (!isNoSuchEntity(caught) && rpcSequence == rpcseq) {
super.onFailure(caught);
}
}
});
}
private void onResult(final boolean isFirst) {
if (script != null && comments != null) {
final Change.Key cid = script.getChangeId();
final String path = patchKey.get();
String fileName = path;
final int last = fileName.lastIndexOf('/');
if (last >= 0) {
fileName = fileName.substring(last + 1);
}
private void onResult(final PatchScript script, final boolean isFirst) {
final Change.Key cid = script.getChangeId();
final String path = patchKey.get();
String fileName = path;
final int last = fileName.lastIndexOf('/');
if (last >= 0) {
fileName = fileName.substring(last + 1);
}
setWindowTitle(PatchUtil.M.patchWindowTitle(cid.abbreviate(), fileName));
setPageTitle(PatchUtil.M.patchPageTitle(cid.abbreviate(), path));
setWindowTitle(PatchUtil.M.patchWindowTitle(cid.abbreviate(), fileName));
setPageTitle(PatchUtil.M.patchPageTitle(cid.abbreviate(), path));
historyTable.display(comments.getHistory());
historyPanel.setVisible(true);
historyTable.display(script.getHistory());
historyPanel.setVisible(true);
// True if there are differences between the two patch sets
boolean hasEdits = !script.getEdits().isEmpty();
// True if this change is a mode change or a pure rename/copy
boolean hasMeta = !script.getPatchHeader().isEmpty();
// True if there are differences between the two patch sets
boolean hasEdits = !script.getEdits().isEmpty();
// True if this change is a mode change or a pure rename/copy
boolean hasMeta = !script.getPatchHeader().isEmpty();
boolean hasDifferences = hasEdits || hasMeta;
boolean pureMetaChange = !hasEdits && hasMeta;
boolean hasDifferences = hasEdits || hasMeta;
boolean pureMetaChange = !hasEdits && hasMeta;
if (contentTable instanceof SideBySideTable && pureMetaChange) {
// User asked for SideBySide (or a link guessed, wrong) and we can't
// show a binary or pure-rename change there accurately. Switch to
// the unified view instead.
//
contentTable.removeFromParent();
contentTable = new UnifiedDiffTable();
contentTable.fileList = fileList;
contentPanel.add(contentTable);
setToken(Dispatcher.toPatchUnified(patchKey));
}
if (contentTable instanceof SideBySideTable && pureMetaChange) {
// User asked for SideBySide (or a link guessed, wrong) and we can't
// show a binary or pure-rename change there accurately. Switch to
// the unified view instead.
//
contentTable.removeFromParent();
contentTable = new UnifiedDiffTable();
contentTable.fileList = fileList;
contentPanel.add(contentTable);
setToken(Dispatcher.toPatchUnified(patchKey));
}
if (hasDifferences) {
contentTable.display(patchKey, idSideA, idSideB, script);
contentTable.display(comments);
contentTable.finishDisplay();
}
showPatch(hasDifferences);
if (hasDifferences) {
contentTable.display(patchKey, idSideA, idSideB, script);
contentTable.display(script.getCommentDetail());
contentTable.finishDisplay();
}
showPatch(hasDifferences);
script = null;
comments = null;
// Mark this file reviewed as soon we display the diff screen
if (Gerrit.isSignedIn() && isFirst) {
reviewedFlag.setValue(true);
setReviewedByCurrentUser(true /* reviewed */);
}
if (!isCurrentView()) {
display();
}
// Mark this file reviewed as soon we display the diff screen
if (Gerrit.isSignedIn() && isFirst) {
reviewedFlag.setValue(true);
setReviewedByCurrentUser(true /* reviewed */);
}
}

View File

@ -1,135 +0,0 @@
// Copyright (C) 2009 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.httpd.rpc.patch;
import com.google.gerrit.common.data.CommentDetail;
import com.google.gerrit.httpd.rpc.Handler;
import com.google.gerrit.reviewdb.Account;
import com.google.gerrit.reviewdb.Change;
import com.google.gerrit.reviewdb.Patch;
import com.google.gerrit.reviewdb.PatchLineComment;
import com.google.gerrit.reviewdb.PatchSet;
import com.google.gerrit.reviewdb.ReviewDb;
import com.google.gerrit.server.CurrentUser;
import com.google.gerrit.server.IdentifiedUser;
import com.google.gerrit.server.account.AccountInfoCacheFactory;
import com.google.gerrit.server.project.ChangeControl;
import com.google.gerrit.server.project.NoSuchChangeException;
import com.google.gwtorm.client.OrmException;
import com.google.inject.Inject;
import com.google.inject.assistedinject.Assisted;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import javax.annotation.Nullable;
class CommentDetailFactory extends Handler<CommentDetail> {
interface Factory {
CommentDetailFactory create(Patch.Key patchKey,
@Assisted("patchSetA") PatchSet.Id patchSetA,
@Assisted("patchSetB") PatchSet.Id patchSetB);
}
private final ReviewDb db;
private final ChangeControl.Factory changeControlFactory;
private final AccountInfoCacheFactory aic;
private final Patch.Key patchKey;
private final PatchSet.Id psa;
private final PatchSet.Id psb;
private final PatchSet.Id patchSetId;
private final Change.Id changeId;
@Inject
CommentDetailFactory(final ReviewDb db,
final ChangeControl.Factory changeControlFactory,
final AccountInfoCacheFactory.Factory accountInfoCacheFactory,
@Assisted final Patch.Key patchKey,
@Assisted("patchSetA") @Nullable final PatchSet.Id patchSetA,
@Assisted("patchSetB") final PatchSet.Id patchSetB) {
this.db = db;
this.changeControlFactory = changeControlFactory;
this.aic = accountInfoCacheFactory.create();
this.patchKey = patchKey;
this.psa = patchSetA;
this.psb = patchSetB;
patchSetId = patchKey.getParentKey();
changeId = patchSetId.getParentKey();
}
@Override
public CommentDetail call() throws OrmException, NoSuchChangeException {
validatePatchSetId(psa);
validatePatchSetId(psb);
final ChangeControl control = changeControlFactory.validateFor(changeId);
final String pn = patchKey.getFileName();
final CommentDetail r = new CommentDetail(psa, psb);
final List<Patch> historyList = new ArrayList<Patch>();
final Map<PatchSet.Id, Patch> bySet = new HashMap<PatchSet.Id, Patch>();
for (final PatchSet ps : db.patchSets().byChange(changeId)) {
final Patch p = new Patch(new Patch.Key(ps.getId(), pn));
historyList.add(p);
bySet.put(ps.getId(), p);
}
for (PatchLineComment c : db.patchComments().published(changeId, pn)) {
if (r.include(c)) {
aic.want(c.getAuthor());
}
final PatchSet.Id psId = c.getKey().getParentKey().getParentKey();
final Patch patch = bySet.get(psId);
if (patch != null) {
patch.setCommentCount(patch.getCommentCount() + 1);
}
}
final CurrentUser user = control.getCurrentUser();
if (user instanceof IdentifiedUser) {
final Account.Id me = ((IdentifiedUser) user).getAccountId();
for (PatchLineComment c : db.patchComments().draft(changeId, pn, me)) {
if (r.include(c)) {
aic.want(me);
}
final PatchSet.Id psId = c.getKey().getParentKey().getParentKey();
final Patch patch = bySet.get(psId);
if (patch != null) {
patch.setDraftCount(patch.getDraftCount() + 1);
}
}
}
r.setHistory(historyList);
r.setAccountInfoCache(aic.create());
return r;
}
private void validatePatchSetId(final PatchSet.Id psId)
throws NoSuchChangeException {
if (psId == null) { // OK, means use base;
} else if (changeId.equals(psId.getParentKey())) { // OK, same change;
} else {
throw new NoSuchChangeException(changeId);
}
}
}

View File

@ -18,7 +18,6 @@ import com.google.gerrit.common.data.AddReviewerResult;
import com.google.gerrit.common.data.ApprovalSummary;
import com.google.gerrit.common.data.ApprovalSummarySet;
import com.google.gerrit.common.data.ApprovalTypes;
import com.google.gerrit.common.data.CommentDetail;
import com.google.gerrit.common.data.PatchDetailService;
import com.google.gerrit.common.data.PatchScript;
import com.google.gerrit.common.data.PatchScriptSettings;
@ -61,7 +60,6 @@ class PatchDetailServiceImpl extends BaseServiceImplementation implements
private final AccountInfoCacheFactory.Factory accountInfoCacheFactory;
private final AddReviewer.Factory addReviewerFactory;
private final ChangeControl.Factory changeControlFactory;
private final CommentDetailFactory.Factory commentDetailFactory;
private final FunctionState.Factory functionStateFactory;
private final PublishComments.Factory publishCommentsFactory;
private final PatchScriptFactory.Factory patchScriptFactoryFactory;
@ -74,7 +72,6 @@ class PatchDetailServiceImpl extends BaseServiceImplementation implements
final AccountInfoCacheFactory.Factory accountInfoCacheFactory,
final AddReviewer.Factory addReviewerFactory,
final ChangeControl.Factory changeControlFactory,
final CommentDetailFactory.Factory commentDetailFactory,
final FunctionState.Factory functionStateFactory,
final PatchScriptFactory.Factory patchScriptFactoryFactory,
final PublishComments.Factory publishCommentsFactory,
@ -85,7 +82,6 @@ class PatchDetailServiceImpl extends BaseServiceImplementation implements
this.accountInfoCacheFactory = accountInfoCacheFactory;
this.addReviewerFactory = addReviewerFactory;
this.changeControlFactory = changeControlFactory;
this.commentDetailFactory = commentDetailFactory;
this.functionStateFactory = functionStateFactory;
this.patchScriptFactoryFactory = patchScriptFactoryFactory;
this.publishCommentsFactory = publishCommentsFactory;
@ -102,15 +98,6 @@ class PatchDetailServiceImpl extends BaseServiceImplementation implements
patchScriptFactoryFactory.create(patchKey, psa, psb, s).to(callback);
}
public void patchComments(final Patch.Key patchKey, final PatchSet.Id psa,
final PatchSet.Id psb, final AsyncCallback<CommentDetail> callback) {
if (psb == null) {
callback.onFailure(new NoSuchEntityException());
return;
}
commentDetailFactory.create(patchKey, psa, psb).to(callback);
}
public void saveDraft(final PatchLineComment comment,
final AsyncCallback<PatchLineComment> callback) {
saveDraftFactory.create(comment).to(callback);

View File

@ -29,7 +29,6 @@ public class PatchModule extends RpcServletModule {
@Override
protected void configure() {
factory(AddReviewer.Factory.class);
factory(CommentDetailFactory.Factory.class);
factory(PatchScriptFactory.Factory.class);
factory(SaveDraft.Factory.class);
}

View File

@ -22,6 +22,7 @@ import com.google.gerrit.common.data.PatchScriptSettings.Whitespace;
import com.google.gerrit.prettify.common.EditList;
import com.google.gerrit.prettify.common.SparseFileContent;
import com.google.gerrit.reviewdb.Change;
import com.google.gerrit.reviewdb.Patch;
import com.google.gerrit.reviewdb.PatchLineComment;
import com.google.gerrit.reviewdb.Patch.PatchType;
import com.google.gerrit.server.FileTypeRegistry;
@ -103,14 +104,15 @@ class PatchScriptBuilder {
}
PatchScript toPatchScript(final PatchListEntry content,
final CommentDetail comments) throws IOException {
final CommentDetail comments, final List<Patch> history)
throws IOException {
if (content.getPatchType() == PatchType.N_WAY) {
// For a diff --cc format we don't support converting it into
// a patch script. Instead treat everything as a file header.
//
return new PatchScript(change.getKey(), content.getHeaderLines(),
settings, a.dst, b.dst, Collections.<Edit> emptyList(),
a.displayMethod, b.displayMethod);
a.displayMethod, b.displayMethod, comments, history);
}
a.path = oldName(content);
@ -157,7 +159,7 @@ class PatchScriptBuilder {
}
return new PatchScript(change.getKey(), header, settings, a.dst, b.dst,
edits, a.displayMethod, b.displayMethod);
edits, a.displayMethod, b.displayMethod, comments, history);
}
private static String oldName(final PatchListEntry entry) {

View File

@ -19,6 +19,7 @@ import com.google.gerrit.common.data.PatchScript;
import com.google.gerrit.common.data.PatchScriptSettings;
import com.google.gerrit.common.data.PatchScriptSettings.Whitespace;
import com.google.gerrit.httpd.rpc.Handler;
import com.google.gerrit.reviewdb.Account;
import com.google.gerrit.reviewdb.AccountGeneralPreferences;
import com.google.gerrit.reviewdb.Change;
import com.google.gerrit.reviewdb.Patch;
@ -26,7 +27,9 @@ import com.google.gerrit.reviewdb.PatchLineComment;
import com.google.gerrit.reviewdb.PatchSet;
import com.google.gerrit.reviewdb.Project;
import com.google.gerrit.reviewdb.ReviewDb;
import com.google.gerrit.server.CurrentUser;
import com.google.gerrit.server.IdentifiedUser;
import com.google.gerrit.server.account.AccountInfoCacheFactory;
import com.google.gerrit.server.git.GitRepositoryManager;
import com.google.gerrit.server.patch.PatchList;
import com.google.gerrit.server.patch.PatchListCache;
@ -47,6 +50,10 @@ import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import java.io.IOException;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import javax.annotation.Nullable;
@ -67,6 +74,7 @@ class PatchScriptFactory extends Handler<PatchScript> {
private final PatchListCache patchListCache;
private final SchemaFactory<ReviewDb> schemaFactory;
private final ChangeControl.Factory changeControlFactory;
private final AccountInfoCacheFactory.Factory aicFactory;
private final Patch.Key patchKey;
@Nullable
@ -80,19 +88,18 @@ class PatchScriptFactory extends Handler<PatchScript> {
private Change change;
private PatchSet patchSet;
private Project.NameKey projectKey;
private Repository git;
private ChangeControl control;
private ObjectId aId;
private ObjectId bId;
private List<Patch> history;
private CommentDetail comments;
@Inject
PatchScriptFactory(final GitRepositoryManager grm,
Provider<PatchScriptBuilder> builderFactory,
final PatchListCache patchListCache, final SchemaFactory<ReviewDb> sf,
final ChangeControl.Factory changeControlFactory,
final AccountInfoCacheFactory.Factory aicFactory,
@Assisted final Patch.Key patchKey,
@Assisted("patchSetA") @Nullable final PatchSet.Id patchSetA,
@Assisted("patchSetB") final PatchSet.Id patchSetB,
@ -102,6 +109,7 @@ class PatchScriptFactory extends Handler<PatchScript> {
this.patchListCache = patchListCache;
this.schemaFactory = sf;
this.changeControlFactory = changeControlFactory;
this.aicFactory = aicFactory;
this.patchKey = patchKey;
this.psa = patchSetA;
@ -119,21 +127,21 @@ class PatchScriptFactory extends Handler<PatchScript> {
control = changeControlFactory.validateFor(changeId);
change = control.getChange();
final CommentDetail comments = allComments();
loadMetaData();
final Repository git;
try {
git = repoManager.openRepository(projectKey.get());
} catch (RepositoryNotFoundException e) {
log.error("Repository " + projectKey + " not found", e);
throw new NoSuchChangeException(changeId, e);
}
final String fileName = patchKey.getFileName();
try {
final PatchList list = listFor(keyFor(settings.getWhitespace()));
final PatchScriptBuilder b = newBuilder(list);
final PatchListEntry content = list.get(fileName);
final PatchScriptBuilder b = newBuilder(list, git);
final PatchListEntry content = list.get(patchKey.getFileName());
try {
return b.toPatchScript(content, comments);
return b.toPatchScript(content, comments, history);
} catch (IOException e) {
log.error("File content unavailable", e);
throw new NoSuchChangeException(changeId, e);
@ -151,7 +159,7 @@ class PatchScriptFactory extends Handler<PatchScript> {
return patchListCache.get(key);
}
private PatchScriptBuilder newBuilder(final PatchList list)
private PatchScriptBuilder newBuilder(final PatchList list, Repository git)
throws NoSuchChangeException {
final PatchScriptSettings s = new PatchScriptSettings(settings);
@ -200,11 +208,9 @@ class PatchScriptFactory extends Handler<PatchScript> {
}
}
private CommentDetail allComments()
throws OrmException, NoSuchChangeException {
ReviewDb db = schemaFactory.open();
private void loadMetaData() throws OrmException, NoSuchChangeException {
final ReviewDb db = schemaFactory.open();
try {
final CommentDetail r = new CommentDetail(psa, psb);
patchSet = db.patchSets().get(patchSetId);
if (patchSet == null) {
throw new NoSuchChangeException(changeId);
@ -213,18 +219,47 @@ class PatchScriptFactory extends Handler<PatchScript> {
projectKey = change.getProject();
aId = psa != null ? toObjectId(db, psa) : null;
bId = toObjectId(db, psb);
final String pn = patchKey.get();
for (PatchLineComment p : db.patchComments().published(changeId, pn)) {
r.include(p);
history = new ArrayList<Patch>();
comments = new CommentDetail(psa, psb);
final String file = patchKey.get();
final Map<PatchSet.Id, Patch> bySet = new HashMap<PatchSet.Id, Patch>();
for (final PatchSet ps : db.patchSets().byChange(changeId)) {
final Patch p = new Patch(new Patch.Key(ps.getId(), file));
history.add(p);
bySet.put(ps.getId(), p);
}
if (control.getCurrentUser() instanceof IdentifiedUser) {
for (PatchLineComment p : db.patchComments().draft(changeId, pn,
((IdentifiedUser) control.getCurrentUser()).getAccountId())) {
r.include(p);
final AccountInfoCacheFactory aic = aicFactory.create();
for (PatchLineComment c : db.patchComments().published(changeId, file)) {
if (comments.include(c)) {
aic.want(c.getAuthor());
}
final PatchSet.Id psId = c.getKey().getParentKey().getParentKey();
final Patch p = bySet.get(psId);
if (p != null) {
p.setCommentCount(p.getCommentCount() + 1);
}
}
return r;
final CurrentUser user = control.getCurrentUser();
if (user instanceof IdentifiedUser) {
final Account.Id me = ((IdentifiedUser) user).getAccountId();
for (PatchLineComment c : db.patchComments().draft(changeId, file, me)) {
if (comments.include(c)) {
aic.want(me);
}
final PatchSet.Id psId = c.getKey().getParentKey().getParentKey();
final Patch p = bySet.get(psId);
if (p != null) {
p.setDraftCount(p.getDraftCount() + 1);
}
}
}
comments.setAccountInfoCache(aic.create());
} finally {
db.close();
}