blob: 53c9dc41ee84b1001d4bc30f515a3620e78fd417 [file] [log] [blame]
// 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.notedb.rebuild;
import com.google.common.base.MoreObjects.ToStringHelper;
import com.google.common.base.Strings;
import com.google.common.collect.ImmutableMap;
import com.google.gerrit.reviewdb.client.Change;
import com.google.gerrit.reviewdb.client.ChangeMessage;
import com.google.gerrit.server.ChangeMessagesUtil;
import com.google.gerrit.server.notedb.ChangeUpdate;
import com.google.gwtorm.server.OrmException;
import java.sql.Timestamp;
import java.util.Map;
import java.util.Optional;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
class ChangeMessageEvent extends Event {
private static final ImmutableMap<Change.Status, Pattern> STATUS_PATTERNS =
ImmutableMap.of(
Change.Status.ABANDONED, Pattern.compile("^Abandoned(\n.*)*$"),
Change.Status.MERGED,
Pattern.compile(
"^Change has been successfully (merged|cherry-picked|rebased|pushed).*$"),
Change.Status.NEW, Pattern.compile("^Restored(\n.*)*$"));
private static final Pattern PRIVATE_SET_REGEXP = Pattern.compile("^Set private$");
private static final Pattern PRIVATE_UNSET_REGEXP = Pattern.compile("^Unset private$");
private static final Pattern TOPIC_SET_REGEXP = Pattern.compile("^Topic set to (.+)$");
private static final Pattern TOPIC_CHANGED_REGEXP =
Pattern.compile("^Topic changed from (.+) to (.+)$");
private static final Pattern TOPIC_REMOVED_REGEXP = Pattern.compile("^Topic (.+) removed$");
private static final Pattern WIP_SET_REGEXP = Pattern.compile("^Set Work In Progress$");
private static final Pattern WIP_UNSET_REGEXP = Pattern.compile("^Set Ready For Review$");
private final Change change;
private final Change noteDbChange;
private final Optional<Change.Status> status;
private final ChangeMessage message;
ChangeMessageEvent(
Change change, Change noteDbChange, ChangeMessage message, Timestamp changeCreatedOn) {
super(
message.getPatchSetId(),
message.getAuthor(),
message.getRealAuthor(),
message.getWrittenOn(),
changeCreatedOn,
message.getTag());
this.change = change;
this.noteDbChange = noteDbChange;
this.message = message;
this.status = parseStatus(message);
}
@Override
boolean uniquePerUpdate() {
return true;
}
@Override
protected boolean isSubmit() {
return status.isPresent() && status.get() == Change.Status.MERGED;
}
@Override
protected boolean canHaveTag() {
return true;
}
@SuppressWarnings("deprecation")
@Override
void apply(ChangeUpdate update) throws OrmException {
checkUpdate(update);
update.setChangeMessage(message.getMessage());
setPrivate(update);
setTopic(update);
setWorkInProgress(update);
if (status.isPresent()) {
Change.Status s = status.get();
update.fixStatus(s);
noteDbChange.setStatus(s);
if (s == Change.Status.MERGED) {
update.setSubmissionId(change.getSubmissionId());
noteDbChange.setSubmissionId(change.getSubmissionId());
}
}
}
private static Optional<Change.Status> parseStatus(ChangeMessage message) {
String msg = message.getMessage();
if (msg == null) {
return Optional.empty();
}
for (Map.Entry<Change.Status, Pattern> e : STATUS_PATTERNS.entrySet()) {
if (e.getValue().matcher(msg).matches()) {
return Optional.of(e.getKey());
}
}
return Optional.empty();
}
private void setPrivate(ChangeUpdate update) {
String msg = message.getMessage();
if (msg == null) {
return;
}
Matcher m = PRIVATE_SET_REGEXP.matcher(msg);
if (m.matches()) {
update.setPrivate(true);
noteDbChange.setPrivate(true);
return;
}
m = PRIVATE_UNSET_REGEXP.matcher(msg);
if (m.matches()) {
update.setPrivate(false);
noteDbChange.setPrivate(false);
}
}
private void setTopic(ChangeUpdate update) {
String msg = message.getMessage();
if (msg == null) {
return;
}
Matcher m = TOPIC_SET_REGEXP.matcher(msg);
if (m.matches()) {
String topic = m.group(1);
update.setTopic(topic);
noteDbChange.setTopic(topic);
return;
}
m = TOPIC_CHANGED_REGEXP.matcher(msg);
if (m.matches()) {
String topic = m.group(2);
update.setTopic(topic);
noteDbChange.setTopic(topic);
return;
}
if (TOPIC_REMOVED_REGEXP.matcher(msg).matches()) {
update.setTopic(null);
noteDbChange.setTopic(null);
}
}
private void setWorkInProgress(ChangeUpdate update) {
String msg = Strings.nullToEmpty(message.getMessage());
String tag = message.getTag();
if (ChangeMessagesUtil.TAG_SET_WIP.equals(tag)
|| ChangeMessagesUtil.TAG_UPLOADED_WIP_PATCH_SET.equals(tag)
|| WIP_SET_REGEXP.matcher(msg).matches()) {
update.setWorkInProgress(true);
noteDbChange.setWorkInProgress(true);
} else if (ChangeMessagesUtil.TAG_SET_READY.equals(tag)
|| ChangeMessagesUtil.TAG_UPLOADED_PATCH_SET.equals(tag)
|| WIP_UNSET_REGEXP.matcher(msg).matches()) {
update.setWorkInProgress(false);
noteDbChange.setWorkInProgress(false);
}
}
@Override
protected void addToString(ToStringHelper helper) {
helper.add("message", message);
}
}