use of com.google.gerrit.server.query.change.ChangeData in project gerrit by GerritCodeReview.
the class MergeOp method getRevisions.
private SetMultimap<ObjectId, PatchSet.Id> getRevisions(OpenRepo or, Collection<ChangeData> cds) throws IntegrationException {
try {
List<String> refNames = new ArrayList<>(cds.size());
for (ChangeData cd : cds) {
Change c = cd.change();
if (c != null) {
refNames.add(c.currentPatchSetId().toRefName());
}
}
SetMultimap<ObjectId, PatchSet.Id> revisions = MultimapBuilder.hashKeys(cds.size()).hashSetValues(1).build();
for (Map.Entry<String, Ref> e : or.repo.getRefDatabase().exactRef(refNames.toArray(new String[refNames.size()])).entrySet()) {
revisions.put(e.getValue().getObjectId(), PatchSet.Id.fromRef(e.getKey()));
}
return revisions;
} catch (IOException | OrmException e) {
throw new IntegrationException("Failed to validate changes", e);
}
}
use of com.google.gerrit.server.query.change.ChangeData in project gerrit by GerritCodeReview.
the class MergeOp method validateChangeList.
private BranchBatch validateChangeList(OpenRepo or, Collection<ChangeData> submitted) throws IntegrationException {
logDebug("Validating {} changes", submitted.size());
Set<CodeReviewCommit> toSubmit = new LinkedHashSet<>(submitted.size());
SetMultimap<ObjectId, PatchSet.Id> revisions = getRevisions(or, submitted);
SubmitType submitType = null;
ChangeData choseSubmitTypeFrom = null;
for (ChangeData cd : submitted) {
Change.Id changeId = cd.getId();
ChangeControl ctl;
Change chg;
try {
ctl = cd.changeControl();
chg = cd.change();
} catch (OrmException e) {
commitStatus.logProblem(changeId, e);
continue;
}
SubmitType st = getSubmitType(cd);
if (st == null) {
commitStatus.logProblem(changeId, "No submit type for change");
continue;
}
if (submitType == null) {
submitType = st;
choseSubmitTypeFrom = cd;
} else if (st != submitType) {
commitStatus.problem(changeId, String.format("Change has submit type %s, but previously chose submit type %s " + "from change %s in the same batch", st, submitType, choseSubmitTypeFrom.getId()));
continue;
}
if (chg.currentPatchSetId() == null) {
String msg = "Missing current patch set on change";
logError(msg + " " + changeId);
commitStatus.problem(changeId, msg);
continue;
}
PatchSet ps;
Branch.NameKey destBranch = chg.getDest();
try {
ps = cd.currentPatchSet();
} catch (OrmException e) {
commitStatus.logProblem(changeId, e);
continue;
}
if (ps == null || ps.getRevision() == null || ps.getRevision().get() == null) {
commitStatus.logProblem(changeId, "Missing patch set or revision on change");
continue;
}
String idstr = ps.getRevision().get();
ObjectId id;
try {
id = ObjectId.fromString(idstr);
} catch (IllegalArgumentException e) {
commitStatus.logProblem(changeId, e);
continue;
}
if (!revisions.containsEntry(id, ps.getId())) {
// TODO this is actually an error, the branch is gone but we
// want to merge the issue. We can't safely do that if the
// tip is not reachable.
//
commitStatus.logProblem(changeId, "Revision " + idstr + " of patch set " + ps.getPatchSetId() + " does not match " + ps.getId().toRefName() + " for change");
continue;
}
CodeReviewCommit commit;
try {
commit = or.rw.parseCommit(id);
} catch (IOException e) {
commitStatus.logProblem(changeId, e);
continue;
}
// TODO(dborowitz): Consider putting ChangeData in CodeReviewCommit.
commit.setControl(ctl);
commit.setPatchsetId(ps.getId());
commitStatus.put(commit);
MergeValidators mergeValidators = mergeValidatorsFactory.create();
try {
mergeValidators.validatePreMerge(or.repo, commit, or.project, destBranch, ps.getId(), caller);
} catch (MergeValidationException mve) {
commitStatus.problem(changeId, mve.getMessage());
continue;
}
commit.add(or.canMergeFlag);
toSubmit.add(commit);
}
logDebug("Submitting on this run: {}", toSubmit);
return new AutoValue_MergeOp_BranchBatch(submitType, toSubmit);
}
use of com.google.gerrit.server.query.change.ChangeData in project gerrit by GerritCodeReview.
the class MergeOp method abandonAllOpenChangeForDeletedProject.
private void abandonAllOpenChangeForDeletedProject(Project.NameKey destProject) {
try {
for (ChangeData cd : internalChangeQuery.byProjectOpen(destProject)) {
try (BatchUpdate bu = batchUpdateFactory.create(db, destProject, internalUserFactory.create(), ts)) {
bu.setRequestId(submissionId);
bu.addOp(cd.getId(), new BatchUpdateOp() {
@Override
public boolean updateChange(ChangeContext ctx) throws OrmException {
Change change = ctx.getChange();
if (!change.getStatus().isOpen()) {
return false;
}
change.setStatus(Change.Status.ABANDONED);
ChangeMessage msg = ChangeMessagesUtil.newMessage(change.currentPatchSetId(), internalUserFactory.create(), change.getLastUpdatedOn(), ChangeMessagesUtil.TAG_MERGED, "Project was deleted.");
cmUtil.addChangeMessage(ctx.getDb(), ctx.getUpdate(change.currentPatchSetId()), msg);
return true;
}
});
try {
bu.execute();
} catch (UpdateException | RestApiException e) {
logWarn("Cannot abandon changes for deleted project " + destProject, e);
}
}
}
} catch (OrmException e) {
logWarn("Cannot abandon changes for deleted project " + destProject, e);
}
}
use of com.google.gerrit.server.query.change.ChangeData in project gerrit by GerritCodeReview.
the class MergeSuperSet method byCommitsOnBranchNotMerged.
private List<ChangeData> byCommitsOnBranchNotMerged(OpenRepo or, ReviewDb db, CurrentUser user, Branch.NameKey branch, Set<String> hashes) throws OrmException, IOException {
if (hashes.isEmpty()) {
return ImmutableList.of();
}
QueryKey k = QueryKey.create(branch, hashes);
List<ChangeData> cached = queryCache.get(k);
if (cached != null) {
return cached;
}
List<ChangeData> result = new ArrayList<>();
Iterable<ChangeData> destChanges = query().byCommitsOnBranchNotMerged(or.repo, db, branch, hashes);
for (ChangeData chd : destChanges) {
chd.changeControl(user);
result.add(chd);
}
queryCache.put(k, result);
return result;
}
use of com.google.gerrit.server.query.change.ChangeData in project gerrit by GerritCodeReview.
the class MergeSuperSet method topicClosure.
/**
* Completes {@code cs} with any additional changes from its topics
*
* <p>{@link #completeChangeSetIncludingTopics} calls this repeatedly, alternating with {@link
* #completeChangeSetWithoutTopic}, to discover what additional changes should be submitted with a
* change until the set stops growing.
*
* <p>{@code topicsSeen} and {@code visibleTopicsSeen} keep track of topics already explored to
* avoid wasted work.
*
* @return the resulting larger {@link ChangeSet}
*/
private ChangeSet topicClosure(ReviewDb db, ChangeSet cs, CurrentUser user, Set<String> topicsSeen, Set<String> visibleTopicsSeen) throws OrmException {
List<ChangeData> visibleChanges = new ArrayList<>();
List<ChangeData> nonVisibleChanges = new ArrayList<>();
for (ChangeData cd : cs.changes()) {
visibleChanges.add(cd);
String topic = cd.change().getTopic();
if (Strings.isNullOrEmpty(topic) || visibleTopicsSeen.contains(topic)) {
continue;
}
for (ChangeData topicCd : query().byTopicOpen(topic)) {
try {
topicCd.changeControl(user);
if (topicCd.changeControl().isVisible(db, topicCd)) {
visibleChanges.add(topicCd);
} else {
nonVisibleChanges.add(topicCd);
}
} catch (OrmException e) {
if (e.getCause() instanceof NoSuchChangeException) {
// Ignore and skip this change
} else {
throw e;
}
}
}
topicsSeen.add(topic);
visibleTopicsSeen.add(topic);
}
for (ChangeData cd : cs.nonVisibleChanges()) {
nonVisibleChanges.add(cd);
String topic = cd.change().getTopic();
if (Strings.isNullOrEmpty(topic) || topicsSeen.contains(topic)) {
continue;
}
for (ChangeData topicCd : query().byTopicOpen(topic)) {
topicCd.changeControl(user);
nonVisibleChanges.add(topicCd);
}
topicsSeen.add(topic);
}
return new ChangeSet(visibleChanges, nonVisibleChanges);
}
Aggregations