use of com.google.gwtorm.server.OrmException in project gerrit by GerritCodeReview.
the class ConsistencyChecker method checkPatchSets.
private boolean checkPatchSets() {
List<PatchSet> all;
try {
// Iterate in descending order.
all = PS_ID_ORDER.sortedCopy(psUtil.byChange(db.get(), ctl.getNotes()));
} catch (OrmException e) {
return error("Failed to look up patch sets", e);
}
patchSetsBySha = MultimapBuilder.hashKeys(all.size()).treeSetValues(PS_ID_ORDER).build();
Map<String, Ref> refs;
try {
refs = repo.getRefDatabase().exactRef(all.stream().map(ps -> ps.getId().toRefName()).toArray(String[]::new));
} catch (IOException e) {
error("error reading refs", e);
refs = Collections.emptyMap();
}
List<DeletePatchSetFromDbOp> deletePatchSetOps = new ArrayList<>();
for (PatchSet ps : all) {
// Check revision format.
int psNum = ps.getId().get();
String refName = ps.getId().toRefName();
ObjectId objId = parseObjectId(ps.getRevision().get(), "patch set " + psNum);
if (objId == null) {
continue;
}
patchSetsBySha.put(objId, ps);
// Check ref existence.
ProblemInfo refProblem = null;
Ref ref = refs.get(refName);
if (ref == null) {
refProblem = problem("Ref missing: " + refName);
} else if (!objId.equals(ref.getObjectId())) {
String actual = ref.getObjectId() != null ? ref.getObjectId().name() : "null";
refProblem = problem(String.format("Expected %s to point to %s, found %s", ref.getName(), objId.name(), actual));
}
// Check object existence.
RevCommit psCommit = parseCommit(objId, String.format("patch set %d", psNum));
if (psCommit == null) {
if (fix != null && fix.deletePatchSetIfCommitMissing) {
deletePatchSetOps.add(new DeletePatchSetFromDbOp(lastProblem(), ps.getId()));
}
continue;
} else if (refProblem != null && fix != null) {
fixPatchSetRef(refProblem, ps);
}
if (ps.getId().equals(change().currentPatchSetId())) {
currPsCommit = psCommit;
}
}
// Delete any bad patch sets found above, in a single update.
deletePatchSets(deletePatchSetOps);
// Check for duplicates.
for (Map.Entry<ObjectId, Collection<PatchSet>> e : patchSetsBySha.asMap().entrySet()) {
if (e.getValue().size() > 1) {
problem(String.format("Multiple patch sets pointing to %s: %s", e.getKey().name(), Collections2.transform(e.getValue(), PatchSet::getPatchSetId)));
}
}
return currPs != null && currPsCommit != null;
}
use of com.google.gwtorm.server.OrmException in project gerrit by GerritCodeReview.
the class ConsistencyChecker method checkExpectMergedAs.
private void checkExpectMergedAs() {
ObjectId objId = parseObjectId(fix.expectMergedAs, "expected merged commit");
RevCommit commit = parseCommit(objId, "expected merged commit");
if (commit == null) {
return;
}
try {
if (!rw.isMergedInto(commit, tip)) {
problem(String.format("Expected merged commit %s is not merged into destination ref %s (%s)", commit.name(), change().getDest().get(), tip.name()));
return;
}
List<PatchSet.Id> thisCommitPsIds = new ArrayList<>();
for (Ref ref : repo.getRefDatabase().getRefs(REFS_CHANGES).values()) {
if (!ref.getObjectId().equals(commit)) {
continue;
}
PatchSet.Id psId = PatchSet.Id.fromRef(ref.getName());
if (psId == null) {
continue;
}
try {
Change c = notesFactory.createChecked(db.get(), change().getProject(), psId.getParentKey()).getChange();
if (!c.getDest().equals(change().getDest())) {
continue;
}
} catch (OrmException e) {
warn(e);
// Include this patch set; should cause an error below, which is good.
}
thisCommitPsIds.add(psId);
}
switch(thisCommitPsIds.size()) {
case 0:
// No patch set for this commit; insert one.
rw.parseBody(commit);
String changeId = Iterables.getFirst(commit.getFooterLines(FooterConstants.CHANGE_ID), null);
// Missing Change-Id footer is ok, but mismatched is not.
if (changeId != null && !changeId.equals(change().getKey().get())) {
problem(String.format("Expected merged commit %s has Change-Id: %s, but expected %s", commit.name(), changeId, change().getKey().get()));
return;
}
insertMergedPatchSet(commit, null, false);
break;
case 1:
// Existing patch set ref pointing to this commit.
PatchSet.Id id = thisCommitPsIds.get(0);
if (id.equals(change().currentPatchSetId())) {
// If it's the current patch set, we can just fix the status.
fixMerged(wrongChangeStatus(id, commit));
} else if (id.get() > change().currentPatchSetId().get()) {
// If it's newer than the current patch set, reuse this patch set
// ID when inserting a new merged patch set.
insertMergedPatchSet(commit, id, true);
} else {
// If it's older than the current patch set, just delete the old
// ref, and use a new ID when inserting a new merged patch set.
insertMergedPatchSet(commit, id, false);
}
break;
default:
problem(String.format("Multiple patch sets for expected merged commit %s: %s", commit.name(), intKeyOrdering().sortedCopy(thisCommitPsIds)));
break;
}
} catch (IOException e) {
error("Error looking up expected merged commit " + fix.expectMergedAs, e);
}
}
use of com.google.gwtorm.server.OrmException in project gerrit by GerritCodeReview.
the class ChangeKindCacheImpl method getChangeKindInternal.
private static ChangeKind getChangeKindInternal(ChangeKindCache cache, @Nullable RevWalk rw, @Nullable Config repoConfig, ChangeData change, PatchSet patch) {
ChangeKind kind = ChangeKind.REWORK;
// the repository.
if (patch.getId().get() > 1) {
try {
Collection<PatchSet> patchSetCollection = change.patchSets();
PatchSet priorPs = patch;
for (PatchSet ps : patchSetCollection) {
if (ps.getId().get() < patch.getId().get() && (ps.getId().get() > priorPs.getId().get() || priorPs == patch)) {
// We only want the previous patch set, so walk until the last one
priorPs = ps;
}
}
// and deletes the draft.
if (priorPs != patch) {
kind = cache.getChangeKind(change.project(), rw, repoConfig, ObjectId.fromString(priorPs.getRevision().get()), ObjectId.fromString(patch.getRevision().get()));
}
} catch (OrmException e) {
// Do nothing; assume we have a complex change
log.warn("Unable to get change kind for patchSet " + patch.getPatchSetId() + "of change " + change.getId(), e);
}
}
return kind;
}
use of com.google.gwtorm.server.OrmException in project gerrit by GerritCodeReview.
the class ChangeResource method prepareETag.
// This includes all information relevant for ETag computation
// unrelated to the UI.
public void prepareETag(Hasher h, CurrentUser user) {
h.putInt(JSON_FORMAT_VERSION).putLong(getChange().getLastUpdatedOn().getTime()).putInt(getChange().getRowVersion()).putInt(user.isIdentifiedUser() ? user.getAccountId().get() : 0);
if (user.isIdentifiedUser()) {
for (AccountGroup.UUID uuid : user.getEffectiveGroups().getKnownGroups()) {
h.putBytes(uuid.get().getBytes(UTF_8));
}
}
byte[] buf = new byte[20];
ObjectId noteId;
try {
noteId = getNotes().loadRevision();
} catch (OrmException e) {
// This ETag will be invalidated if it loads next time.
noteId = null;
}
hashObjectId(h, noteId, buf);
for (ProjectState p : control.getProjectControl().getProjectState().tree()) {
hashObjectId(h, p.getConfig().getRevision(), buf);
}
}
use of com.google.gwtorm.server.OrmException in project gerrit by GerritCodeReview.
the class AbandonUtil method abandonInactiveOpenChanges.
public void abandonInactiveOpenChanges(BatchUpdate.Factory updateFactory) {
if (cfg.getAbandonAfter() <= 0) {
return;
}
try {
String query = "status:new age:" + TimeUnit.MILLISECONDS.toMinutes(cfg.getAbandonAfter()) + "m";
if (!cfg.getAbandonIfMergeable()) {
query += " -is:mergeable";
}
List<ChangeData> changesToAbandon = queryProcessor.enforceVisibility(false).query(queryBuilder.parse(query)).entities();
ImmutableListMultimap.Builder<Project.NameKey, ChangeControl> builder = ImmutableListMultimap.builder();
for (ChangeData cd : changesToAbandon) {
ChangeControl control = cd.changeControl(internalUser);
builder.put(control.getProject().getNameKey(), control);
}
int count = 0;
ListMultimap<Project.NameKey, ChangeControl> abandons = builder.build();
String message = cfg.getAbandonMessage();
for (Project.NameKey project : abandons.keySet()) {
Collection<ChangeControl> changes = getValidChanges(abandons.get(project), query);
try {
abandon.batchAbandon(updateFactory, project, internalUser, changes, message);
count += changes.size();
} catch (Throwable e) {
StringBuilder msg = new StringBuilder("Failed to auto-abandon inactive change(s):");
for (ChangeControl change : changes) {
msg.append(" ").append(change.getId().get());
}
msg.append(".");
log.error(msg.toString(), e);
}
}
log.info(String.format("Auto-Abandoned %d of %d changes.", count, changesToAbandon.size()));
} catch (QueryParseException | OrmException e) {
log.error("Failed to query inactive open changes for auto-abandoning.", e);
}
}
Aggregations