use of com.google.gerrit.reviewdb.client.RevId in project gerrit by GerritCodeReview.
the class ChangeNoteUtil method parseNote.
public List<Comment> parseNote(byte[] note, MutableInteger p, Change.Id changeId) throws ConfigInvalidException {
if (p.value >= note.length) {
return ImmutableList.of();
}
Set<Comment.Key> seen = new HashSet<>();
List<Comment> result = new ArrayList<>();
int sizeOfNote = note.length;
byte[] psb = PATCH_SET.getBytes(UTF_8);
byte[] bpsb = BASE_PATCH_SET.getBytes(UTF_8);
byte[] bpn = PARENT_NUMBER.getBytes(UTF_8);
RevId revId = new RevId(parseStringField(note, p, changeId, REVISION));
String fileName = null;
PatchSet.Id psId = null;
boolean isForBase = false;
Integer parentNumber = null;
while (p.value < sizeOfNote) {
boolean matchPs = match(note, p, psb);
boolean matchBase = match(note, p, bpsb);
if (matchPs) {
fileName = null;
psId = parsePsId(note, p, changeId, PATCH_SET);
isForBase = false;
} else if (matchBase) {
fileName = null;
psId = parsePsId(note, p, changeId, BASE_PATCH_SET);
isForBase = true;
if (match(note, p, bpn)) {
parentNumber = parseParentNumber(note, p, changeId);
}
} else if (psId == null) {
throw parseException(changeId, "missing %s or %s header", PATCH_SET, BASE_PATCH_SET);
}
Comment c = parseComment(note, p, fileName, psId, revId, isForBase, parentNumber);
fileName = c.key.filename;
if (!seen.add(c.key)) {
throw parseException(changeId, "multiple comments for %s in note", c.key);
}
result.add(c);
}
return result;
}
use of com.google.gerrit.reviewdb.client.RevId in project gerrit by GerritCodeReview.
the class ReceiveCommits method selectNewAndReplacedChangesFromMagicBranch.
private void selectNewAndReplacedChangesFromMagicBranch() {
logDebug("Finding new and replaced changes");
newChanges = new ArrayList<>();
ListMultimap<ObjectId, Ref> existing = changeRefsById();
GroupCollector groupCollector = GroupCollector.create(changeRefsById(), db, psUtil, notesFactory, project.getNameKey());
try {
RevCommit start = setUpWalkForSelectingChanges();
if (start == null) {
return;
}
LinkedHashMap<RevCommit, ChangeLookup> pending = new LinkedHashMap<>();
Set<Change.Key> newChangeIds = new HashSet<>();
int maxBatchChanges = receiveConfig.getEffectiveMaxBatchChangesLimit(user);
int total = 0;
int alreadyTracked = 0;
boolean rejectImplicitMerges = start.getParentCount() == 1 && projectCache.get(project.getNameKey()).isRejectImplicitMerges() && // late.
!magicBranch.merged;
Set<RevCommit> mergedParents;
if (rejectImplicitMerges) {
mergedParents = new HashSet<>();
} else {
mergedParents = null;
}
for (; ; ) {
RevCommit c = rp.getRevWalk().next();
if (c == null) {
break;
}
total++;
rp.getRevWalk().parseBody(c);
String name = c.name();
groupCollector.visit(c);
Collection<Ref> existingRefs = existing.get(c);
if (rejectImplicitMerges) {
Collections.addAll(mergedParents, c.getParents());
mergedParents.remove(c);
}
boolean commitAlreadyTracked = !existingRefs.isEmpty();
if (commitAlreadyTracked) {
alreadyTracked++;
// different target branch.
for (Ref ref : existingRefs) {
updateGroups.add(new UpdateGroupsRequest(ref, c));
}
if (!(newChangeForAllNotInTarget || magicBranch.base != null)) {
continue;
}
}
List<String> idList = c.getFooterLines(CHANGE_ID);
String idStr = !idList.isEmpty() ? idList.get(idList.size() - 1).trim() : null;
if (idStr != null) {
pending.put(c, new ChangeLookup(c, new Change.Key(idStr)));
} else {
pending.put(c, new ChangeLookup(c));
}
int n = pending.size() + newChanges.size();
if (maxBatchChanges != 0 && n > maxBatchChanges) {
logDebug("{} changes exceeds limit of {}", n, maxBatchChanges);
reject(magicBranch.cmd, "the number of pushed changes in a batch exceeds the max limit " + maxBatchChanges);
newChanges = Collections.emptyList();
return;
}
if (commitAlreadyTracked) {
boolean changeExistsOnDestBranch = false;
for (ChangeData cd : pending.get(c).destChanges) {
if (cd.change().getDest().equals(magicBranch.dest)) {
changeExistsOnDestBranch = true;
break;
}
}
if (changeExistsOnDestBranch) {
continue;
}
logDebug("Creating new change for {} even though it is already tracked", name);
}
if (!validCommit(rp.getRevWalk(), magicBranch.ctl, magicBranch.cmd, c)) {
// Not a change the user can propose? Abort as early as possible.
newChanges = Collections.emptyList();
logDebug("Aborting early due to invalid commit");
return;
}
// Don't allow merges to be uploaded in commit chain via all-not-in-target
if (newChangeForAllNotInTarget && c.getParentCount() > 1) {
reject(magicBranch.cmd, "Pushing merges in commit chains with 'all not in target' is not allowed,\n" + "to override please set the base manually");
logDebug("Rejecting merge commit {} with newChangeForAllNotInTarget", name);
// TODO(dborowitz): Should we early return here?
}
if (idList.isEmpty()) {
newChanges.add(new CreateRequest(c, magicBranch.dest.get()));
continue;
}
}
logDebug("Finished initial RevWalk with {} commits total: {} already" + " tracked, {} new changes with no Change-Id, and {} deferred" + " lookups", total, alreadyTracked, newChanges.size(), pending.size());
if (rejectImplicitMerges) {
rejectImplicitMerges(mergedParents);
}
for (Iterator<ChangeLookup> itr = pending.values().iterator(); itr.hasNext(); ) {
ChangeLookup p = itr.next();
if (p.changeKey == null) {
continue;
}
if (newChangeIds.contains(p.changeKey)) {
logDebug("Multiple commits with Change-Id {}", p.changeKey);
reject(magicBranch.cmd, SAME_CHANGE_ID_IN_MULTIPLE_CHANGES);
newChanges = Collections.emptyList();
return;
}
List<ChangeData> changes = p.destChanges;
if (changes.size() > 1) {
logDebug("Multiple changes in branch {} with Change-Id {}: {}", magicBranch.dest, p.changeKey, changes.stream().map(cd -> cd.getId().toString()).collect(joining()));
// WTF, multiple changes in this branch have the same key?
// Since the commit is new, the user should recreate it with
// a different Change-Id. In practice, we should never see
// this error message as Change-Id should be unique per branch.
//
reject(magicBranch.cmd, p.changeKey.get() + " has duplicates");
newChanges = Collections.emptyList();
return;
}
if (changes.size() == 1) {
// Schedule as a replacement to this one matching change.
//
RevId currentPs = changes.get(0).currentPatchSet().getRevision();
// If Commit is already current PatchSet of target Change.
if (p.commit.name().equals(currentPs.get())) {
if (pending.size() == 1) {
// There are no commits left to check, all commits in pending were already
// current PatchSet of the corresponding target changes.
reject(magicBranch.cmd, "commit(s) already exists (as current patchset)");
} else {
// Commit is already current PatchSet.
// Remove from pending and try next commit.
itr.remove();
continue;
}
}
if (requestReplace(magicBranch.cmd, false, changes.get(0).change(), p.commit)) {
continue;
}
newChanges = Collections.emptyList();
return;
}
if (changes.size() == 0) {
if (!isValidChangeId(p.changeKey.get())) {
reject(magicBranch.cmd, "invalid Change-Id");
newChanges = Collections.emptyList();
return;
}
// double check against the existing refs
if (foundInExistingRef(existing.get(p.commit))) {
if (pending.size() == 1) {
reject(magicBranch.cmd, "commit(s) already exists (as current patchset)");
newChanges = Collections.emptyList();
return;
}
itr.remove();
continue;
}
newChangeIds.add(p.changeKey);
}
newChanges.add(new CreateRequest(p.commit, magicBranch.dest.get()));
}
logDebug("Finished deferred lookups with {} updates and {} new changes", replaceByChange.size(), newChanges.size());
} catch (IOException e) {
// Should never happen, the core receive process would have
// identified the missing object earlier before we got control.
//
magicBranch.cmd.setResult(REJECTED_MISSING_OBJECT);
logError("Invalid pack upload; one or more objects weren't sent", e);
newChanges = Collections.emptyList();
return;
} catch (OrmException e) {
logError("Cannot query database to locate prior changes", e);
reject(magicBranch.cmd, "database error");
newChanges = Collections.emptyList();
return;
}
if (newChanges.isEmpty() && replaceByChange.isEmpty()) {
reject(magicBranch.cmd, "no new changes");
return;
}
if (!newChanges.isEmpty() && magicBranch.edit) {
reject(magicBranch.cmd, "edit is not supported for new changes");
return;
}
try {
SortedSetMultimap<ObjectId, String> groups = groupCollector.getGroups();
List<Integer> newIds = seq.nextChangeIds(newChanges.size());
for (int i = 0; i < newChanges.size(); i++) {
CreateRequest create = newChanges.get(i);
create.setChangeId(newIds.get(i));
create.groups = ImmutableList.copyOf(groups.get(create.commit));
}
for (ReplaceRequest replace : replaceByChange.values()) {
replace.groups = ImmutableList.copyOf(groups.get(replace.newCommitId));
}
for (UpdateGroupsRequest update : updateGroups) {
update.groups = ImmutableList.copyOf((groups.get(update.commit)));
}
logDebug("Finished updating groups from GroupCollector");
} catch (OrmException e) {
logError("Error collecting groups for changes", e);
reject(magicBranch.cmd, "internal server error");
return;
}
}
Aggregations