in rest-api/src/jetbrains/buildServer/server/rest/data/finder/impl/ChangeFinder.java [493:638]
public ItemHolder<SVcsModificationOrChangeDescriptor> getPrefilteredItems(@NotNull final Locator locator) {
final String internalVersion = locator.getSingleDimensionValue(INTERNAL_VERSION);
if (internalVersion != null) {
return wrapModifications(((VcsModificationHistoryEx)myVcsModificationHistory).findModificationsByVersion(internalVersion));
}
ValueCondition displayVersionCondition = ParameterCondition.createValueCondition(locator.lookupSingleDimensionValue(VERSION));
final String displayVersion = displayVersionCondition != null ? displayVersionCondition.getConstantValueIfSimpleEqualsCondition() : null;
if (displayVersion != null) {
locator.markUsed(VERSION);
return wrapModifications(((VcsModificationHistoryEx)myVcsModificationHistory).findModificationsByDisplayVersion(displayVersion));
}
Boolean personal = locator.lookupSingleDimensionValueAsBoolean(PERSONAL);
if (personal != null && personal) {
if (locator.lookupSingleDimensionValue(BUILD) == null && locator.lookupSingleDimensionValue(USER) == null) {
throw new BadRequestException("Filtering personal changes is supported only when '" + DIMENSION_ID + "', '" + USER + "' or '" + BUILD + "' dimensions are specified");
}
}
final String buildLocator = locator.getSingleDimensionValue(BUILD);
if (buildLocator != null) {
BuildPromotion buildFromBuildFinder;
try {
buildFromBuildFinder = myBuildPromotionFinder.getItem(buildLocator);
} catch (Exception e) {
if (!TeamCityProperties.getBoolean("rest.request.changes.legacySingleBuildSearch")) {
throw e;
}
//support for finished builds
//todo: use buildPromotionFinder here (ensure it also supports finished builds)
buildFromBuildFinder = myBuildFinder.getBuildPromotion(null, buildLocator); //THIS SHOULD NEVER HAPPEN
}
return wrapDescriptors(getBuildChangeDescriptors(buildFromBuildFinder, locator));
}
//pre-9.0 compatibility
final Long promotionLocator = locator.getSingleDimensionValueAsLong(PROMOTION);
if (promotionLocator != null) {
return wrapDescriptors(getBuildChangeDescriptors(myBuildPromotionFinder.getBuildPromotion(promotionLocator), locator));
}
final String parentChangeLocator = locator.getSingleDimensionValue(CHILD_CHANGE);
if (parentChangeLocator != null) {
final SVcsModification parentChange = getItem(parentChangeLocator).getSVcsModification();
return wrapModifications(getChangesWhichHasChild(parentChange, locator.getSingleDimensionValueAsLong(DIMENSION_LOOKUP_LIMIT)));
//todo: return iterator instead of processing lookup limit here
}
final String childChangeLocator = locator.getSingleDimensionValue(PARENT_CHANGE);
if (childChangeLocator != null) {
final SVcsModification parentChange = getItem(childChangeLocator).getSVcsModification();
return wrapModifications(getChangesWhichHasParent(parentChange, locator.getSingleDimensionValueAsLong(DIMENSION_LOOKUP_LIMIT)));
}
final String graphLocator = locator.getSingleDimensionValue(DAG_TRAVERSE);
if (graphLocator != null) {
final GraphFinder<SVcsModification> graphFinder = new GraphFinder<>(
locatorText -> getItems(locatorText).getEntries().stream().map(SVcsModificationOrChangeDescriptor::getSVcsModification).collect(Collectors.toList()),
new ChangesGraphTraverser()
);
graphFinder.setDefaultLookupLimit(1000L);
return wrapModifications(graphFinder.getItems(graphLocator).getEntries());
}
Long sinceChangeId = null;
final String sinceChangeLocator = locator.getSingleDimensionValue(SINCE_CHANGE);
if (sinceChangeLocator != null) {
sinceChangeId = getChangeIdBySinceChangeLocator(sinceChangeLocator);
}
SBuildType buildType = null;
final String buildTypeLocator = locator.getSingleDimensionValue(BUILD_TYPE); //todo: support multiple buildTypes here
if (buildTypeLocator != null) {
buildType = myBuildTypeFinder.getBuildType(null, buildTypeLocator, false);
}
Boolean pending = locator.getSingleDimensionValueAsBoolean(PENDING);
if (pending != null) {
if (pending) {
Stream<SVcsModificationOrChangeDescriptor> changes = getPendingChanges(buildType, locator);
return processor -> changes.allMatch(processor::processItem);
} else {
locator.markUnused(PENDING);
}
}
if (buildType != null) {
Stream<SVcsModificationOrChangeDescriptor> changes = getBranchChanges(buildType, SelectPrevBuildPolicy.SINCE_NULL_BUILD, locator);
return processor -> changes.allMatch(processor::processItem);
}
if (locator.lookupSingleDimensionValue(BRANCH) != null) {
throw new BadRequestException("Filtering changes by branch is only supported when buildType is specified.");
}
final String projectLocator = locator.getSingleDimensionValue(PROJECT);
if (projectLocator != null) {
return wrapModifications(getProjectChanges(myProjectFinder.getItem(projectLocator), sinceChangeId, false));
}
final String affectedProjectLocator = locator.getSingleDimensionValue(AFFECTED_PROJECT);
if (affectedProjectLocator != null) {
return wrapModifications(getProjectChanges(myProjectFinder.getItem(affectedProjectLocator), sinceChangeId, true));
}
final String userLocator = locator.getSingleDimensionValue(USER);
if (userLocator != null) {
final SUser user = myUserFinder.getItem(userLocator);
Stream<SVcsModification> modifications = myServiceLocator.getSingletonService(UserChangesFacade.class)
.getAllVcsModifications(user).stream()
.flatMap(this::modificationWithDuplicates)
.filter(myPermissionChecker::checkCanView);
return wrapModifications(modifications);
}
final String username = locator.getSingleDimensionValue(USERNAME);
if (username != null) {
Stream<SVcsModification> modifications = myServiceLocator.getSingletonService(VcsModificationsStorage.class)
.findModificationsByUsername(username).stream()
.flatMap(this::modificationWithDuplicates)
.filter(myPermissionChecker::checkCanView);
return wrapModifications(modifications);
}
final String vcsRootInstanceLocator = locator.getSingleDimensionValue(VCS_ROOT_INSTANCE);
if (vcsRootInstanceLocator != null) {
final VcsRootInstance vcsRootInstance = myVcsRootInstanceFinder.getItem(vcsRootInstanceLocator);
if (sinceChangeId != null) {
//todo: use lookupLimit here or otherwise limit processing
return wrapModifications(myVcsModificationHistory.getModificationsInRange(vcsRootInstance, sinceChangeId, null));
} else {
//todo: highly inefficient!
return wrapModifications(myVcsModificationHistory.getAllModifications(vcsRootInstance));
}
}
if (sinceChangeId != null) {
return wrapModifications(myVcsModificationHistory.getModificationsInRange(null, sinceChangeId, null)); //todo: use lookupLimit here or otherwise limit processing
}
return wrapModifications(((VcsModificationHistoryEx) myVcsModificationHistory)::processModifications); // ItemHolder
}