@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); }
@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; }
@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(); }
@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); } } }