Esempio n. 1
0
    @Override
    public void updateRepoImpl(RepoContext ctx)
        throws IntegrationException, InvalidChangeOperationException, RestApiException, IOException,
            OrmException {
      // TODO(dborowitz): args.rw is needed because it's a CodeReviewRevWalk.
      // When hoisting BatchUpdate into MergeOp, we will need to teach
      // BatchUpdate how to produce CodeReviewRevWalks.
      if (args.mergeUtil.canFastForward(
          args.mergeSorter, args.mergeTip.getCurrentTip(), args.rw, toMerge)) {
        toMerge.setStatusCode(CommitMergeStatus.CLEAN_MERGE);
        args.mergeTip.moveTipTo(toMerge, toMerge);
        acceptMergeTip(args.mergeTip);
        return;
      }

      // Stale read of patch set is ok; see comments in RebaseChangeOp.
      PatchSet origPs =
          args.psUtil.get(ctx.getDb(), toMerge.getControl().getNotes(), toMerge.getPatchsetId());
      rebaseOp =
          args.rebaseFactory
              .create(toMerge.getControl(), origPs, args.mergeTip.getCurrentTip().name())
              .setRunHooks(false)
              // Bypass approval copier since SubmitStrategyOp copy all approvals
              // later anyway.
              .setCopyApprovals(false)
              .setValidatePolicy(CommitValidators.Policy.NONE);
      try {
        rebaseOp.updateRepo(ctx);
      } catch (MergeConflictException | NoSuchChangeException e) {
        toMerge.setStatusCode(CommitMergeStatus.REBASE_MERGE_CONFLICT);
        throw new IntegrationException(
            "Cannot rebase " + toMerge.name() + ": " + e.getMessage(), e);
      }
      newCommit = args.rw.parseCommit(rebaseOp.getRebasedCommit());
      newCommit.copyFrom(toMerge);
      newCommit.setStatusCode(CommitMergeStatus.CLEAN_REBASE);
      newCommit.setPatchsetId(rebaseOp.getPatchSetId());
      args.mergeTip.moveTipTo(newCommit, newCommit);
      args.commits.put(args.mergeTip.getCurrentTip());
      acceptMergeTip(args.mergeTip);
    }
Esempio n. 2
0
  @Override
  public List<SubmitStrategyOp> buildOps(Collection<CodeReviewCommit> toMerge)
      throws IntegrationException {
    List<CodeReviewCommit> sorted = sort(toMerge);
    List<SubmitStrategyOp> ops = new ArrayList<>(sorted.size());
    boolean first = true;

    while (!sorted.isEmpty()) {
      CodeReviewCommit n = sorted.remove(0);
      if (first && args.mergeTip.getInitialTip() == null) {
        ops.add(new RebaseUnbornRootOp(n));
      } else if (n.getParentCount() == 0) {
        ops.add(new RebaseRootOp(n));
      } else if (n.getParentCount() == 1) {
        ops.add(new RebaseOneOp(n));
      } else {
        ops.add(new RebaseMultipleParentsOp(n));
      }
      first = false;
    }
    return ops;
  }
Esempio n. 3
0
    @Override
    public PatchSet updateChangeImpl(ChangeContext ctx)
        throws NoSuchChangeException, ResourceConflictException, OrmException, IOException {
      if (rebaseOp == null) {
        // Took the fast-forward option, nothing to do.
        return null;
      }

      rebaseOp.updateChange(ctx);
      ctx.getChange()
          .setCurrentPatchSet(
              args.patchSetInfoFactory.get(args.rw, newCommit, rebaseOp.getPatchSetId()));
      newCommit.setControl(ctx.getControl());
      return rebaseOp.getPatchSet();
    }
Esempio n. 4
0
    @Override
    public void onPreMerge(
        final Repository repo,
        final CodeReviewCommit commit,
        final ProjectState destProject,
        final Branch.NameKey destBranch,
        final PatchSet.Id patchSetId)
        throws MergeValidationException {
      if (RefNames.REFS_CONFIG.equals(destBranch.get())) {
        final Project.NameKey newParent;
        try {
          ProjectConfig cfg = new ProjectConfig(destProject.getProject().getNameKey());
          cfg.load(repo, commit);
          newParent = cfg.getProject().getParent(allProjectsName);
          final Project.NameKey oldParent = destProject.getProject().getParent(allProjectsName);
          if (oldParent == null) {
            // update of the 'All-Projects' project
            if (newParent != null) {
              throw new MergeValidationException(ROOT_NO_PARENT);
            }
          } else {
            if (!oldParent.equals(newParent)) {
              PatchSetApproval psa = approvalsUtil.getSubmitter(db, commit.notes(), patchSetId);
              if (psa == null) {
                throw new MergeValidationException(SET_BY_ADMIN);
              }
              final IdentifiedUser submitter = identifiedUserFactory.create(psa.getAccountId());
              if (!submitter.getCapabilities().canAdministrateServer()) {
                throw new MergeValidationException(SET_BY_ADMIN);
              }

              if (projectCache.get(newParent) == null) {
                throw new MergeValidationException(PARENT_NOT_FOUND);
              }
            }
          }

          for (Entry<ProjectConfigEntry> e : pluginConfigEntries) {
            PluginConfig pluginCfg = cfg.getPluginConfig(e.getPluginName());
            ProjectConfigEntry configEntry = e.getProvider().get();

            String value = pluginCfg.getString(e.getExportName());
            String oldValue =
                destProject
                    .getConfig()
                    .getPluginConfig(e.getPluginName())
                    .getString(e.getExportName());

            if ((value == null ? oldValue != null : !value.equals(oldValue))
                && !configEntry.isEditable(destProject)) {
              throw new MergeValidationException(PLUGIN_VALUE_NOT_EDITABLE);
            }

            if (ProjectConfigEntry.Type.LIST.equals(configEntry.getType())
                && value != null
                && !configEntry.getPermittedValues().contains(value)) {
              throw new MergeValidationException(PLUGIN_VALUE_NOT_PERMITTED);
            }
          }
        } catch (ConfigInvalidException | IOException e) {
          throw new MergeValidationException(INVALID_CONFIG);
        }
      }
    }