use of com.google.gerrit.server.project.NoSuchChangeException 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);
}
use of com.google.gerrit.server.project.NoSuchChangeException in project gerrit by GerritCodeReview.
the class ChangeRebuilderImpl method execute.
public Result execute(ReviewDb db, Change.Id changeId, NoteDbUpdateManager manager, boolean checkReadOnly) throws OrmException, IOException {
db = ReviewDbUtil.unwrapDb(db);
Change change = checkNoteDbState(ChangeNotes.readOneReviewDbChange(db, changeId));
if (change == null) {
throw new NoSuchChangeException(changeId);
}
final String oldNoteDbState = change.getNoteDbState();
Result r = manager.stageAndApplyDelta(change);
final String newNoteDbState = change.getNoteDbState();
try {
db.changes().atomicUpdate(changeId, new AtomicUpdate<Change>() {
@Override
public Change update(Change change) {
if (checkReadOnly) {
NoteDbChangeState.checkNotReadOnly(change, skewMs);
}
String currNoteDbState = change.getNoteDbState();
if (Objects.equals(currNoteDbState, newNoteDbState)) {
// Another thread completed the same rebuild we were about to.
throw new AbortUpdateException();
} else if (!Objects.equals(oldNoteDbState, currNoteDbState)) {
// Another thread updated the state to something else.
throw new ConflictingUpdateException(change, oldNoteDbState);
}
change.setNoteDbState(newNoteDbState);
return change;
}
});
} catch (ConflictingUpdateException e) {
// the other thread.
throw new OrmException(e.getMessage());
} catch (AbortUpdateException e) {
if (NoteDbChangeState.parse(changeId, newNoteDbState).isUpToDate(manager.getChangeRepo().cmds.getRepoRefCache(), manager.getAllUsersRepo().cmds.getRepoRefCache())) {
// Result was flushed to the repo by whatever thread won the race.
return r;
}
// If the state doesn't match, that means another thread attempted this
// rebuild, but failed. Fall through and try to update the ref again.
}
if (migration.failChangeWrites()) {
// results instead of reading from the repo.
throw new OrmException(NoteDbUpdateManager.CHANGES_READ_ONLY);
}
manager.execute();
return r;
}
use of com.google.gerrit.server.project.NoSuchChangeException in project gerrit by GerritCodeReview.
the class CatServlet method doGet.
@Override
protected void doGet(final HttpServletRequest req, final HttpServletResponse rsp) throws IOException {
String keyStr = req.getPathInfo();
// We shouldn't have to do this extra decode pass, but somehow we
// are now receiving our "^1" suffix as "%5E1", which confuses us
// downstream. Other times we get our embedded "," as "%2C", which
// is equally bad. And yet when these happen a "%2F" is left as-is,
// rather than escaped as "%252F", which makes me feel really really
// uncomfortable with a blind decode right here.
//
keyStr = Url.decode(keyStr);
if (!keyStr.startsWith("/")) {
rsp.sendError(HttpServletResponse.SC_NOT_FOUND);
return;
}
keyStr = keyStr.substring(1);
final Patch.Key patchKey;
final int side;
{
final int c = keyStr.lastIndexOf('^');
if (c == 0) {
rsp.sendError(HttpServletResponse.SC_NOT_FOUND);
return;
}
if (c < 0) {
side = 0;
} else {
try {
side = Integer.parseInt(keyStr.substring(c + 1));
keyStr = keyStr.substring(0, c);
} catch (NumberFormatException e) {
rsp.sendError(HttpServletResponse.SC_NOT_FOUND);
return;
}
}
try {
patchKey = Patch.Key.parse(keyStr);
} catch (NumberFormatException e) {
rsp.sendError(HttpServletResponse.SC_NOT_FOUND);
return;
}
}
final Change.Id changeId = patchKey.getParentKey().getParentKey();
String revision;
try {
final ReviewDb db = requestDb.get();
final ChangeControl control = changeControl.validateFor(db, changeId, userProvider.get());
if (patchKey.getParentKey().get() == 0) {
// change edit
try {
Optional<ChangeEdit> edit = changeEditUtil.byChange(control.getChange());
if (edit.isPresent()) {
revision = ObjectId.toString(edit.get().getEditCommit());
} else {
rsp.sendError(HttpServletResponse.SC_NOT_FOUND);
return;
}
} catch (AuthException e) {
rsp.sendError(HttpServletResponse.SC_NOT_FOUND);
return;
}
} else {
PatchSet patchSet = psUtil.get(db, control.getNotes(), patchKey.getParentKey());
if (patchSet == null) {
rsp.sendError(HttpServletResponse.SC_NOT_FOUND);
return;
}
revision = patchSet.getRevision().get();
}
} catch (NoSuchChangeException e) {
rsp.sendError(HttpServletResponse.SC_NOT_FOUND);
return;
} catch (OrmException e) {
getServletContext().log("Cannot query database", e);
rsp.sendError(HttpServletResponse.SC_INTERNAL_SERVER_ERROR);
return;
}
String path = patchKey.getFileName();
String restUrl = String.format("%s/changes/%d/revisions/%s/files/%s/download?parent=%d", req.getContextPath(), changeId.get(), revision, Url.encode(path), side);
rsp.sendRedirect(restUrl);
}
use of com.google.gerrit.server.project.NoSuchChangeException in project gerrit by GerritCodeReview.
the class EventBroker method isVisibleTo.
protected boolean isVisibleTo(Event event, CurrentUser user) throws OrmException {
if (event instanceof RefEvent) {
RefEvent refEvent = (RefEvent) event;
String ref = refEvent.getRefName();
if (PatchSet.isChangeRef(ref)) {
Change.Id cid = PatchSet.Id.fromRef(ref).getParentKey();
try {
Change change = notesFactory.createChecked(dbProvider.get(), refEvent.getProjectNameKey(), cid).getChange();
return isVisibleTo(change, user);
} catch (NoSuchChangeException e) {
log.debug("Change {} cannot be found, falling back on ref visibility check", cid.id);
}
}
return isVisibleTo(refEvent.getBranchNameKey(), user);
} else if (event instanceof ProjectEvent) {
return isVisibleTo(((ProjectEvent) event).getProjectNameKey(), user);
}
return true;
}
use of com.google.gerrit.server.project.NoSuchChangeException in project gerrit by GerritCodeReview.
the class ChangeNotes method rebuildAndOpen.
private LoadHandle rebuildAndOpen(Repository repo, ObjectId oldId) throws IOException {
Timer1.Context timer = args.metrics.autoRebuildLatency.start(CHANGES);
try {
Change.Id cid = getChangeId();
ReviewDb db = args.db.get();
ChangeRebuilder rebuilder = args.rebuilder.get();
NoteDbUpdateManager.Result r;
try (NoteDbUpdateManager manager = rebuilder.stage(db, cid)) {
if (manager == null) {
// May be null in tests.
return super.openHandle(repo, oldId);
}
manager.setRefLogMessage("Auto-rebuilding change");
r = manager.stageAndApplyDelta(change);
try {
rebuilder.execute(db, cid, manager);
repo.scanForRepoChanges();
} catch (OrmException | IOException e) {
// Rebuilding failed. Most likely cause is contention on one or more
// change refs; there are other types of errors that can happen during
// rebuilding, but generally speaking they should happen during stage(),
// not execute(). Assume that some other worker is going to successfully
// store the rebuilt state, which is deterministic given an input
// ChangeBundle.
//
// Parse notes from the staged result so we can return something useful
// to the caller instead of throwing.
log.debug("Rebuilding change {} failed: {}", getChangeId(), e.getMessage());
args.metrics.autoRebuildFailureCount.increment(CHANGES);
rebuildResult = checkNotNull(r);
checkNotNull(r.newState());
checkNotNull(r.staged());
return LoadHandle.create(ChangeNotesCommit.newStagedRevWalk(repo, r.staged().changeObjects()), r.newState().getChangeMetaId());
}
}
return LoadHandle.create(ChangeNotesCommit.newRevWalk(repo), r.newState().getChangeMetaId());
} catch (NoSuchChangeException e) {
return super.openHandle(repo, oldId);
} catch (OrmException e) {
throw new IOException(e);
} finally {
log.debug("Rebuilt change {} in project {} in {} ms", getChangeId(), getProjectName(), TimeUnit.MILLISECONDS.convert(timer.stop(), TimeUnit.NANOSECONDS));
}
}
Aggregations