Merge "Support comments option in query command"

This commit is contained in:
Martin Fick 2011-07-29 09:51:19 -07:00 committed by Android Code Review
commit f62e8a7f1d
9 changed files with 150 additions and 19 deletions

View File

@ -12,6 +12,7 @@ SYNOPSIS
[--format {TEXT | JSON}]
[--current-patch-set]
[--patch-sets | --all-approvals]
[--comments]
[--]
<query>
[limit:<n>]
@ -58,6 +59,11 @@ OPTIONS
the --current-patch-set flag then the current patch set
information will be output twice, once in each field.
--comments::
Include comments for all changes. If combined with the
--patch-sets flag then all in-line comments are included for
each patch set.
limit:<n>::
Maximum number of results to return. This is actually a
query operator, and not a command line option. If more

View File

@ -32,6 +32,7 @@ public class ChangeAttribute {
public String sortKey;
public Boolean open;
public Change.Status status;
public List<MessageAttribute> comments;
public List<TrackingIdAttribute> trackingIds;
public PatchSetAttribute currentPatchSet;

View File

@ -19,6 +19,8 @@ import com.google.gerrit.common.data.ApprovalTypes;
import com.google.gerrit.reviewdb.Account;
import com.google.gerrit.reviewdb.Branch;
import com.google.gerrit.reviewdb.Change;
import com.google.gerrit.reviewdb.ChangeMessage;
import com.google.gerrit.reviewdb.PatchLineComment;
import com.google.gerrit.reviewdb.PatchSet;
import com.google.gerrit.reviewdb.PatchSetApproval;
import com.google.gerrit.reviewdb.TrackingId;
@ -128,6 +130,30 @@ public class EventFactory {
}
}
public void addPatchSetComments(PatchSetAttribute patchSetAttribute,
Collection<PatchLineComment> patchLineComments) {
for (PatchLineComment comment : patchLineComments) {
if (comment.getKey().getParentKey().getParentKey().get()
== Integer.parseInt(patchSetAttribute.number)) {
if (patchSetAttribute.comments == null) {
patchSetAttribute.comments =
new ArrayList<PatchSetCommentAttribute>();
}
patchSetAttribute.comments.add(asPatchSetLineAttribute(comment));
}
}
}
public void addComments(ChangeAttribute ca,
Collection<ChangeMessage> messages) {
if (!messages.isEmpty()) {
ca.comments = new ArrayList<MessageAttribute>();
for (ChangeMessage message : messages) {
ca.comments.add(asMessageAttribute(message));
}
}
}
public TrackingIdAttribute asTrackingIdAttribute(TrackingId id) {
TrackingIdAttribute a = new TrackingIdAttribute();
a.system = id.getSystem();
@ -220,6 +246,23 @@ public class EventFactory {
return a;
}
public MessageAttribute asMessageAttribute(ChangeMessage message) {
MessageAttribute a = new MessageAttribute();
a.timestamp = message.getWrittenOn().getTime() / 1000L;
a.reviewer = asAccountAttribute(message.getAuthor());
a.message = message.getMessage();
return a;
}
public PatchSetCommentAttribute asPatchSetLineAttribute(PatchLineComment c) {
PatchSetCommentAttribute a = new PatchSetCommentAttribute();
a.reviewer = asAccountAttribute(c.getAuthor());
a.file = c.getKey().getParentKey().get();
a.line = c.getLine();
a.message = c.getMessage();
return a;
}
/** Get a link to the change; null if the server doesn't know its own address. */
private String getChangeUrl(final Change change) {
if (change != null && urlProvider.get() != null) {

View File

@ -0,0 +1,21 @@
// Copyright (C) 2011 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.events;
public class MessageAttribute {
public Long timestamp;
public AccountAttribute reviewer;
public String message;
}

View File

@ -23,4 +23,5 @@ public class PatchSetAttribute {
public AccountAttribute uploader;
public List<ApprovalAttribute> approvals;
public List<PatchSetCommentAttribute> comments;
}

View File

@ -0,0 +1,22 @@
// Copyright (C) 2011 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.events;
public class PatchSetCommentAttribute {
public String file;
public Integer line;
public AccountAttribute reviewer;
public String message;
}

View File

@ -15,6 +15,7 @@
package com.google.gerrit.server.query.change;
import com.google.gerrit.reviewdb.Change;
import com.google.gerrit.reviewdb.ChangeMessage;
import com.google.gerrit.reviewdb.Patch;
import com.google.gerrit.reviewdb.PatchLineComment;
import com.google.gerrit.reviewdb.PatchSet;
@ -47,6 +48,7 @@ public class ChangeData {
private Collection<PatchLineComment> comments;
private Collection<TrackingId> trackingIds;
private CurrentUser visibleTo;
private List<ChangeMessage> messages;
public ChangeData(final Change.Id id) {
legacyId = id;
@ -210,4 +212,12 @@ public class ChangeData {
}
return trackingIds;
}
public List<ChangeMessage> messages(Provider<ReviewDb> db)
throws OrmException {
if (messages == null) {
messages = db.get().changeMessages().byChange(legacyId).toList();
}
return messages;
}
}

View File

@ -21,6 +21,7 @@ import com.google.gerrit.reviewdb.ReviewDb;
import com.google.gerrit.server.CurrentUser;
import com.google.gerrit.server.events.ChangeAttribute;
import com.google.gerrit.server.events.EventFactory;
import com.google.gerrit.server.events.PatchSetAttribute;
import com.google.gerrit.server.events.QueryStats;
import com.google.gerrit.server.query.Predicate;
import com.google.gerrit.server.query.QueryParseException;
@ -71,6 +72,7 @@ public class QueryProcessor {
private boolean includePatchSets;
private boolean includeCurrentPatchSet;
private boolean includeApprovals;
private boolean includeComments;
private OutputStream outputStream = DisabledOutputStream.INSTANCE;
private PrintWriter out;
@ -100,6 +102,10 @@ public class QueryProcessor {
includeApprovals = on;
}
public void setIncludeComments(boolean on) {
includeComments = on;
}
public void setOutput(OutputStream out, OutputFormat fmt) {
this.outputStream = out;
this.outputFormat = fmt;
@ -180,6 +186,15 @@ public class QueryProcessor {
}
}
if (includeComments) {
eventFactory.addComments(c, d.messages(db));
if (includePatchSets) {
for (PatchSetAttribute attribute : c.patchSets) {
eventFactory.addPatchSetComments(attribute, d.comments(db));
}
}
}
show(c);
}
@ -270,32 +285,39 @@ public class QueryProcessor {
continue;
}
indent(depth);
out.print(f.getName());
out.print(":");
if (val instanceof Long && isDateField(f.getName())) {
out.print(' ');
out.print(sdf.format(new Date(((Long) val) * 1000L)));
out.print('\n');
} else {
showTextValue(val, depth);
}
showField(f.getName(), val, depth);
}
}
private void indent(int depth) {
for (int i = 0; i < depth; i++) {
out.print(" ");
private String indent(int spaces) {
if (spaces == 0) {
return "";
} else {
return String.format("%" + spaces + "s", " ");
}
}
private void showTextValue(Object value, int depth) {
if (isPrimitive(value)) {
private void showField(String field, Object value, int depth) {
final int spacesDepthRatio = 2;
String indent = indent(depth * spacesDepthRatio);
out.print(indent);
out.print(field);
out.print(':');
if (value instanceof String && ((String) value).contains("\n")) {
out.print(' ');
// Idention for multi-line text is
// current depth indetion + length of field + length of ": "
indent = indent(indent.length() + field.length() + spacesDepthRatio);
out.print(((String) value).replaceAll("\n", "\n" + indent).trim());
out.print('\n');
} else if (value instanceof Long && isDateField(field)) {
out.print(' ');
out.print(sdf.format(new Date(((Long) value) * 1000L)));
out.print('\n');
} else if (isPrimitive(value)) {
out.print(' ');
out.print(value);
out.print('\n');
} else if (value instanceof Collection) {
out.print('\n');
for (Object thing : ((Collection<?>) value)) {
@ -305,7 +327,6 @@ public class QueryProcessor {
out.print('\n');
} else {
showText(thing, depth + 1);
out.print('\n');
}
}
} else {
@ -323,7 +344,8 @@ public class QueryProcessor {
private static boolean isDateField(String name) {
return "lastUpdated".equals(name) //
|| "grantedOn".equals(name);
|| "grantedOn".equals(name) //
|| "timestamp".equals(name);
}
private List<Field> fieldsOf(Class<?> type) {

View File

@ -51,6 +51,11 @@ class Query extends BaseCommand {
processor.setIncludeApprovals(on);
}
@Option(name = "--comments", usage = "Include patch set and inline comments")
void setComments(boolean on) {
processor.setIncludeComments(on);
}
@Argument(index = 0, required = true, multiValued = true, metaVar = "QUERY", usage = "Query to execute")
private List<String> query;