summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorMika Hamalainen <mika.hamalainen@accenture.com>2011-08-01 14:02:06 +0300
committerMika Hamalainen <mika.hamalainen@accenture.com>2011-08-03 15:02:40 +0300
commit0600ac58c13daf8062e5974cf9dd014a3a3ae504 (patch)
tree52dafad5cc78f67fd04164569709449f156535fb
parentb1934ee5b0bb61543e9cc9e3e69e9520c869fe35 (diff)
Commit message footer options for cherry-pick mode
When using cherry pick submit type, there additional options which define which footers are added to the commit message. Also, added footers can be limited to reviewers who gave the maximum approval score. Bug: issue 655 Change-Id: Ibfb7193edde7f88607683adf061e8603cb382d06
-rw-r--r--gerrit-gwtui/src/main/java/com/google/gerrit/client/admin/AdminConstants.java4
-rw-r--r--gerrit-gwtui/src/main/java/com/google/gerrit/client/admin/AdminConstants.properties4
-rw-r--r--gerrit-gwtui/src/main/java/com/google/gerrit/client/admin/ProjectInfoScreen.java70
-rw-r--r--gerrit-reviewdb/src/main/java/com/google/gerrit/reviewdb/Project.java72
-rw-r--r--gerrit-server/src/main/java/com/google/gerrit/server/git/MergeOp.java23
-rw-r--r--gerrit-server/src/main/java/com/google/gerrit/server/git/ProjectConfig.java26
6 files changed, 196 insertions, 3 deletions
diff --git a/gerrit-gwtui/src/main/java/com/google/gerrit/client/admin/AdminConstants.java b/gerrit-gwtui/src/main/java/com/google/gerrit/client/admin/AdminConstants.java
index bbb0992106..e2243b925c 100644
--- a/gerrit-gwtui/src/main/java/com/google/gerrit/client/admin/AdminConstants.java
+++ b/gerrit-gwtui/src/main/java/com/google/gerrit/client/admin/AdminConstants.java
@@ -47,6 +47,10 @@ public interface AdminConstants extends Constants {
String emailOnlyAuthors();
String descriptionNotifications();
String buttonSaveGroupOptions();
+ String cherryPickOptions();
+ String includeReviewedOn();
+ String includeOnlyMaxApprovals();
+ String footerPrefix();
String headingOwner();
String headingParentProjectName();
diff --git a/gerrit-gwtui/src/main/java/com/google/gerrit/client/admin/AdminConstants.properties b/gerrit-gwtui/src/main/java/com/google/gerrit/client/admin/AdminConstants.properties
index b331b6a45e..4ba12d51f5 100644
--- a/gerrit-gwtui/src/main/java/com/google/gerrit/client/admin/AdminConstants.properties
+++ b/gerrit-gwtui/src/main/java/com/google/gerrit/client/admin/AdminConstants.properties
@@ -24,6 +24,10 @@ allowTopicReview = Allow Topics to be reviewed as a hole entity
headingGroupOptions = Group Options
isVisibleToAll = Make group visible to all registered users.
buttonSaveGroupOptions = Save Group Options
+cherryPickOptions = Cherry Pick Options
+includeReviewedOn = Footer Reviewed-on
+includeOnlyMaxApprovals = Add footer only for approvals with maximum score
+footerPrefix = Footer
emailOnlyAuthors = Authors
descriptionNotifications = Send email notifications about comments and actions by users in this group only to:
diff --git a/gerrit-gwtui/src/main/java/com/google/gerrit/client/admin/ProjectInfoScreen.java b/gerrit-gwtui/src/main/java/com/google/gerrit/client/admin/ProjectInfoScreen.java
index f4a66e372a..07357ff3c6 100644
--- a/gerrit-gwtui/src/main/java/com/google/gerrit/client/admin/ProjectInfoScreen.java
+++ b/gerrit-gwtui/src/main/java/com/google/gerrit/client/admin/ProjectInfoScreen.java
@@ -19,6 +19,7 @@ import com.google.gerrit.client.rpc.GerritCallback;
import com.google.gerrit.client.rpc.ScreenLoadCallback;
import com.google.gerrit.client.ui.OnEditEnabler;
import com.google.gerrit.client.ui.SmallHeading;
+import com.google.gerrit.common.data.ApprovalType;
import com.google.gerrit.common.data.ProjectDetail;
import com.google.gerrit.reviewdb.Project;
import com.google.gerrit.reviewdb.Project.SubmitType;
@@ -33,6 +34,10 @@ import com.google.gwt.user.client.ui.Panel;
import com.google.gwt.user.client.ui.VerticalPanel;
import com.google.gwtexpui.globalkey.client.NpTextArea;
+import java.util.HashMap;
+import java.util.Map;
+import java.util.Map.Entry;
+
public class ProjectInfoScreen extends ProjectScreen {
private Project project;
@@ -46,6 +51,11 @@ public class ProjectInfoScreen extends ProjectScreen {
private CheckBox useContributorAgreements;
private CheckBox useSignedOffBy;
+ private Panel cherryPickPanel;
+ private CheckBox includeReviewedOn;
+ private CheckBox includeOnlyMaxApproval;
+ private Map<String, CheckBox> approvalsInFooter;
+
private NpTextArea descTxt;
private Button saveProject;
@@ -69,6 +79,7 @@ public class ProjectInfoScreen extends ProjectScreen {
initDescription();
initProjectOptions();
+ initcherryPickOptions();
initAgreements();
add(saveProject);
}
@@ -76,6 +87,17 @@ public class ProjectInfoScreen extends ProjectScreen {
@Override
protected void onLoad() {
super.onLoad();
+ for (final ApprovalType t :
+ Gerrit.getConfig().getApprovalTypes().getApprovalTypes()) {
+ final String footer = t.getCategory().getLabelName();
+ if (!approvalsInFooter.containsKey(footer)) {
+ final String title = Util.C.footerPrefix() + " " + footer;
+ CheckBox checkBox = new CheckBox(title, true);
+ approvalsInFooter.put(footer, checkBox);
+ saveEnabler.listenTo(checkBox);
+ cherryPickPanel.add(checkBox);
+ }
+ }
Util.PROJECT_SVC.projectDetail(getProjectKey(),
new ScreenLoadCallback<ProjectDetail>(this) {
public void preDisplay(final ProjectDetail result) {
@@ -126,6 +148,7 @@ public class ProjectInfoScreen extends ProjectScreen {
@Override
public void onChange(ChangeEvent event) {
setEnabledForUseContentMerge();
+ setEnabledForCherryPick();
}
});
saveEnabler.listenTo(submitType);
@@ -162,6 +185,17 @@ public class ProjectInfoScreen extends ProjectScreen {
}
}
+ private void setEnabledForCherryPick() {
+ final boolean isCherryPickSubmitType =
+ SubmitType.CHERRY_PICK.equals(Project.SubmitType.valueOf(
+ submitType.getValue(submitType.getSelectedIndex())));
+ includeReviewedOn.setEnabled(isCherryPickSubmitType);
+ includeOnlyMaxApproval.setEnabled(isCherryPickSubmitType);
+ for (CheckBox checkBox : approvalsInFooter.values()) {
+ checkBox.setEnabled(isCherryPickSubmitType);
+ }
+ }
+
private void initAgreements() {
agreementsPanel = new VerticalPanel();
agreementsPanel.add(new SmallHeading(Util.C.headingAgreements()));
@@ -177,6 +211,23 @@ public class ProjectInfoScreen extends ProjectScreen {
add(agreementsPanel);
}
+ private void initcherryPickOptions() {
+ cherryPickPanel = new VerticalPanel();
+ cherryPickPanel.add(new SmallHeading(Util.C.cherryPickOptions()));
+
+ includeOnlyMaxApproval = new CheckBox(Util.C.includeOnlyMaxApprovals(), true);
+ saveEnabler.listenTo(includeOnlyMaxApproval);
+ cherryPickPanel.add(includeOnlyMaxApproval);
+
+ includeReviewedOn = new CheckBox(Util.C.includeReviewedOn(), true);
+ saveEnabler.listenTo(includeReviewedOn);
+ cherryPickPanel.add(includeReviewedOn);
+
+ approvalsInFooter = new HashMap<String, CheckBox>();
+
+ add(cherryPickPanel);
+ }
+
private void setSubmitType(final Project.SubmitType newSubmitType) {
int index = -1;
if (submitType != null) {
@@ -188,6 +239,7 @@ public class ProjectInfoScreen extends ProjectScreen {
}
submitType.setSelectedIndex(index);
setEnabledForUseContentMerge();
+ setEnabledForCherryPick();
}
}
@@ -209,6 +261,19 @@ public class ProjectInfoScreen extends ProjectScreen {
allowTopicReview.setValue(project.isAllowTopicReview());
setSubmitType(project.getSubmitType());
+ includeOnlyMaxApproval.setValue(project.isIncludeOnlyMaxApproval());
+ includeReviewedOn.setValue(!project.isHideReviewedOn());
+
+ Map<String, Boolean> hiddenFooters = project.getHiddenFooters();
+ for (Entry<String, CheckBox> entry : approvalsInFooter.entrySet()) {
+ final CheckBox checkBox = entry.getValue();
+ if (hiddenFooters.containsKey(entry.getKey())) {
+ checkBox.setValue(!hiddenFooters.get(entry.getKey()));
+ } else {
+ checkBox.setValue(true);
+ }
+ }
+
saveProject.setEnabled(false);
}
@@ -225,6 +290,11 @@ public class ProjectInfoScreen extends ProjectScreen {
project.setSubmitType(Project.SubmitType.valueOf(submitType
.getValue(submitType.getSelectedIndex())));
}
+ project.setIncludeOnlyMaxApproval(includeOnlyMaxApproval.getValue());
+ project.setHideReviewedOn(!includeReviewedOn.getValue());
+ for (Entry<String, CheckBox> entry : approvalsInFooter.entrySet()) {
+ project.addHiddenFooter(entry.getKey(), !entry.getValue().getValue());
+ }
enableForm(false, false, false);
diff --git a/gerrit-reviewdb/src/main/java/com/google/gerrit/reviewdb/Project.java b/gerrit-reviewdb/src/main/java/com/google/gerrit/reviewdb/Project.java
index faebcf2a06..68e4655886 100644
--- a/gerrit-reviewdb/src/main/java/com/google/gerrit/reviewdb/Project.java
+++ b/gerrit-reviewdb/src/main/java/com/google/gerrit/reviewdb/Project.java
@@ -17,6 +17,11 @@ package com.google.gerrit.reviewdb;
import com.google.gwtorm.client.Column;
import com.google.gwtorm.client.StringKey;
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+
/** Projects match a source code repository managed by Gerrit */
public final class Project {
/** Project name key */
@@ -57,6 +62,27 @@ public final class Project {
}
}
+ public static class ApprovalFooterValue {
+ String category;
+ boolean hidden;
+
+ protected ApprovalFooterValue() {
+ }
+
+ protected ApprovalFooterValue(final String category, final boolean on) {
+ this.category = category;
+ this.hidden = on;
+ }
+
+ public String getCategory() {
+ return category;
+ }
+
+ public boolean getHidden() {
+ return hidden;
+ }
+ }
+
public static enum SubmitType {
FAST_FORWARD_ONLY,
@@ -85,12 +111,20 @@ public final class Project {
protected boolean useContentMerge;
+ protected boolean hideReviewedOn;
+
+ protected boolean includeOnlyMaximumApprovals;
+
+ protected List<ApprovalFooterValue> hiddenFooters;
+
protected Project() {
+ hiddenFooters = new ArrayList<Project.ApprovalFooterValue>();
}
public Project(Project.NameKey nameKey) {
name = nameKey;
submitType = SubmitType.MERGE_IF_NECESSARY;
+ hiddenFooters = new ArrayList<Project.ApprovalFooterValue>();
}
public Project.NameKey getNameKey() {
@@ -133,6 +167,22 @@ public final class Project {
return allowTopicReview;
}
+ public boolean isHideReviewedOn() {
+ return hideReviewedOn;
+ }
+
+ public boolean isIncludeOnlyMaxApproval() {
+ return includeOnlyMaximumApprovals;
+ }
+
+ public Map<String, Boolean> getHiddenFooters() {
+ HashMap<String, Boolean> footers = new HashMap<String, Boolean>();
+ for (ApprovalFooterValue value : hiddenFooters) {
+ footers.put(value.getCategory(), value.getHidden());
+ }
+ return footers;
+ }
+
public void setUseSignedOffBy(final boolean sbo) {
useSignedOffBy = sbo;
}
@@ -149,6 +199,14 @@ public final class Project {
allowTopicReview = atr;
}
+ public void setHideReviewedOn(boolean includeReviewedOn) {
+ this.hideReviewedOn = includeReviewedOn;
+ }
+
+ public void setIncludeOnlyMaxApproval(boolean includeOnlyMaxApproval) {
+ this.includeOnlyMaximumApprovals = includeOnlyMaxApproval;
+ }
+
public SubmitType getSubmitType() {
return submitType;
}
@@ -157,6 +215,17 @@ public final class Project {
submitType = type;
}
+ public void addHiddenFooter(final String category, final boolean on) {
+ for (ApprovalFooterValue value : hiddenFooters) {
+ if (value.category.equals(category)) {
+ value.hidden = on;
+ return;
+ }
+ }
+
+ hiddenFooters.add(new ApprovalFooterValue(category, on));
+ }
+
public void copySettingsFrom(final Project update) {
description = update.description;
useContributorAgreements = update.useContributorAgreements;
@@ -165,6 +234,9 @@ public final class Project {
requireChangeID = update.requireChangeID;
allowTopicReview = update.allowTopicReview;
submitType = update.submitType;
+ includeOnlyMaximumApprovals = update.includeOnlyMaximumApprovals;
+ hideReviewedOn = update.hideReviewedOn;
+ hiddenFooters = update.hiddenFooters;
}
public Project.NameKey getParent() {
diff --git a/gerrit-server/src/main/java/com/google/gerrit/server/git/MergeOp.java b/gerrit-server/src/main/java/com/google/gerrit/server/git/MergeOp.java
index 74f8795c70..c35ef30fe3 100644
--- a/gerrit-server/src/main/java/com/google/gerrit/server/git/MergeOp.java
+++ b/gerrit-server/src/main/java/com/google/gerrit/server/git/MergeOp.java
@@ -57,6 +57,7 @@ import com.google.inject.Provider;
import com.google.inject.assistedinject.Assisted;
import org.eclipse.jgit.diff.Sequence;
+import org.eclipse.jgit.errors.ConfigInvalidException;
import org.eclipse.jgit.errors.IncorrectObjectTypeException;
import org.eclipse.jgit.errors.MissingObjectException;
import org.eclipse.jgit.errors.RepositoryNotFoundException;
@@ -778,6 +779,8 @@ public class MergeOp {
} catch (IOException e) {
throw new MergeException("Cannot merge " + n.name(), e);
+ } catch (ConfigInvalidException e) {
+ throw new MergeException("Cannot merge " + n.name(), e);
}
}
}
@@ -794,9 +797,13 @@ public class MergeOp {
}
private void writeCherryPickCommit(final Merger m, final CodeReviewCommit n)
- throws IOException {
+ throws IOException, ConfigInvalidException {
rw.parseBody(n);
+ final ProjectConfig cfg = new ProjectConfig(destProject.getNameKey());
+ cfg.load(db);
+ final Project project = cfg.getProject();
+
final List<FooterLine> footers = n.getFooterLines();
final StringBuilder msgbuf = new StringBuilder();
msgbuf.append(n.getFullMessage());
@@ -823,8 +830,9 @@ public class MergeOp {
msgbuf.append('\n');
}
+
final String siteUrl = urlProvider.get();
- if (siteUrl != null) {
+ if (!project.isHideReviewedOn() && siteUrl != null) {
final String url = siteUrl + n.patchsetId.getParentKey().get();
if (!contains(footers, REVIEWED_ON, url)) {
msgbuf.append(REVIEWED_ON.getName());
@@ -843,6 +851,7 @@ public class MergeOp {
return a.getGranted().compareTo(b.getGranted());
}
});
+ final Map<String, Boolean> hiddenFooters = project.getHiddenFooters();
for (final PatchSetApproval a : approvalList) {
if (a.getValue() <= 0) {
@@ -905,7 +914,15 @@ public class MergeOp {
tag = at.getCategory().getName().replace(' ', '-');
}
- if (!contains(footers, new FooterKey(tag), identbuf.toString())) {
+ if (project.isIncludeOnlyMaxApproval()) {
+ final ApprovalType at = approvalTypes.byId(a.getCategoryId());
+ if (a.getValue() < at.getMax().getValue()) {
+ continue;
+ }
+ }
+
+ if (!hiddenFooters.containsKey(tag)
+ && !contains(footers, new FooterKey(tag), identbuf.toString())) {
msgbuf.append(tag);
msgbuf.append(": ");
msgbuf.append(identbuf);
diff --git a/gerrit-server/src/main/java/com/google/gerrit/server/git/ProjectConfig.java b/gerrit-server/src/main/java/com/google/gerrit/server/git/ProjectConfig.java
index 69611baa98..7f0b74a77f 100644
--- a/gerrit-server/src/main/java/com/google/gerrit/server/git/ProjectConfig.java
+++ b/gerrit-server/src/main/java/com/google/gerrit/server/git/ProjectConfig.java
@@ -41,6 +41,7 @@ import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
+import java.util.Map.Entry;
import java.util.Set;
public class ProjectConfig extends VersionedMetaData {
@@ -65,6 +66,11 @@ public class ProjectConfig extends VersionedMetaData {
private static final String KEY_ACTION = "action";
private static final String KEY_MERGE_CONTENT = "mergeContent";
+ private static final String CHERRY_PICK = "cherryPick";
+ private static final String CATEGORY_FOOTERS = "categoryFooters";
+ private static final String INCLUDE_ONLY_MAX_APPROVALS = "includeOnlyMaximumApprovals";
+ private static final String HIDE_REVIEWED_ON = "includeReviewedOn";
+
private static final SubmitType defaultSubmitAction =
SubmitType.MERGE_IF_NECESSARY;
@@ -192,6 +198,9 @@ public class ProjectConfig extends VersionedMetaData {
p.setSubmitType(rc.getEnum(SUBMIT, null, KEY_ACTION, defaultSubmitAction));
p.setUseContentMerge(rc.getBoolean(SUBMIT, null, KEY_MERGE_CONTENT, false));
+
+ p.setIncludeOnlyMaxApproval(rc.getBoolean(CHERRY_PICK, INCLUDE_ONLY_MAX_APPROVALS, false));
+ p.setHideReviewedOn(rc.getBoolean(CHERRY_PICK, HIDE_REVIEWED_ON, false));
accessSections = new HashMap<String, AccessSection>();
for (String refName : rc.getSubsections(ACCESS)) {
@@ -209,6 +218,11 @@ public class ProjectConfig extends VersionedMetaData {
for (String varName : rc.getNames(ACCESS, refName)) {
if (isPermission(varName)) {
Permission perm = as.getPermission(varName, true);
+ for (String category : rc.getNames(CHERRY_PICK, CATEGORY_FOOTERS)) {
+ final boolean value = rc.getBoolean(CATEGORY_FOOTERS, category, true);
+ p.addHiddenFooter(category, value);
+ }
+
boolean useRange = perm.isLabel();
for (String ruleString : rc.getStringList(ACCESS, refName, varName)) {
@@ -290,6 +304,9 @@ public class ProjectConfig extends VersionedMetaData {
set(rc, RECEIVE, null, KEY_REQUIRE_CHANGE_ID, p.isRequireChangeID() || p.isAllowTopicReview());
set(rc, RECEIVE, null, KEY_ALLOW_TOPIC_REVIEW, p.isAllowTopicReview());
+ set(rc, CHERRY_PICK, null, INCLUDE_ONLY_MAX_APPROVALS, p.isIncludeOnlyMaxApproval());
+ set(rc, CHERRY_PICK, null, HIDE_REVIEWED_ON, p.isHideReviewedOn());
+
set(rc, SUBMIT, null, KEY_ACTION, p.getSubmitType(), defaultSubmitAction);
set(rc, SUBMIT, null, KEY_MERGE_CONTENT, p.isUseContentMerge());
@@ -342,6 +359,15 @@ public class ProjectConfig extends VersionedMetaData {
}
groupsByUUID.keySet().retainAll(keepGroups);
+ final Map<String, Boolean> footers = p.getHiddenFooters();
+ for (Entry<String, Boolean> entry : footers.entrySet()) {
+ if (!entry.getValue()) {
+ rc.unset(CHERRY_PICK, CATEGORY_FOOTERS, entry.getKey());
+ } else {
+ rc.setBoolean(CHERRY_PICK, CATEGORY_FOOTERS, entry.getKey(), true);
+ }
+ }
+
saveConfig(PROJECT_CONFIG, rc);
saveGroupList();
}