BatchRefUpdate batch = getRepository().getRefDatabase().newBatchUpdate();
batch.setAllowNonFastForwards(isAllowNonFastForwards());
batch.setRefLogIdent(getRefLogIdent());
batch.setRefLogMessage("push", true);
ReceiveCommand patchsetRefCmd = null;
PatchsetCommand patchsetCmd = null;
for (ReceiveCommand cmd : toApply) {
if (Result.NOT_ATTEMPTED != cmd.getResult()) {
// Already rejected by the core receive process.
continue;
}
if (isPatchsetRef(cmd.getRefName()) && processPatchsets) {
if (ticketService == null) {
sendRejection(cmd, "Sorry, the ticket service is unavailable and can not accept patchsets at this time.");
continue;
}
if (!ticketService.isReady()) {
sendRejection(cmd, "Sorry, the ticket service can not accept patchsets at this time.");
continue;
}
if (UserModel.ANONYMOUS.equals(user)) {
// server allows anonymous pushes, but anonymous patchset
// contributions are prohibited by design
sendRejection(cmd, "Sorry, anonymous patchset contributions are prohibited.");
continue;
}
final Matcher m = NEW_PATCHSET.matcher(cmd.getRefName());
if (m.matches()) {
// prohibit pushing directly to a patchset ref
long id = getTicketId(cmd.getRefName());
sendError("You may not directly push directly to a patchset ref!");
sendError("Instead, please push to one the following:");
sendError(" - {0}{1,number,0}", Constants.R_FOR, id);
sendError(" - {0}{1,number,0}", Constants.R_TICKET, id);
sendRejection(cmd, "protected ref");
continue;
}
if (hasRefNamespace(Constants.R_FOR)) {
// the refs/for/ namespace exists and it must not
LOGGER.error("{} already has refs in the {} namespace",
repository.name, Constants.R_FOR);
sendRejection(cmd, "Sorry, a repository administrator will have to remove the {} namespace", Constants.R_FOR);
continue;
}
if (cmd.getNewId().equals(ObjectId.zeroId())) {
// ref deletion request
if (cmd.getRefName().startsWith(Constants.R_TICKET)) {
if (user.canDeleteRef(repository)) {
batch.addCommand(cmd);
} else {
sendRejection(cmd, "Sorry, you do not have permission to delete {}", cmd.getRefName());
}
} else {
sendRejection(cmd, "Sorry, you can not delete {}", cmd.getRefName());
}
continue;
}
if (patchsetRefCmd != null) {
sendRejection(cmd, "You may only push one patchset at a time.");
continue;
}
LOGGER.info(MessageFormat.format("Verifying {0} push ref \"{1}\" received from {2}",
repository.name, cmd.getRefName(), user.username));
// responsible verification
String responsible = PatchsetCommand.getSingleOption(cmd, PatchsetCommand.RESPONSIBLE);
if (!StringUtils.isEmpty(responsible)) {
UserModel assignee = gitblit.getUserModel(responsible);
if (assignee == null) {
// no account by this name
sendRejection(cmd, "{0} can not be assigned any tickets because there is no user account by that name", responsible);
continue;
} else if (!assignee.canPush(repository)) {
// account does not have RW permissions
sendRejection(cmd, "{0} ({1}) can not be assigned any tickets because the user does not have RW permissions for {2}",
assignee.getDisplayName(), assignee.username, repository.name);
continue;
}
}
// milestone verification
String milestone = PatchsetCommand.getSingleOption(cmd, PatchsetCommand.MILESTONE);
if (!StringUtils.isEmpty(milestone)) {
TicketMilestone milestoneModel = ticketService.getMilestone(repository, milestone);
if (milestoneModel == null) {
// milestone does not exist
sendRejection(cmd, "Sorry, \"{0}\" is not a valid milestone!", milestone);
continue;
}
}
// watcher verification
List<String> watchers = PatchsetCommand.getOptions(cmd, PatchsetCommand.WATCH);
if (!ArrayUtils.isEmpty(watchers)) {
boolean verified = true;
for (String watcher : watchers) {
UserModel user = gitblit.getUserModel(watcher);
if (user == null) {
// watcher does not exist
sendRejection(cmd, "Sorry, \"{0}\" is not a valid username for the watch list!", watcher);
verified = false;
break;
}
}
if (!verified) {
continue;
}
}
patchsetRefCmd = cmd;
patchsetCmd = preparePatchset(cmd);
if (patchsetCmd != null) {
batch.addCommand(patchsetCmd);
}
continue;
}
batch.addCommand(cmd);
}
if (!batch.getCommands().isEmpty()) {
try {
batch.execute(getRevWalk(), updating);
} catch (IOException err) {
for (ReceiveCommand cmd : toApply) {
if (cmd.getResult() == Result.NOT_ATTEMPTED) {
sendRejection(cmd, "lock error: {0}", err.getMessage());
LOGGER.error(MessageFormat.format("failed to lock {0}:{1}",
repository.name, cmd.getRefName()), err);
}
}
}
}
//
// set the results into the patchset ref receive command
//
if (patchsetRefCmd != null && patchsetCmd != null) {
if (!patchsetCmd.getResult().equals(Result.OK)) {
// patchset command failed!
LOGGER.error(patchsetCmd.getType() + " " + patchsetCmd.getRefName()
+ " " + patchsetCmd.getResult());
patchsetRefCmd.setResult(patchsetCmd.getResult(), patchsetCmd.getMessage());
} else {
// all patchset commands were applied
patchsetRefCmd.setResult(Result.OK);
// update the ticket branch ref
RefUpdate ru = updateRef(
patchsetCmd.getTicketBranch(),
patchsetCmd.getNewId(),