Merge changes I9a7060e3,I8d80186c

* changes:
  Refactor CommitValidators to reduce repetition
  Add test for pushing initial review in empty repo
This commit is contained in:
Edwin Kempin
2016-09-13 08:55:52 +00:00
committed by Gerrit Code Review
7 changed files with 126 additions and 129 deletions

View File

@@ -33,6 +33,7 @@ import com.google.gerrit.acceptance.GerritConfig;
import com.google.gerrit.acceptance.GitUtil;
import com.google.gerrit.acceptance.PushOneCommit;
import com.google.gerrit.acceptance.TestAccount;
import com.google.gerrit.acceptance.TestProjectInput;
import com.google.gerrit.common.data.LabelType;
import com.google.gerrit.common.data.Permission;
import com.google.gerrit.extensions.api.changes.NotifyHandling;
@@ -128,6 +129,27 @@ public abstract class AbstractPushForReview extends AbstractDaemonTest {
r.assertChange(Change.Status.NEW, null);
}
@Test
@TestProjectInput(createEmptyCommit = false)
public void pushInitialCommitForMasterBranch() throws Exception {
RevCommit c =
testRepo.commit().message("Initial commit").insertChangeId().create();
String id = GitUtil.getChangeId(testRepo, c).get();
testRepo.reset(c);
String r = "refs/for/master";
PushResult pr = pushHead(testRepo, r, false);
assertPushOk(pr, r);
ChangeInfo change = gApi.changes().id(id).info();
assertThat(change.branch).isEqualTo("master");
assertThat(change.status).isEqualTo(ChangeStatus.NEW);
try (Repository repo = repoManager.openRepository(project)) {
assertThat(repo.resolve("master")).isNull();
}
}
@Test
public void output() throws Exception {
String url = canonicalWebUrl.get();

View File

@@ -19,7 +19,6 @@ import com.google.gerrit.extensions.events.GitReferenceUpdatedListener;
import com.google.gerrit.extensions.registration.DynamicSet;
import com.google.gerrit.server.git.GitModule;
import com.google.gerrit.server.git.validators.CommitValidationListener;
import com.google.gerrit.server.git.validators.CommitValidators;
/** Module for batch programs that need git access. */
public class BatchGitModule extends FactoryModule {
@@ -27,7 +26,6 @@ public class BatchGitModule extends FactoryModule {
protected void configure() {
DynamicSet.setOf(binder(), GitReferenceUpdatedListener.class);
DynamicSet.setOf(binder(), CommitValidationListener.class);
factory(CommitValidators.Factory.class);
install(new GitModule());
}
}

View File

@@ -41,7 +41,6 @@ import com.google.gerrit.server.PatchSetUtil;
import com.google.gerrit.server.events.CommitReceivedEvent;
import com.google.gerrit.server.extensions.events.CommentAdded;
import com.google.gerrit.server.extensions.events.RevisionCreated;
import com.google.gerrit.server.git.BanCommit;
import com.google.gerrit.server.git.BatchUpdate;
import com.google.gerrit.server.git.BatchUpdate.ChangeContext;
import com.google.gerrit.server.git.BatchUpdate.Context;
@@ -66,7 +65,6 @@ import com.google.inject.Inject;
import com.google.inject.assistedinject.Assisted;
import org.eclipse.jgit.lib.ObjectId;
import org.eclipse.jgit.notes.NoteMap;
import org.eclipse.jgit.revwalk.RevCommit;
import org.eclipse.jgit.transport.ReceiveCommand;
import org.eclipse.jgit.util.ChangeIdUtil;
@@ -468,9 +466,6 @@ public class ChangeInserter extends BatchUpdate.InsertChangeOp {
try {
RefControl refControl = projectControlFactory
.controlFor(ctx.getProject(), ctx.getUser()).controlForRef(refName);
CommitValidators cv = commitValidatorsFactory.create(
refControl, new NoSshInfo(), ctx.getRepository());
String refName = psId.toRefName();
CommitReceivedEvent event = new CommitReceivedEvent(
new ReceiveCommand(
@@ -481,19 +476,10 @@ public class ChangeInserter extends BatchUpdate.InsertChangeOp {
change.getDest().get(),
commit,
ctx.getIdentifiedUser());
switch (validatePolicy) {
case RECEIVE_COMMITS:
NoteMap rejectCommits = BanCommit.loadRejectCommitsMap(
ctx.getRepository(), ctx.getRevWalk());
cv.validateForReceiveCommits(event, rejectCommits);
break;
case GERRIT:
cv.validateForGerritCommits(event);
break;
case NONE:
break;
}
commitValidatorsFactory
.create(
validatePolicy, refControl, new NoSshInfo(), ctx.getRepository())
.validate(event);
} catch (CommitValidationException e) {
throw new ResourceConflictException(e.getFullMessage());
} catch (NoSuchProjectException e) {

View File

@@ -35,7 +35,6 @@ import com.google.gerrit.server.PatchSetUtil;
import com.google.gerrit.server.ReviewerSet;
import com.google.gerrit.server.events.CommitReceivedEvent;
import com.google.gerrit.server.extensions.events.RevisionCreated;
import com.google.gerrit.server.git.BanCommit;
import com.google.gerrit.server.git.BatchUpdate;
import com.google.gerrit.server.git.BatchUpdate.ChangeContext;
import com.google.gerrit.server.git.BatchUpdate.Context;
@@ -52,7 +51,6 @@ import com.google.inject.assistedinject.Assisted;
import com.google.inject.assistedinject.AssistedInject;
import org.eclipse.jgit.lib.ObjectId;
import org.eclipse.jgit.notes.NoteMap;
import org.eclipse.jgit.revwalk.RevCommit;
import org.eclipse.jgit.transport.ReceiveCommand;
import org.slf4j.Logger;
@@ -275,12 +273,12 @@ public class PatchSetInserter extends BatchUpdate.Op {
private void validate(RepoContext ctx)
throws AuthException, ResourceConflictException, IOException,
OrmException {
CommitValidators cv = commitValidatorsFactory.create(
origCtl.getRefControl(), new NoSshInfo(), ctx.getRepository());
if (!origCtl.canAddPatchSet(ctx.getDb())) {
throw new AuthException("cannot add patch set");
}
if (validatePolicy == CommitValidators.Policy.NONE) {
return;
}
String refName = getPatchSetId().toRefName();
CommitReceivedEvent event = new CommitReceivedEvent(
@@ -293,18 +291,11 @@ public class PatchSetInserter extends BatchUpdate.Op {
commit, ctx.getIdentifiedUser());
try {
switch (validatePolicy) {
case RECEIVE_COMMITS:
NoteMap rejectCommits = BanCommit.loadRejectCommitsMap(
ctx.getRepository(), ctx.getRevWalk());
cv.validateForReceiveCommits(event, rejectCommits);
break;
case GERRIT:
cv.validateForGerritCommits(event);
break;
case NONE:
break;
}
commitValidatorsFactory
.create(
validatePolicy, origCtl.getRefControl(), new NoSshInfo(),
ctx.getRepository())
.validate(event);
} catch (CommitValidationException e) {
throw new ResourceConflictException(e.getFullMessage());
}

View File

@@ -116,7 +116,6 @@ import com.google.gerrit.server.git.TagCache;
import com.google.gerrit.server.git.TransferConfig;
import com.google.gerrit.server.git.strategy.SubmitStrategy;
import com.google.gerrit.server.git.validators.CommitValidationListener;
import com.google.gerrit.server.git.validators.CommitValidators;
import com.google.gerrit.server.git.validators.MergeValidationListener;
import com.google.gerrit.server.git.validators.MergeValidators;
import com.google.gerrit.server.git.validators.MergeValidators.ProjectConfigValidator;
@@ -372,7 +371,6 @@ public class GerritGlobalModule extends FactoryModule {
bind(AnonymousUser.class);
factory(CommitValidators.Factory.class);
factory(RefOperationValidators.Factory.class);
factory(MergeValidators.Factory.class);
factory(ProjectConfigValidator.Factory.class);

View File

@@ -2588,12 +2588,11 @@ public class ReceiveCommits {
rw.parseBody(c);
CommitReceivedEvent receiveEvent =
new CommitReceivedEvent(cmd, project, ctl.getRefName(), c, user);
CommitValidators commitValidators =
commitValidatorsFactory.create(ctl, sshInfo, repo);
CommitValidators commitValidators = commitValidatorsFactory.create(
CommitValidators.Policy.RECEIVE_COMMITS, ctl, sshInfo, repo);
try {
messages.addAll(commitValidators.validateForReceiveCommits(
receiveEvent, rejectCommits));
messages.addAll(commitValidators.validate(receiveEvent));
} catch (CommitValidationException e) {
logDebug("Commit validation failed on {}", c.name());
messages.addAll(e.getMessages());

View File

@@ -16,8 +16,10 @@ package com.google.gerrit.server.git.validators;
import static com.google.gerrit.reviewdb.client.Change.CHANGE_ID_PATTERN;
import static com.google.gerrit.reviewdb.client.RefNames.REFS_CONFIG;
import static com.google.gerrit.server.git.ReceiveCommits.NEW_PATCHSET;
import com.google.common.base.CharMatcher;
import com.google.common.collect.ImmutableList;
import com.google.gerrit.common.FooterConstants;
import com.google.gerrit.common.Nullable;
import com.google.gerrit.common.PageLinks;
@@ -31,15 +33,15 @@ import com.google.gerrit.server.config.AllUsersName;
import com.google.gerrit.server.config.CanonicalWebUrl;
import com.google.gerrit.server.config.GerritServerConfig;
import com.google.gerrit.server.events.CommitReceivedEvent;
import com.google.gerrit.server.git.BanCommit;
import com.google.gerrit.server.git.ProjectConfig;
import com.google.gerrit.server.git.ReceiveCommits;
import com.google.gerrit.server.git.ValidationError;
import com.google.gerrit.server.project.ProjectControl;
import com.google.gerrit.server.project.RefControl;
import com.google.gerrit.server.ssh.SshInfo;
import com.google.gerrit.server.util.MagicBranch;
import com.google.inject.Inject;
import com.google.inject.assistedinject.Assisted;
import com.google.inject.Singleton;
import com.jcraft.jsch.HostKey;
@@ -51,6 +53,7 @@ import org.eclipse.jgit.notes.NoteMap;
import org.eclipse.jgit.revwalk.FooterKey;
import org.eclipse.jgit.revwalk.FooterLine;
import org.eclipse.jgit.revwalk.RevCommit;
import org.eclipse.jgit.revwalk.RevWalk;
import org.eclipse.jgit.util.SystemReader;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
@@ -68,107 +71,99 @@ public class CommitValidators {
.getLogger(CommitValidators.class);
public enum Policy {
/** Use {@link #validateForGerritCommits}. */
/** Use {@link Factory#forGerritCommits}. */
GERRIT,
/** Use {@link #validateForReceiveCommits}. */
/** Use {@link Factory#forReceiveCommits}. */
RECEIVE_COMMITS,
/** Do not validate commits. */
NONE
}
public interface Factory {
CommitValidators create(RefControl refControl, SshInfo sshInfo,
Repository repo);
}
@Singleton
public static class Factory {
private final PersonIdent gerritIdent;
private final RefControl refControl;
private final String canonicalWebUrl;
private final String installCommitMsgHookCommand;
private final SshInfo sshInfo;
private final Repository repo;
private final DynamicSet<CommitValidationListener> commitValidationListeners;
private final DynamicSet<CommitValidationListener> pluginValidators;
private final AllUsersName allUsers;
private final String installCommitMsgHookCommand;
@Inject
CommitValidators(@GerritPersonIdent PersonIdent gerritIdent,
Factory(@GerritPersonIdent PersonIdent gerritIdent,
@CanonicalWebUrl @Nullable String canonicalWebUrl,
@GerritServerConfig Config config,
DynamicSet<CommitValidationListener> commitValidationListeners,
AllUsersName allUsers,
@Assisted SshInfo sshInfo,
@Assisted Repository repo,
@Assisted RefControl refControl) {
@GerritServerConfig Config cfg,
DynamicSet<CommitValidationListener> pluginValidators,
AllUsersName allUsers) {
this.gerritIdent = gerritIdent;
this.canonicalWebUrl = canonicalWebUrl;
this.installCommitMsgHookCommand =
config.getString("gerrit", null, "installCommitMsgHookCommand");
this.commitValidationListeners = commitValidationListeners;
this.pluginValidators = pluginValidators;
this.allUsers = allUsers;
this.sshInfo = sshInfo;
this.repo = repo;
this.refControl = refControl;
this.installCommitMsgHookCommand = cfg != null
? cfg.getString("gerrit", null, "installCommitMsgHookCommand") : null;
}
public List<CommitValidationMessage> validateForReceiveCommits(
CommitReceivedEvent receiveEvent, NoteMap rejectCommits)
throws CommitValidationException {
List<CommitValidationListener> validators = new LinkedList<>();
validators.add(new UploadMergesPermissionValidator(refControl));
validators.add(new AmendedGerritMergeCommitValidationListener(
refControl, gerritIdent));
validators.add(new AuthorUploaderValidator(refControl, canonicalWebUrl));
validators.add(new CommitterUploaderValidator(refControl, canonicalWebUrl));
validators.add(new SignedOffByValidator(refControl));
if (MagicBranch.isMagicBranch(receiveEvent.command.getRefName())
|| ReceiveCommits.NEW_PATCHSET.matcher(
receiveEvent.command.getRefName()).matches()) {
validators.add(new ChangeIdValidator(refControl, canonicalWebUrl,
installCommitMsgHookCommand, sshInfo));
public CommitValidators create(Policy policy, RefControl refControl,
SshInfo sshInfo, Repository repo) throws IOException {
switch (policy) {
case RECEIVE_COMMITS:
return forReceiveCommits(refControl, sshInfo, repo);
case GERRIT:
return forGerritCommits(refControl, sshInfo, repo);
case NONE:
return none();
default:
throw new IllegalArgumentException("unspported policy: " + policy);
}
validators.add(new ConfigValidator(refControl, repo, allUsers));
validators.add(new BannedCommitsValidator(rejectCommits));
validators.add(new PluginCommitValidationListener(commitValidationListeners));
List<CommitValidationMessage> messages = new LinkedList<>();
try {
for (CommitValidationListener commitValidator : validators) {
messages.addAll(commitValidator.onCommitReceived(receiveEvent));
}
} catch (CommitValidationException e) {
// Keep the old messages (and their order) in case of an exception
messages.addAll(e.getMessages());
throw new CommitValidationException(e.getMessage(), messages);
}
return messages;
}
public List<CommitValidationMessage> validateForGerritCommits(
private CommitValidators forReceiveCommits(RefControl refControl,
SshInfo sshInfo, Repository repo) throws IOException {
try (RevWalk rw = new RevWalk(repo)) {
NoteMap rejectCommits = BanCommit.loadRejectCommitsMap(repo, rw);
return new CommitValidators(ImmutableList.of(
new UploadMergesPermissionValidator(refControl),
new AmendedGerritMergeCommitValidationListener(
refControl, gerritIdent),
new AuthorUploaderValidator(refControl, canonicalWebUrl),
new CommitterUploaderValidator(refControl, canonicalWebUrl),
new SignedOffByValidator(refControl),
new ChangeIdValidator(refControl, canonicalWebUrl,
installCommitMsgHookCommand, sshInfo),
new ConfigValidator(refControl, repo, allUsers),
new BannedCommitsValidator(rejectCommits),
new PluginCommitValidationListener(pluginValidators)));
}
}
private CommitValidators forGerritCommits(RefControl refControl,
SshInfo sshInfo, Repository repo) {
return new CommitValidators(ImmutableList.of(
new UploadMergesPermissionValidator(refControl),
new AmendedGerritMergeCommitValidationListener(
refControl, gerritIdent),
new AuthorUploaderValidator(refControl, canonicalWebUrl),
new SignedOffByValidator(refControl),
new ChangeIdValidator(refControl, canonicalWebUrl,
installCommitMsgHookCommand, sshInfo),
new ConfigValidator(refControl, repo, allUsers),
new PluginCommitValidationListener(pluginValidators)));
}
private CommitValidators none() {
return new CommitValidators(ImmutableList.<CommitValidationListener>of());
}
}
private final List<CommitValidationListener> validators;
CommitValidators(List<CommitValidationListener> validators) {
this.validators = validators;
}
public List<CommitValidationMessage> validate(
CommitReceivedEvent receiveEvent) throws CommitValidationException {
List<CommitValidationListener> validators = new LinkedList<>();
validators.add(new UploadMergesPermissionValidator(refControl));
validators.add(new AmendedGerritMergeCommitValidationListener(
refControl, gerritIdent));
validators.add(new AuthorUploaderValidator(refControl, canonicalWebUrl));
validators.add(new SignedOffByValidator(refControl));
if (MagicBranch.isMagicBranch(receiveEvent.command.getRefName())
|| ReceiveCommits.NEW_PATCHSET.matcher(
receiveEvent.command.getRefName()).matches()) {
validators.add(new ChangeIdValidator(refControl, canonicalWebUrl,
installCommitMsgHookCommand, sshInfo));
}
validators.add(new ConfigValidator(refControl, repo, allUsers));
validators.add(new PluginCommitValidationListener(commitValidationListeners));
List<CommitValidationMessage> messages = new LinkedList<>();
try {
for (CommitValidationListener commitValidator : validators) {
messages.addAll(commitValidator.onCommitReceived(receiveEvent));
@@ -221,6 +216,9 @@ public class CommitValidators {
@Override
public List<CommitValidationMessage> onCommitReceived(
CommitReceivedEvent receiveEvent) throws CommitValidationException {
if (!shouldValidateChangeId(receiveEvent)) {
return Collections.emptyList();
}
RevCommit commit = receiveEvent.commit;
List<CommitValidationMessage> messages = new LinkedList<>();
List<String> idList = commit.getFooterLines(FooterConstants.CHANGE_ID);
@@ -255,6 +253,11 @@ public class CommitValidators {
return Collections.emptyList();
}
private static boolean shouldValidateChangeId(CommitReceivedEvent event) {
return MagicBranch.isMagicBranch(event.command.getRefName())
|| NEW_PATCHSET.matcher(event.command.getRefName()).matches();
}
private CommitValidationMessage getMissingChangeIdErrorMsg(
final String errMsg, final RevCommit c) {
StringBuilder sb = new StringBuilder();