diff options
author | Mika Hamalainen <mika.hamalainen@accenture.com> | 2011-08-01 14:02:06 +0300 |
---|---|---|
committer | Mika Hamalainen <mika.hamalainen@accenture.com> | 2011-08-03 15:02:40 +0300 |
commit | 0600ac58c13daf8062e5974cf9dd014a3a3ae504 (patch) | |
tree | 52dafad5cc78f67fd04164569709449f156535fb | |
parent | b1934ee5b0bb61543e9cc9e3e69e9520c869fe35 (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
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(); } |