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 4f95a7029c..b50e35753d 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 @@ -40,6 +40,7 @@ public interface AdminConstants extends Constants { String useContentMerge(); String useContributorAgreements(); String useSignedOffBy(); + String requireShortMessage(); String requireChangeID(); String headingGroupOptions(); String isVisibleToAll(); 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 e9575cfe80..eef574f40a 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 @@ -19,6 +19,7 @@ buttonSaveChanges = Save Changes useContentMerge = Automatically resolve conflicts useContributorAgreements = Require a valid contributor agreement to upload useSignedOffBy = Require Signed-off-by in commit message +requireShortMessage = Require the first line of the commit to be 50 characters or less requireChangeID = Require Change-Id in commit message headingGroupOptions = Group Options isVisibleToAll = Make group visible to all registered users. 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 fb35855c6f..74d131724f 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 @@ -37,6 +37,7 @@ public class ProjectInfoScreen extends ProjectScreen { private Project project; private Panel projectOptionsPanel; + private CheckBox requireShortMessage; private CheckBox requireChangeID; private ListBox submitType; private CheckBox useContentMerge; @@ -96,6 +97,7 @@ public class ProjectInfoScreen extends ProjectScreen { descTxt.setEnabled(canModifyDescription); useContributorAgreements.setEnabled(canModifyAgreements); useSignedOffBy.setEnabled(canModifyAgreements); + requireShortMessage.setEnabled(canModifyMergeType); requireChangeID.setEnabled(canModifyMergeType); } @@ -134,6 +136,10 @@ public class ProjectInfoScreen extends ProjectScreen { saveEnabler.listenTo(useContentMerge); projectOptionsPanel.add(useContentMerge); + requireShortMessage = new CheckBox(Util.C.requireShortMessage(), true); + saveEnabler.listenTo(requireShortMessage); + projectOptionsPanel.add(requireShortMessage); + requireChangeID = new CheckBox(Util.C.requireChangeID(), true); saveEnabler.listenTo(requireChangeID); projectOptionsPanel.add(requireChangeID); @@ -200,6 +206,7 @@ public class ProjectInfoScreen extends ProjectScreen { useContributorAgreements.setValue(project.isUseContributorAgreements()); useSignedOffBy.setValue(project.isUseSignedOffBy()); useContentMerge.setValue(project.isUseContentMerge()); + requireShortMessage.setValue(project.isRequireShortMessage()); requireChangeID.setValue(project.isRequireChangeID()); setSubmitType(project.getSubmitType()); @@ -211,6 +218,7 @@ public class ProjectInfoScreen extends ProjectScreen { project.setUseContributorAgreements(useContributorAgreements.getValue()); project.setUseSignedOffBy(useSignedOffBy.getValue()); project.setUseContentMerge(useContentMerge.getValue()); + project.setRequireShortMessage(requireShortMessage.getValue()); project.setRequireChangeID(requireChangeID.getValue()); if (submitType.getSelectedIndex() >= 0) { project.setSubmitType(Project.SubmitType.valueOf(submitType 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 49f3333f96..8ca79f2c69 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 @@ -79,6 +79,8 @@ public final class Project { protected NameKey parent; + protected boolean requireShortMessage; + protected boolean requireChangeID; protected boolean useContentMerge; @@ -123,6 +125,10 @@ public final class Project { return useContentMerge; } + public boolean isRequireShortMessage() { + return requireShortMessage; + } + public boolean isRequireChangeID() { return requireChangeID; } @@ -135,6 +141,10 @@ public final class Project { useContentMerge = cm; } + public void setRequireShortMessage(final boolean sm) { + requireShortMessage = sm; + } + public void setRequireChangeID(final boolean cid) { requireChangeID = cid; } @@ -152,6 +162,7 @@ public final class Project { useContributorAgreements = update.useContributorAgreements; useSignedOffBy = update.useSignedOffBy; useContentMerge = update.useContentMerge; + requireShortMessage = update.requireShortMessage; requireChangeID = update.requireChangeID; submitType = update.submitType; } 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 651fc6a028..335f5aa88e 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 @@ -56,6 +56,7 @@ public class ProjectConfig extends VersionedMetaData { private static final String RECEIVE = "receive"; private static final String KEY_REQUIRE_SIGNED_OFF_BY = "requireSignedOffBy"; + private static final String KEY_REQUIRE_SHORT_MESSAGE = "requireShortMessage"; private static final String KEY_REQUIRE_CHANGE_ID = "requireChangeId"; private static final String KEY_REQUIRE_CONTRIBUTOR_AGREEMENT = "requireContributorAgreement"; @@ -186,6 +187,7 @@ public class ProjectConfig extends VersionedMetaData { p.setUseContributorAgreements(rc.getBoolean(RECEIVE, KEY_REQUIRE_CONTRIBUTOR_AGREEMENT, false)); p.setUseSignedOffBy(rc.getBoolean(RECEIVE, KEY_REQUIRE_SIGNED_OFF_BY, false)); + p.setRequireShortMessage(rc.getBoolean(RECEIVE, KEY_REQUIRE_SHORT_MESSAGE, false)); p.setRequireChangeID(rc.getBoolean(RECEIVE, KEY_REQUIRE_CHANGE_ID, false)); p.setSubmitType(rc.getEnum(SUBMIT, null, KEY_ACTION, defaultSubmitAction)); @@ -285,6 +287,7 @@ public class ProjectConfig extends VersionedMetaData { set(rc, RECEIVE, null, KEY_REQUIRE_CONTRIBUTOR_AGREEMENT, p.isUseContributorAgreements()); set(rc, RECEIVE, null, KEY_REQUIRE_SIGNED_OFF_BY, p.isUseSignedOffBy()); + set(rc, RECEIVE, null, KEY_REQUIRE_SHORT_MESSAGE, p.isRequireShortMessage()); set(rc, RECEIVE, null, KEY_REQUIRE_CHANGE_ID, p.isRequireChangeID()); set(rc, SUBMIT, null, KEY_ACTION, p.getSubmitType(), defaultSubmitAction); diff --git a/gerrit-server/src/main/java/com/google/gerrit/server/git/ReceiveCommits.java b/gerrit-server/src/main/java/com/google/gerrit/server/git/ReceiveCommits.java index 97ad546c56..0ae300d936 100644 --- a/gerrit-server/src/main/java/com/google/gerrit/server/git/ReceiveCommits.java +++ b/gerrit-server/src/main/java/com/google/gerrit/server/git/ReceiveCommits.java @@ -113,6 +113,8 @@ public class ReceiveCommits implements PreReceiveHook, PostReceiveHook { private static final FooterKey TESTED_BY = new FooterKey("Tested-by"); private static final FooterKey CHANGE_ID = new FooterKey("Change-Id"); + private static final long COMMIT_SUBJECT_LENGTH = 50; + public interface Factory { ReceiveCommits create(ProjectControl projectControl, Repository repository); } @@ -1669,6 +1671,26 @@ public class ReceiveCommits implements PreReceiveHook, PostReceiveHook { } } + // Check for people + if (project.isRequireShortMessage() && + (COMMIT_SUBJECT_LENGTH < c.getShortMessage().length())) { + + String errMsg = "first line of commit message is too long"; + reject(cmd, errMsg); + + StringBuilder sb = new StringBuilder(); + sb.append("ERROR: ").append(errMsg).append("\n"); + sb.append("The first line in a commit should be no more than "); + sb.append(COMMIT_SUBJECT_LENGTH).append(" characters\n\n"); + + sb.append("Please ammend your commit with:\n\n"); + sb.append(" git commit --amend\n\n"); + sb.append("and resubmit.\n"); + + rp.sendMessage(sb.toString()); + return false; + } + final List idList = c.getFooterLines(CHANGE_ID); if (idList.isEmpty()) { if (project.isRequireChangeID() && (cmd.getRefName().startsWith(NEW_CHANGE) @@ -1764,7 +1786,7 @@ public class ReceiveCommits implements PreReceiveHook, PostReceiveHook { private void warnMalformedMessage(RevCommit c) { ObjectReader reader = rp.getRevWalk().getObjectReader(); - if (65 < c.getShortMessage().length()) { + if (COMMIT_SUBJECT_LENGTH < c.getShortMessage().length()) { AbbreviatedObjectId id; try { id = reader.abbreviate(c); @@ -1772,7 +1794,7 @@ public class ReceiveCommits implements PreReceiveHook, PostReceiveHook { id = c.abbreviate(6); } rp.sendMessage("(W) " + id.name() // - + ": commit subject >65 characters; use shorter first paragraph"); + + ": commit subject >" + COMMIT_SUBJECT_LENGTH + " characters; use shorter first paragraph"); } int longLineCnt = 0, nonEmptyCnt = 0; diff --git a/gerrit-sshd/src/main/java/com/google/gerrit/sshd/commands/CreateProject.java b/gerrit-sshd/src/main/java/com/google/gerrit/sshd/commands/CreateProject.java index 77dc8f12d4..90e1a28730 100644 --- a/gerrit-sshd/src/main/java/com/google/gerrit/sshd/commands/CreateProject.java +++ b/gerrit-sshd/src/main/java/com/google/gerrit/sshd/commands/CreateProject.java @@ -86,6 +86,9 @@ final class CreateProject extends BaseCommand { @Option(name = "--use-content-merge", usage = "allow automatic conflict resolving within files") private boolean contentMerge; + @Option(name = "--require-short-message", usage = "if short commit subject is required") + private boolean requireShortMessage; + @Option(name = "--require-change-id", aliases = {"--id"}, usage = "if change-id is required") private boolean requireChangeID; @@ -211,6 +214,7 @@ final class CreateProject extends BaseCommand { newProject.setUseContributorAgreements(contributorAgreements); newProject.setUseSignedOffBy(signedOffBy); newProject.setUseContentMerge(contentMerge); + newProject.setRequireShortMessage(requireShortMessage); newProject.setRequireChangeID(requireChangeID); if (newParent != null) { newProject.setParentName(newParent.getProject().getName());