diff --git a/Documentation/json.txt b/Documentation/json.txt index 3b8a8cba28..dc82ad1569 100644 --- a/Documentation/json.txt +++ b/Documentation/json.txt @@ -29,6 +29,8 @@ url:: Canonical URL to reach this change. commitMessage:: The full commit message for the change's current patch set. +hashtags:: List of hashtags associated with this change. + createdOn:: Time in seconds since the UNIX epoch when this change was created. diff --git a/java/com/google/gerrit/server/data/ChangeAttribute.java b/java/com/google/gerrit/server/data/ChangeAttribute.java index ec76f500f4..fde592200f 100644 --- a/java/com/google/gerrit/server/data/ChangeAttribute.java +++ b/java/com/google/gerrit/server/data/ChangeAttribute.java @@ -30,6 +30,7 @@ public class ChangeAttribute { public AccountAttribute assignee; public String url; public String commitMessage; + public List hashtags; public Long createdOn; public Long lastUpdated; diff --git a/java/com/google/gerrit/server/events/EventFactory.java b/java/com/google/gerrit/server/events/EventFactory.java index f675dd5e7f..75a08bd256 100644 --- a/java/com/google/gerrit/server/events/EventFactory.java +++ b/java/com/google/gerrit/server/events/EventFactory.java @@ -130,9 +130,9 @@ public class EventFactory { * @param change * @return object suitable for serialization to JSON */ - public ChangeAttribute asChangeAttribute(Change change) { + public ChangeAttribute asChangeAttribute(Change change, ChangeNotes notes) { try (ReviewDb db = schema.open()) { - return asChangeAttribute(db, change); + return asChangeAttribute(db, change, notes); } catch (OrmException e) { logger.atSevere().withCause(e).log("Cannot open database connection"); return new ChangeAttribute(); @@ -170,6 +170,24 @@ public class EventFactory { return a; } + /** + * Create a ChangeAttribute for the given change suitable for serialization to JSON. + * + * @param db Review database + * @param change + * @param notes + * @return object suitable for serialization to JSON + */ + public ChangeAttribute asChangeAttribute(ReviewDb db, Change change, ChangeNotes notes) + throws OrmException { + ChangeAttribute a = asChangeAttribute(db, change); + Set hashtags = notes.load().getHashtags(); + if (!hashtags.isEmpty()) { + a.hashtags = new ArrayList(hashtags.size()); + a.hashtags.addAll(hashtags); + } + return a; + } /** * Create a RefUpdateAttribute for the given old ObjectId, new ObjectId, and branch that is * suitable for serialization to JSON. diff --git a/java/com/google/gerrit/server/events/StreamEventsApiListener.java b/java/com/google/gerrit/server/events/StreamEventsApiListener.java index 9592238be7..7a7805518d 100644 --- a/java/com/google/gerrit/server/events/StreamEventsApiListener.java +++ b/java/com/google/gerrit/server/events/StreamEventsApiListener.java @@ -156,12 +156,12 @@ public class StreamEventsApiListener return psUtil.get(db.get(), notes, PatchSet.Id.fromRef(info.ref)); } - private Supplier changeAttributeSupplier(Change change) { + private Supplier changeAttributeSupplier(Change change, ChangeNotes notes) { return Suppliers.memoize( new Supplier() { @Override public ChangeAttribute get() { - return eventFactory.asChangeAttribute(change); + return eventFactory.asChangeAttribute(change, notes); } }); } @@ -257,10 +257,11 @@ public class StreamEventsApiListener @Override public void onAssigneeChanged(AssigneeChangedListener.Event ev) { try { - Change change = getChange(ev.getChange()); + ChangeNotes notes = getNotes(ev.getChange()); + Change change = notes.getChange(); AssigneeChangedEvent event = new AssigneeChangedEvent(change); - event.change = changeAttributeSupplier(change); + event.change = changeAttributeSupplier(change, notes); event.changer = accountAttributeSupplier(ev.getWho()); event.oldAssignee = accountAttributeSupplier(ev.getOldAssignee()); @@ -273,10 +274,11 @@ public class StreamEventsApiListener @Override public void onTopicEdited(TopicEditedListener.Event ev) { try { - Change change = getChange(ev.getChange()); + ChangeNotes notes = getNotes(ev.getChange()); + Change change = notes.getChange(); TopicChangedEvent event = new TopicChangedEvent(change); - event.change = changeAttributeSupplier(change); + event.change = changeAttributeSupplier(change, notes); event.changer = accountAttributeSupplier(ev.getWho()); event.oldTopic = ev.getOldTopic(); @@ -294,7 +296,7 @@ public class StreamEventsApiListener PatchSet patchSet = getPatchSet(notes, ev.getRevision()); PatchSetCreatedEvent event = new PatchSetCreatedEvent(change); - event.change = changeAttributeSupplier(change); + event.change = changeAttributeSupplier(change, notes); event.patchSet = patchSetAttributeSupplier(change, patchSet); event.uploader = accountAttributeSupplier(ev.getWho()); @@ -310,7 +312,7 @@ public class StreamEventsApiListener ChangeNotes notes = getNotes(ev.getChange()); Change change = notes.getChange(); ReviewerDeletedEvent event = new ReviewerDeletedEvent(change); - event.change = changeAttributeSupplier(change); + event.change = changeAttributeSupplier(change, notes); event.patchSet = patchSetAttributeSupplier(change, psUtil.current(db.get(), notes)); event.reviewer = accountAttributeSupplier(ev.getReviewer()); event.remover = accountAttributeSupplier(ev.getWho()); @@ -331,7 +333,7 @@ public class StreamEventsApiListener Change change = notes.getChange(); ReviewerAddedEvent event = new ReviewerAddedEvent(change); - event.change = changeAttributeSupplier(change); + event.change = changeAttributeSupplier(change, notes); event.patchSet = patchSetAttributeSupplier(change, psUtil.current(db.get(), notes)); for (AccountInfo reviewer : ev.getReviewers()) { event.reviewer = accountAttributeSupplier(reviewer); @@ -354,10 +356,11 @@ public class StreamEventsApiListener @Override public void onHashtagsEdited(HashtagsEditedListener.Event ev) { try { - Change change = getChange(ev.getChange()); + ChangeNotes notes = getNotes(ev.getChange()); + Change change = notes.getChange(); HashtagsChangedEvent event = new HashtagsChangedEvent(change); - event.change = changeAttributeSupplier(change); + event.change = changeAttributeSupplier(change, notes); event.editor = accountAttributeSupplier(ev.getWho()); event.hashtags = hashtagArray(ev.getHashtags()); event.added = hashtagArray(ev.getAddedHashtags()); @@ -402,7 +405,7 @@ public class StreamEventsApiListener PatchSet ps = getPatchSet(notes, ev.getRevision()); CommentAddedEvent event = new CommentAddedEvent(change); - event.change = changeAttributeSupplier(change); + event.change = changeAttributeSupplier(change, notes); event.author = accountAttributeSupplier(ev.getWho()); event.patchSet = patchSetAttributeSupplier(change, ps); event.comment = ev.getComment(); @@ -421,7 +424,7 @@ public class StreamEventsApiListener Change change = notes.getChange(); ChangeRestoredEvent event = new ChangeRestoredEvent(change); - event.change = changeAttributeSupplier(change); + event.change = changeAttributeSupplier(change, notes); event.restorer = accountAttributeSupplier(ev.getWho()); event.patchSet = patchSetAttributeSupplier(change, psUtil.current(db.get(), notes)); event.reason = ev.getReason(); @@ -439,7 +442,7 @@ public class StreamEventsApiListener Change change = notes.getChange(); ChangeMergedEvent event = new ChangeMergedEvent(change); - event.change = changeAttributeSupplier(change); + event.change = changeAttributeSupplier(change, notes); event.submitter = accountAttributeSupplier(ev.getWho()); event.patchSet = patchSetAttributeSupplier(change, psUtil.current(db.get(), notes)); event.newRev = ev.getNewRevisionId(); @@ -457,7 +460,7 @@ public class StreamEventsApiListener Change change = notes.getChange(); ChangeAbandonedEvent event = new ChangeAbandonedEvent(change); - event.change = changeAttributeSupplier(change); + event.change = changeAttributeSupplier(change, notes); event.abandoner = accountAttributeSupplier(ev.getWho()); event.patchSet = patchSetAttributeSupplier(change, psUtil.current(db.get(), notes)); event.reason = ev.getReason(); @@ -471,10 +474,11 @@ public class StreamEventsApiListener @Override public void onWorkInProgressStateChanged(WorkInProgressStateChangedListener.Event ev) { try { - Change change = getChange(ev.getChange()); + ChangeNotes notes = getNotes(ev.getChange()); + Change change = notes.getChange(); WorkInProgressStateChangedEvent event = new WorkInProgressStateChangedEvent(change); - event.change = changeAttributeSupplier(change); + event.change = changeAttributeSupplier(change, notes); event.changer = accountAttributeSupplier(ev.getWho()); dispatcher.get().postEvent(change, event); @@ -486,10 +490,11 @@ public class StreamEventsApiListener @Override public void onPrivateStateChanged(PrivateStateChangedListener.Event ev) { try { - Change change = getChange(ev.getChange()); + ChangeNotes notes = getNotes(ev.getChange()); + Change change = notes.getChange(); PrivateStateChangedEvent event = new PrivateStateChangedEvent(change); - event.change = changeAttributeSupplier(change); + event.change = changeAttributeSupplier(change, notes); event.changer = accountAttributeSupplier(ev.getWho()); dispatcher.get().postEvent(change, event); @@ -505,7 +510,7 @@ public class StreamEventsApiListener Change change = notes.getChange(); VoteDeletedEvent event = new VoteDeletedEvent(change); - event.change = changeAttributeSupplier(change); + event.change = changeAttributeSupplier(change, notes); event.patchSet = patchSetAttributeSupplier(change, psUtil.current(db.get(), notes)); event.comment = ev.getMessage(); event.reviewer = accountAttributeSupplier(ev.getReviewer()); diff --git a/java/com/google/gerrit/server/query/change/OutputStreamQuery.java b/java/com/google/gerrit/server/query/change/OutputStreamQuery.java index dc57a9b248..dbbf367ade 100644 --- a/java/com/google/gerrit/server/query/change/OutputStreamQuery.java +++ b/java/com/google/gerrit/server/query/change/OutputStreamQuery.java @@ -237,7 +237,7 @@ public class OutputStreamQuery { ChangeData d, Map repos, Map revWalks) throws OrmException, IOException { LabelTypes labelTypes = d.getLabelTypes(); - ChangeAttribute c = eventFactory.asChangeAttribute(db, d.change()); + ChangeAttribute c = eventFactory.asChangeAttribute(db, d.change(), d.notes()); eventFactory.extend(c, d.change()); if (!trackingFooters.isEmpty()) {