Reject commit subjects over 50 characters.

Add a test in receive commits for commit message first lines of over 50
characters and a boolean config option to enable checking for it.

Change-Id: I557d1ff72e6df97b991b05c36483c13873b706fb
This commit is contained in:
Monty Taylor 2011-08-10 14:35:12 -04:00
parent 1e35b2096f
commit d0fa8866d4
7 changed files with 52 additions and 2 deletions

View File

@ -40,6 +40,7 @@ public interface AdminConstants extends Constants {
String useContentMerge();
String useContributorAgreements();
String useSignedOffBy();
String requireShortMessage();
String requireChangeID();
String headingGroupOptions();
String isVisibleToAll();

View File

@ -19,6 +19,7 @@ buttonSaveChanges = Save Changes
useContentMerge = Automatically resolve conflicts
useContributorAgreements = Require a valid contributor agreement to upload
useSignedOffBy = Require <a href="http://gerrit.googlecode.com/svn/documentation/2.0/user-signedoffby.html#Signed-off-by" target="_blank"><code>Signed-off-by</code></a> in commit message
requireShortMessage = Require the first line of the commit to be 50 characters or less
requireChangeID = Require <a href="http://gerrit.googlecode.com/svn/documentation/2.0/user-changeid.html" target="_blank"><code>Change-Id</code></a> in commit message
headingGroupOptions = Group Options
isVisibleToAll = Make group visible to all registered users.

View File

@ -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

View File

@ -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;
}

View File

@ -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);

View File

@ -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<String> 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;

View File

@ -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());