public Builds replaceBuilds()

in rest-api/src/jetbrains/buildServer/server/rest/request/BuildQueueRequest.java [168:234]


  public Builds replaceBuilds(Builds builds, @QueryParam("fields") String fields, @Context UriInfo uriInfo, @Context HttpServletRequest request){
    if (builds == null){
      throw new BadRequestException("List of builds should be posted.");
    }
    if (builds.getSubmittedBuilds() == null){
      throw new BadRequestException("Posted element should contain 'builds' sub-element.");
    }

    final jetbrains.buildServer.serverSide.BuildQueue buildQueue = myServiceLocator.getSingletonService(jetbrains.buildServer.serverSide.BuildQueue.class);
    final List<BuildPromotion> queuedBuildPromotions = CollectionsUtil.convertCollection(buildQueue.getItems(), new Converter<BuildPromotion, SQueuedBuild>() {
      public BuildPromotion createFrom(@NotNull final SQueuedBuild source) {
        return source.getBuildPromotion();
      }
    });
    final List<String> queuedBuildIds = CollectionsUtil.convertCollection(buildQueue.getItems(), new Converter<String, SQueuedBuild>() {
      public String createFrom(@NotNull final SQueuedBuild source) {
        return source.getItemId();
      }
    });
    buildQueue.removeItems(queuedBuildIds, myServiceLocator.getSingletonService(UserFinder.class).getCurrentUser(), null); //todo: consider providing comment here

    //TeamCity API issue: TW-34143
    if (!buildQueue.isQueueEmpty()) {
      throw new AuthorizationFailedException("Some builds were not canceled. Probably not sufficient permissions.");
    }

    //now delete the canceled builds
    for (BuildPromotion queuedBuildPromotion : queuedBuildPromotions) {
      final SBuild associatedBuild = queuedBuildPromotion.getAssociatedBuild();
      if (associatedBuild == null){
        throw new OperationException("After canceling a build with promotion id '" + queuedBuildPromotion.getId() + "' , no canceled build found to delete.");
      }
      DataProvider.deleteBuild(associatedBuild, myBeanContext.getSingletonService(BuildHistory.class));
    }

    // now queue

    final SUser user = myServiceLocator.getSingletonService(UserFinder.class).getCurrentUser();
    final Map<Long, Long> buildPromotionIdReplacements = new HashMap<Long, Long>();
    List<Build> buildsToTrigger = builds.getSubmittedBuilds();
    Map<Build, Exception> buildsWithErrors;
    while (true) {
      buildsWithErrors = triggerBuilds(buildsToTrigger, user, buildPromotionIdReplacements);
      if (buildsWithErrors.isEmpty() || buildsToTrigger.size() <= buildsWithErrors.size()) {
        //no errors or no builds triggered
        break;
      }
      buildsToTrigger = new ArrayList<Build>(buildsWithErrors.keySet());
      LOG.info("There was an error triggering " + buildsToTrigger.size() + " builds, will try again." + " Affected build ids: " + listBuildIds(buildsToTrigger));
      //repeat (dependnecies order might be relevant)
    }

    if (buildsWithErrors.size() != 0) {
      final StringBuilder buildListDetails = new StringBuilder();
      for (Map.Entry<Build, Exception> buildExceptionEntry : buildsWithErrors.entrySet()) {
        final Build build = buildExceptionEntry.getKey();
        //noinspection ThrowableResultOfMethodCallIgnored
        buildListDetails.append("Not able to add build").append(build.getPromotionIdOfSubmittedBuild() != null ? " with id '" + build.getPromotionIdOfSubmittedBuild() + "'" : "")
                        .append(" to the build queue due to error: ").append(buildExceptionEntry.getValue().toString());
        buildListDetails.append("\n");
      }

      throw new BadRequestException("Error triggering " + buildsWithErrors.size() + " out of " + builds.getSubmittedBuilds().size() + " builds: \n" +
                                    buildListDetails.substring(0, buildListDetails.length() - "\n".length()));
    }
    return getBuilds(null, fields, uriInfo, request);
  }