use of com.google.gerrit.entities.PatchSet in project gerrit by GerritCodeReview.
the class StreamEventsApiListener method onRevisionCreated.
@Override
public void onRevisionCreated(RevisionCreatedListener.Event ev) {
try {
ChangeNotes notes = getNotes(ev.getChange());
Change change = notes.getChange();
PatchSet patchSet = getPatchSet(notes, ev.getRevision());
PatchSetCreatedEvent event = new PatchSetCreatedEvent(change);
event.change = changeAttributeSupplier(change, notes);
event.patchSet = patchSetAttributeSupplier(change, patchSet);
event.uploader = accountAttributeSupplier(ev.getWho());
dispatcher.run(d -> d.postEvent(change, event));
} catch (StorageException e) {
logger.atSevere().withCause(e).log("Failed to dispatch event");
}
}
use of com.google.gerrit.entities.PatchSet in project gerrit by GerritCodeReview.
the class ReceiveCommits method autoCloseChanges.
private void autoCloseChanges(ReceiveCommand cmd, Task progress) {
try (TraceTimer traceTimer = newTimer("autoCloseChanges")) {
logger.atFine().log("Starting auto-closing of changes");
String refName = cmd.getRefName();
Set<Change.Id> ids = new HashSet<>();
// handleRegularCommands
try {
retryHelper.changeUpdate("autoCloseChanges", updateFactory -> {
try (BatchUpdate bu = updateFactory.create(projectState.getNameKey(), user, TimeUtil.now());
ObjectInserter ins = repo.newObjectInserter();
ObjectReader reader = ins.newReader();
RevWalk rw = new RevWalk(reader)) {
if (ObjectId.zeroId().equals(cmd.getOldId())) {
// potentially expensive computation that loop over all commits.
return null;
}
bu.setRepository(repo, rw, ins);
// TODO(dborowitz): Teach BatchUpdate to ignore missing changes.
RevCommit newTip = rw.parseCommit(cmd.getNewId());
BranchNameKey branch = BranchNameKey.create(project.getNameKey(), refName);
rw.reset();
rw.sort(RevSort.REVERSE);
rw.markStart(newTip);
rw.markUninteresting(rw.parseCommit(cmd.getOldId()));
Map<Change.Key, ChangeNotes> byKey = null;
List<ReplaceRequest> replaceAndClose = new ArrayList<>();
int existingPatchSets = 0;
int newPatchSets = 0;
SubmissionId submissionId = null;
COMMIT: for (RevCommit c; (c = rw.next()) != null; ) {
rw.parseBody(c);
// refs pointing to this commit.
for (PatchSet.Id psId : receivePackRefCache.patchSetIdsFromObjectId(c.copy())) {
Optional<ChangeNotes> notes = getChangeNotes(psId.changeId());
if (notes.isPresent() && notes.get().getChange().getDest().equals(branch)) {
if (submissionId == null) {
submissionId = new SubmissionId(notes.get().getChange());
}
existingPatchSets++;
bu.addOp(notes.get().getChangeId(), setPrivateOpFactory.create(false, null));
bu.addOp(psId.changeId(), mergedByPushOpFactory.create(requestScopePropagator, psId, submissionId, refName, newTip.getId().getName()));
continue COMMIT;
}
}
for (String changeId : ChangeUtil.getChangeIdsFromFooter(c, urlFormatter.get())) {
if (byKey == null) {
byKey = retryHelper.changeIndexQuery("queryOpenChangesByKeyByBranch", q -> openChangesByKeyByBranch(q, branch)).call();
}
ChangeNotes onto = byKey.get(Change.key(changeId.trim()));
if (onto != null) {
newPatchSets++;
// Hold onto this until we're done with the walk, as the call to
// req.validate below calls isMergedInto which resets the walk.
ReplaceRequest req = new ReplaceRequest(onto.getChangeId(), c, cmd, false);
req.notes = onto;
replaceAndClose.add(req);
continue COMMIT;
}
}
}
for (ReplaceRequest req : replaceAndClose) {
Change.Id id = req.notes.getChangeId();
if (!req.validateNewPatchSetForAutoClose()) {
logger.atFine().log("Not closing %s because validation failed", id);
continue;
}
if (submissionId == null) {
submissionId = new SubmissionId(req.notes.getChange());
}
req.addOps(bu, null);
bu.addOp(id, setPrivateOpFactory.create(false, null));
bu.addOp(id, mergedByPushOpFactory.create(requestScopePropagator, req.psId, submissionId, refName, newTip.getId().getName()).setPatchSetProvider(req.replaceOp::getPatchSet));
bu.addOp(id, new ChangeProgressOp(progress));
ids.add(id);
}
logger.atFine().log("Auto-closing %d changes with existing patch sets and %d with new patch" + " sets", existingPatchSets, newPatchSets);
bu.execute();
} catch (IOException | StorageException | PermissionBackendException e) {
throw new StorageException("Failed to auto-close changes", e);
}
// If we are here, we didn't throw UpdateException. Record the result.
// The ordering is indeterminate due to the HashSet; unfortunately, Change.Id
// doesn't
// fit into TreeSet.
ids.stream().forEach(id -> result.addChange(ReceiveCommitsResult.ChangeStatus.AUTOCLOSED, id));
return null;
}).defaultTimeoutMultiplier(5).call();
} catch (RestApiException e) {
logger.atSevere().withCause(e).log("Can't insert patchset");
} catch (UpdateException e) {
logger.atSevere().withCause(e).log("Failed to auto-close changes");
} finally {
logger.atFine().log("Done auto-closing changes");
}
}
}
use of com.google.gerrit.entities.PatchSet in project gerrit by GerritCodeReview.
the class ReplaceOp method updateChange.
@Override
public boolean updateChange(ChangeContext ctx) throws RestApiException, IOException, PermissionBackendException, ConfigInvalidException, ValidationException {
notes = ctx.getNotes();
Change change = notes.getChange();
if (change == null || change.isClosed()) {
rejectMessage = CHANGE_IS_CLOSED;
return false;
}
if (groups.isEmpty()) {
PatchSet prevPs = psUtil.current(notes);
groups = prevPs != null ? prevPs.groups() : ImmutableList.of();
}
ChangeData cd = changeDataFactory.create(ctx.getNotes());
oldRecipients = getRecipientsFromReviewers(cd.reviewers());
ChangeUpdate update = ctx.getUpdate(patchSetId);
update.setSubjectForCommit("Create patch set " + patchSetId.get());
String reviewMessage = null;
String psDescription = null;
if (magicBranch != null) {
reviewMessage = magicBranch.message;
psDescription = magicBranch.message;
approvals.putAll(magicBranch.labels);
Set<String> hashtags = magicBranch.hashtags;
if (hashtags != null && !hashtags.isEmpty()) {
hashtags.addAll(notes.getHashtags());
update.setHashtags(hashtags);
}
if (magicBranch.topic != null && !magicBranch.topic.equals(ctx.getChange().getTopic())) {
try {
update.setTopic(magicBranch.topic);
} catch (ValidationException ex) {
throw new BadRequestException(ex.getMessage());
}
}
if (magicBranch.removePrivate) {
change.setPrivate(false);
update.setPrivate(false);
} else if (magicBranch.isPrivate) {
change.setPrivate(true);
update.setPrivate(true);
}
if (magicBranch.ready) {
change.setWorkInProgress(false);
change.setReviewStarted(true);
update.setWorkInProgress(false);
} else if (magicBranch.workInProgress) {
change.setWorkInProgress(true);
update.setWorkInProgress(true);
}
if (magicBranch.ignoreAttentionSet) {
update.ignoreFurtherAttentionSetUpdates();
}
}
newPatchSet = psUtil.insert(ctx.getRevWalk(), update, patchSetId, commitId, groups, pushCertificate != null ? pushCertificate.toTextWithSignature() : null, psDescription);
update.setPsDescription(psDescription);
MailRecipients fromFooters = getRecipientsFromFooters(accountResolver, commit.getFooterLines());
approvalsUtil.addApprovalsForNewPatchSet(update, projectState.getLabelTypes(), newPatchSet, ctx.getUser(), approvals);
reviewerAdditions = reviewerModifier.prepare(ctx.getNotes(), ctx.getUser(), getReviewerInputs(magicBranch, fromFooters, ctx.getChange(), info), true);
Optional<ReviewerModification> reviewerError = reviewerAdditions.getFailures().stream().findFirst();
if (reviewerError.isPresent()) {
throw new UnprocessableEntityException(reviewerError.get().result.error);
}
reviewerAdditions.updateChange(ctx, newPatchSet);
// reviewer which is needed in several other code paths.
if (magicBranch != null && !magicBranch.labels.isEmpty()) {
update.putReviewer(ctx.getAccountId(), REVIEWER);
}
approvalsUtil.persistCopiedApprovals(ctx.getNotes(), newPatchSet, ctx.getRevWalk(), ctx.getRepoView().getConfig(), update);
mailMessage = insertChangeMessage(update, ctx, reviewMessage);
if (mergedByPushOp == null) {
resetChange(ctx);
} else {
mergedByPushOp.setPatchSetProvider(Providers.of(newPatchSet)).updateChange(ctx);
}
return true;
}
use of com.google.gerrit.entities.PatchSet in project gerrit by GerritCodeReview.
the class SubmitWithStickyApprovalDiff method apply.
public String apply(ChangeNotes notes, CurrentUser currentUser) throws AuthException, IOException, PermissionBackendException, InvalidChangeOperationException {
PatchSet currentPatchset = notes.getCurrentPatchSet();
PatchSet.Id latestApprovedPatchsetId = getLatestApprovedPatchsetId(notes);
if (latestApprovedPatchsetId.get() == currentPatchset.id().get()) {
// If the latest approved patchset is the current patchset, no need to return anything.
return "";
}
StringBuilder diff = new StringBuilder(String.format("\n\n%d is the latest approved patch-set.\n", latestApprovedPatchsetId.get()));
Map<String, FileDiffOutput> modifiedFiles = listModifiedFiles(notes.getProjectName(), currentPatchset, notes.getPatchSets().get(latestApprovedPatchsetId));
// To make the message a bit more concise, we skip the magic files.
List<FileDiffOutput> modifiedFilesList = modifiedFiles.values().stream().filter(p -> !Patch.isMagic(p.newPath().orElse(""))).collect(Collectors.toList());
if (modifiedFilesList.isEmpty()) {
diff.append("No files were changed between the latest approved patch-set and the submitted one.\n");
return diff.toString();
}
diff.append("The change was submitted with unreviewed changes in the following files:\n\n");
TemporaryBuffer.Heap buffer = new TemporaryBuffer.Heap(Math.min(HEAP_EST_SIZE, DEFAULT_POST_SUBMIT_SIZE_LIMIT), DEFAULT_POST_SUBMIT_SIZE_LIMIT);
try (Repository repository = repositoryManager.openRepository(notes.getProjectName());
DiffFormatter formatter = new DiffFormatter(buffer)) {
formatter.setRepository(repository);
formatter.setDetectRenames(true);
boolean isDiffTooLarge = false;
List<String> formatterResult = null;
try {
formatter.format(modifiedFilesList.get(0).oldCommitId(), modifiedFilesList.get(0).newCommitId());
// This returns the diff for all the files.
formatterResult = Arrays.stream(RawParseUtils.decode(buffer.toByteArray()).split("\n")).collect(Collectors.toList());
} catch (IOException e) {
if (JGitText.get().inMemoryBufferLimitExceeded.equals(e.getMessage())) {
isDiffTooLarge = true;
} else {
throw e;
}
}
if (formatterResult != null) {
int addedBytes = formatterResult.stream().mapToInt(String::length).sum();
if (!CommentCumulativeSizeValidator.isEnoughSpace(notes, addedBytes, maxCumulativeSize)) {
isDiffTooLarge = true;
}
}
for (FileDiffOutput fileDiff : modifiedFilesList) {
diff.append(getDiffForFile(notes, currentPatchset.id(), latestApprovedPatchsetId, fileDiff, currentUser, formatterResult, isDiffTooLarge));
}
}
return diff.toString();
}
use of com.google.gerrit.entities.PatchSet in project gerrit by GerritCodeReview.
the class UploaderinPredicate method match.
@Override
public boolean match(ChangeData cd) {
PatchSet latestPatchSet = cd.currentPatchSet();
if (latestPatchSet == null) {
return false;
}
IdentifiedUser uploader = userFactory.create(latestPatchSet.uploader());
return uploader.getEffectiveGroups().contains(uuid);
}
Aggregations