Search in sources :

Example 6 with InvalidChangeOperationException

use of com.google.gerrit.server.project.InvalidChangeOperationException in project gerrit by GerritCodeReview.

the class ChangeEditModifier method rebaseEdit.

/**
 * Rebase change edit on latest patch set
 *
 * @param repository the affected Git repository
 * @param notes the {@link ChangeNotes} of the change whose change edit should be rebased
 * @throws AuthException if the user isn't authenticated or not allowed to use change edits
 * @throws InvalidChangeOperationException if a change edit doesn't exist for the specified
 *     change, the change edit is already based on the latest patch set, or the change represents
 *     the root commit
 */
public void rebaseEdit(Repository repository, ChangeNotes notes) throws AuthException, InvalidChangeOperationException, IOException, PermissionBackendException, ResourceConflictException {
    assertCanEdit(notes);
    Optional<ChangeEdit> optionalChangeEdit = lookupChangeEdit(notes);
    if (!optionalChangeEdit.isPresent()) {
        throw new InvalidChangeOperationException(String.format("No change edit exists for change %s", notes.getChangeId()));
    }
    ChangeEdit changeEdit = optionalChangeEdit.get();
    PatchSet currentPatchSet = lookupCurrentPatchSet(notes);
    if (isBasedOn(changeEdit, currentPatchSet)) {
        throw new InvalidChangeOperationException(String.format("Change edit for change %s is already based on latest patch set %s", notes.getChangeId(), currentPatchSet.id()));
    }
    rebase(repository, changeEdit, currentPatchSet);
}
Also used : InvalidChangeOperationException(com.google.gerrit.server.project.InvalidChangeOperationException) PatchSet(com.google.gerrit.entities.PatchSet)

Example 7 with InvalidChangeOperationException

use of com.google.gerrit.server.project.InvalidChangeOperationException in project gerrit by GerritCodeReview.

the class ChangeEditModifier method modifyCommit.

private ChangeEdit modifyCommit(Repository repository, ChangeNotes notes, ModificationIntention modificationIntention, CommitModification commitModification) throws AuthException, BadRequestException, IOException, InvalidChangeOperationException, PermissionBackendException, ResourceConflictException {
    assertCanEdit(notes);
    Optional<ChangeEdit> optionalChangeEdit = lookupChangeEdit(notes);
    EditBehavior editBehavior = optionalChangeEdit.<EditBehavior>map(changeEdit -> new ExistingEditBehavior(changeEdit, noteDbEdits)).orElseGet(() -> new NewEditBehavior(noteDbEdits));
    ModificationTarget modificationTarget = editBehavior.getModificationTarget(notes, modificationIntention);
    RevCommit commitToModify = modificationTarget.getCommit(repository);
    ObjectId newTreeId = createNewTree(repository, commitToModify, commitModification.treeModifications());
    newTreeId = editBehavior.mergeTreesIfNecessary(repository, newTreeId, commitToModify);
    PatchSet basePatchset = modificationTarget.getBasePatchset();
    RevCommit basePatchsetCommit = NoteDbEdits.lookupCommit(repository, basePatchset.commitId());
    boolean changeIdRequired = projectCache.get(notes.getChange().getProject()).orElseThrow(illegalState(notes.getChange().getProject())).is(BooleanProjectConfig.REQUIRE_CHANGE_ID);
    String currentChangeId = notes.getChange().getKey().get();
    String newCommitMessage = createNewCommitMessage(changeIdRequired, currentChangeId, editBehavior, commitModification, commitToModify);
    newCommitMessage = editBehavior.mergeCommitMessageIfNecessary(newCommitMessage, commitToModify);
    Optional<ChangeEdit> unmodifiedEdit = editBehavior.getEditIfNoModification(newTreeId, newCommitMessage);
    if (unmodifiedEdit.isPresent()) {
        return unmodifiedEdit.get();
    }
    Instant nowTimestamp = TimeUtil.now();
    ObjectId newEditCommit = createCommit(repository, basePatchsetCommit, newTreeId, newCommitMessage, nowTimestamp);
    return editBehavior.updateEditInStorage(repository, notes, basePatchset, newEditCommit, nowTimestamp);
}
Also used : CommitMessageUtil(com.google.gerrit.server.util.CommitMessageUtil) ObjectInserter(org.eclipse.jgit.lib.ObjectInserter) ProjectCache(com.google.gerrit.server.project.ProjectCache) Inject(com.google.inject.Inject) RawTextComparator(org.eclipse.jgit.diff.RawTextComparator) ChangeFileContentModification(com.google.gerrit.server.edit.tree.ChangeFileContentModification) ReceiveCommand(org.eclipse.jgit.transport.ReceiveCommand) InvalidPathException(org.eclipse.jgit.dircache.InvalidPathException) BadRequestException(com.google.gerrit.extensions.restapi.BadRequestException) PermissionBackend(com.google.gerrit.server.permissions.PermissionBackend) RevWalk(org.eclipse.jgit.revwalk.RevWalk) MergeConflictException(com.google.gerrit.extensions.restapi.MergeConflictException) ChangeIndexer(com.google.gerrit.server.index.change.ChangeIndexer) InvalidChangeOperationException(com.google.gerrit.server.project.InvalidChangeOperationException) RefNames(com.google.gerrit.entities.RefNames) AuthException(com.google.gerrit.extensions.restapi.AuthException) RawText(org.eclipse.jgit.diff.RawText) RawInput(com.google.gerrit.extensions.restapi.RawInput) MergeChunk(org.eclipse.jgit.merge.MergeChunk) MergeAlgorithm(org.eclipse.jgit.merge.MergeAlgorithm) TimeZone(java.util.TimeZone) RefUpdate(org.eclipse.jgit.lib.RefUpdate) Instant(java.time.Instant) NullProgressMonitor(org.eclipse.jgit.lib.NullProgressMonitor) MergeStrategy(org.eclipse.jgit.merge.MergeStrategy) RevTree(org.eclipse.jgit.revwalk.RevTree) Objects(java.util.Objects) PersonIdent(org.eclipse.jgit.lib.PersonIdent) List(java.util.List) BatchRefUpdate(org.eclipse.jgit.lib.BatchRefUpdate) BooleanProjectConfig(com.google.gerrit.entities.BooleanProjectConfig) Optional(java.util.Optional) Singleton(com.google.inject.Singleton) PermissionBackendException(com.google.gerrit.server.permissions.PermissionBackendException) RevCommit(org.eclipse.jgit.revwalk.RevCommit) ChangePermission(com.google.gerrit.server.permissions.ChangePermission) CommitBuilder(org.eclipse.jgit.lib.CommitBuilder) Change(com.google.gerrit.entities.Change) PatchSet(com.google.gerrit.entities.PatchSet) ChangeUtil(com.google.gerrit.server.ChangeUtil) LockFailureException(com.google.gerrit.git.LockFailureException) Charsets(com.google.common.base.Charsets) TreeModification(com.google.gerrit.server.edit.tree.TreeModification) SupportedAlgorithm(org.eclipse.jgit.diff.DiffAlgorithm.SupportedAlgorithm) ProjectCache.illegalState(com.google.gerrit.server.project.ProjectCache.illegalState) CurrentUser(com.google.gerrit.server.CurrentUser) TreeCreator(com.google.gerrit.server.edit.tree.TreeCreator) ChangeNotes(com.google.gerrit.server.notedb.ChangeNotes) IOException(java.io.IOException) ThreeWayMerger(org.eclipse.jgit.merge.ThreeWayMerger) DiffAlgorithm(org.eclipse.jgit.diff.DiffAlgorithm) DeleteFileModification(com.google.gerrit.server.edit.tree.DeleteFileModification) RenameFileModification(com.google.gerrit.server.edit.tree.RenameFileModification) ObjectId(org.eclipse.jgit.lib.ObjectId) MergeResult(org.eclipse.jgit.merge.MergeResult) RestoreFileModification(com.google.gerrit.server.edit.tree.RestoreFileModification) Provider(com.google.inject.Provider) ResourceConflictException(com.google.gerrit.extensions.restapi.ResourceConflictException) IdentifiedUser(com.google.gerrit.server.IdentifiedUser) Project(com.google.gerrit.entities.Project) TimeUtil(com.google.gerrit.server.util.time.TimeUtil) PatchSetUtil(com.google.gerrit.server.PatchSetUtil) GerritPersonIdent(com.google.gerrit.server.GerritPersonIdent) Repository(org.eclipse.jgit.lib.Repository) ObjectId(org.eclipse.jgit.lib.ObjectId) Instant(java.time.Instant) PatchSet(com.google.gerrit.entities.PatchSet) RevCommit(org.eclipse.jgit.revwalk.RevCommit)

Example 8 with InvalidChangeOperationException

use of com.google.gerrit.server.project.InvalidChangeOperationException in project gerrit by GerritCodeReview.

the class CherryPickChange method cherryPick.

/**
 * This function can be called directly to cherry-pick a change (or commit if sourceChange is
 * null) with a few other parameters that are especially useful for cherry-picking a commit that
 * is the revert-of another change.
 *
 * @param sourceChange Change to cherry pick. Can be null, and then the function will only cherry
 *     pick a commit.
 * @param project Project name
 * @param sourceCommit Id of the commit to be cherry picked.
 * @param input Input object for different configurations of cherry pick.
 * @param dest Destination branch for the cherry pick.
 * @param timestamp the current timestamp.
 * @param revertedChange The id of the change that is reverted. This is used for the "revertOf"
 *     field to mark the created cherry pick change as "revertOf" the original change that was
 *     reverted.
 * @param changeIdForNewChange The Change-Id that the new change of the cherry pick will have.
 * @param idForNewChange The ID that the new change of the cherry pick will have. If provided and
 *     the cherry-pick doesn't result in creating a new change, then
 *     InvalidChangeOperationException is thrown.
 * @return Result object that describes the cherry pick.
 * @throws IOException Unable to open repository or read from the database.
 * @throws InvalidChangeOperationException Parent or branch don't exist, or two changes with same
 *     key exist in the branch. Also thrown when idForNewChange is not null but cherry-pick only
 *     creates a new patchset rather than a new change.
 * @throws UpdateException Problem updating the database using batchUpdateFactory.
 * @throws RestApiException Error such as invalid SHA1
 * @throws ConfigInvalidException Can't find account to notify.
 * @throws NoSuchProjectException Can't find project state.
 */
public Result cherryPick(@Nullable Change sourceChange, Project.NameKey project, ObjectId sourceCommit, CherryPickInput input, BranchNameKey dest, Instant timestamp, @Nullable Change.Id revertedChange, @Nullable ObjectId changeIdForNewChange, @Nullable Change.Id idForNewChange, @Nullable Boolean workInProgress) throws IOException, InvalidChangeOperationException, UpdateException, RestApiException, ConfigInvalidException, NoSuchProjectException {
    IdentifiedUser identifiedUser = user.get();
    try (Repository git = gitManager.openRepository(project);
        // before patch sets are updated.
        ObjectInserter oi = git.newObjectInserter();
        ObjectReader reader = oi.newReader();
        CodeReviewRevWalk revWalk = CodeReviewCommit.newRevWalk(reader)) {
        Ref destRef = git.getRefDatabase().exactRef(dest.branch());
        if (destRef == null) {
            throw new InvalidChangeOperationException(String.format("Branch %s does not exist.", dest.branch()));
        }
        RevCommit baseCommit = getBaseCommit(destRef, project.get(), revWalk, input.base);
        CodeReviewCommit commitToCherryPick = revWalk.parseCommit(sourceCommit);
        if (input.parent <= 0 || input.parent > commitToCherryPick.getParentCount()) {
            throw new InvalidChangeOperationException(String.format("Cherry Pick: Parent %s does not exist. Please specify a parent in" + " range [1, %s].", input.parent, commitToCherryPick.getParentCount()));
        }
        // If the commit message is not set, the commit message of the source commit will be used.
        String commitMessage = Strings.nullToEmpty(input.message);
        commitMessage = commitMessage.isEmpty() ? commitToCherryPick.getFullMessage() : commitMessage;
        String destChangeId = getDestinationChangeId(commitMessage, changeIdForNewChange);
        ChangeData destChange = null;
        if (destChangeId != null) {
            // If "idForNewChange" is not null we must fail, since we are not expecting an already
            // existing change.
            destChange = getDestChangeWithVerification(destChangeId, dest, idForNewChange != null);
        }
        if (changeIdForNewChange != null) {
            // If Change-Id was explicitly provided for the new change, override the value in commit
            // message.
            commitMessage = ChangeIdUtil.insertId(commitMessage, changeIdForNewChange, true);
        } else if (destChangeId == null) {
            // If commit message did not specify Change-Id, generate a new one and insert to the
            // message.
            commitMessage = ChangeIdUtil.insertId(commitMessage, CommitMessageUtil.generateChangeId(), true);
        }
        commitMessage = CommitMessageUtil.checkAndSanitizeCommitMessage(commitMessage);
        CodeReviewCommit cherryPickCommit;
        ProjectState projectState = projectCache.get(dest.project()).orElseThrow(noSuchProject(dest.project()));
        PersonIdent committerIdent = identifiedUser.newCommitterIdent(timestamp, serverTimeZone);
        try {
            MergeUtil mergeUtil;
            if (input.allowConflicts) {
                // allowConflicts requires to use content merge
                mergeUtil = mergeUtilFactory.create(projectState, true);
            } else {
                // use content merge only if it's configured on the project
                mergeUtil = mergeUtilFactory.create(projectState);
            }
            cherryPickCommit = mergeUtil.createCherryPickFromCommit(oi, git.getConfig(), baseCommit, commitToCherryPick, committerIdent, commitMessage, revWalk, input.parent - 1, input.allowEmpty, input.allowConflicts);
            oi.flush();
        } catch (MergeIdenticalTreeException | MergeConflictException e) {
            throw new IntegrationConflictException("Cherry pick failed: " + e.getMessage(), e);
        }
        try (BatchUpdate bu = batchUpdateFactory.create(project, identifiedUser, timestamp)) {
            bu.setRepository(git, revWalk, oi);
            bu.setNotify(resolveNotify(input));
            Change.Id changeId;
            String newTopic = null;
            if (input.topic != null) {
                newTopic = Strings.emptyToNull(input.topic.trim());
            }
            if (newTopic == null && sourceChange != null && !Strings.isNullOrEmpty(sourceChange.getTopic())) {
                newTopic = sourceChange.getTopic() + "-" + dest.shortName();
            }
            if (destChange != null) {
                // The change key exists on the destination branch. The cherry pick
                // will be added as a new patch set.
                changeId = insertPatchSet(bu, git, destChange.notes(), cherryPickCommit, sourceChange, newTopic, input, workInProgress);
            } else {
                // Change key not found on destination branch. We can create a new
                // change.
                changeId = createNewChange(bu, cherryPickCommit, dest.branch(), newTopic, project, sourceChange, sourceCommit, input, revertedChange, idForNewChange, workInProgress);
            }
            bu.execute();
            return Result.create(changeId, cherryPickCommit.getFilesWithGitConflicts());
        }
    }
}
Also used : InvalidChangeOperationException(com.google.gerrit.server.project.InvalidChangeOperationException) CodeReviewRevWalk(com.google.gerrit.server.git.CodeReviewCommit.CodeReviewRevWalk) Change(com.google.gerrit.entities.Change) IdentifiedUser(com.google.gerrit.server.IdentifiedUser) CodeReviewCommit(com.google.gerrit.server.git.CodeReviewCommit) ChangeData(com.google.gerrit.server.query.change.ChangeData) MergeIdenticalTreeException(com.google.gerrit.server.submit.MergeIdenticalTreeException) BatchUpdate(com.google.gerrit.server.update.BatchUpdate) Repository(org.eclipse.jgit.lib.Repository) Ref(org.eclipse.jgit.lib.Ref) MergeConflictException(com.google.gerrit.extensions.restapi.MergeConflictException) ObjectInserter(org.eclipse.jgit.lib.ObjectInserter) PersonIdent(org.eclipse.jgit.lib.PersonIdent) GerritPersonIdent(com.google.gerrit.server.GerritPersonIdent) MergeUtil(com.google.gerrit.server.git.MergeUtil) ObjectReader(org.eclipse.jgit.lib.ObjectReader) ProjectState(com.google.gerrit.server.project.ProjectState) IntegrationConflictException(com.google.gerrit.server.submit.IntegrationConflictException) RevCommit(org.eclipse.jgit.revwalk.RevCommit)

Example 9 with InvalidChangeOperationException

use of com.google.gerrit.server.project.InvalidChangeOperationException in project gerrit by GerritCodeReview.

the class CherryPickCommit method apply.

@Override
public Response<ChangeInfo> apply(CommitResource rsrc, CherryPickInput input) throws IOException, UpdateException, RestApiException, PermissionBackendException, ConfigInvalidException, NoSuchProjectException {
    String destination = Strings.nullToEmpty(input.destination).trim();
    input.parent = input.parent == null ? 1 : input.parent;
    Project.NameKey projectName = rsrc.getProjectState().getNameKey();
    if (destination.isEmpty()) {
        throw new BadRequestException("destination must be non-empty");
    }
    String refName = RefNames.fullName(destination);
    contributorAgreements.check(projectName, user.get());
    permissionBackend.currentUser().project(projectName).ref(refName).check(RefPermission.CREATE_CHANGE);
    rsrc.getProjectState().checkStatePermitsWrite();
    try {
        CherryPickChange.Result cherryPickResult = cherryPickChange.cherryPick(null, projectName, rsrc.getCommit(), input, BranchNameKey.create(rsrc.getProjectState().getNameKey(), refName));
        ChangeInfo changeInfo = json.noOptions().format(projectName, cherryPickResult.changeId());
        changeInfo.containsGitConflicts = !cherryPickResult.filesWithGitConflicts().isEmpty() ? true : null;
        return Response.ok(changeInfo);
    } catch (InvalidChangeOperationException e) {
        throw new BadRequestException(e.getMessage());
    }
}
Also used : Project(com.google.gerrit.entities.Project) InvalidChangeOperationException(com.google.gerrit.server.project.InvalidChangeOperationException) ChangeInfo(com.google.gerrit.extensions.common.ChangeInfo) BadRequestException(com.google.gerrit.extensions.restapi.BadRequestException)

Example 10 with InvalidChangeOperationException

use of com.google.gerrit.server.project.InvalidChangeOperationException in project gerrit by GerritCodeReview.

the class CherryPick method applyImpl.

@Override
protected ChangeInfo applyImpl(BatchUpdate.Factory updateFactory, RevisionResource revision, CherryPickInput input) throws OrmException, IOException, UpdateException, RestApiException {
    final ChangeControl control = revision.getControl();
    input.parent = input.parent == null ? 1 : input.parent;
    if (input.message == null || input.message.trim().isEmpty()) {
        throw new BadRequestException("message must be non-empty");
    } else if (input.destination == null || input.destination.trim().isEmpty()) {
        throw new BadRequestException("destination must be non-empty");
    }
    if (!control.isVisible(dbProvider.get())) {
        throw new AuthException("Cherry pick not permitted");
    }
    ProjectControl projectControl = control.getProjectControl();
    Capable capable = projectControl.canPushToAtLeastOneRef();
    if (capable != Capable.OK) {
        throw new AuthException(capable.getMessage());
    }
    String refName = RefNames.fullName(input.destination);
    RefControl refControl = projectControl.controlForRef(refName);
    if (!refControl.canUpload()) {
        throw new AuthException("Not allowed to cherry pick " + revision.getChange().getId().toString() + " to " + input.destination);
    }
    try {
        Change.Id cherryPickedChangeId = cherryPickChange.cherryPick(updateFactory, revision.getChange(), revision.getPatchSet(), input, refName, refControl);
        return json.noOptions().format(revision.getProject(), cherryPickedChangeId);
    } catch (InvalidChangeOperationException e) {
        throw new BadRequestException(e.getMessage());
    } catch (IntegrationException | NoSuchChangeException e) {
        throw new ResourceConflictException(e.getMessage());
    }
}
Also used : InvalidChangeOperationException(com.google.gerrit.server.project.InvalidChangeOperationException) IntegrationException(com.google.gerrit.server.git.IntegrationException) RefControl(com.google.gerrit.server.project.RefControl) AuthException(com.google.gerrit.extensions.restapi.AuthException) Change(com.google.gerrit.reviewdb.client.Change) ProjectControl(com.google.gerrit.server.project.ProjectControl) ResourceConflictException(com.google.gerrit.extensions.restapi.ResourceConflictException) Capable(com.google.gerrit.common.data.Capable) NoSuchChangeException(com.google.gerrit.server.project.NoSuchChangeException) ChangeControl(com.google.gerrit.server.project.ChangeControl) BadRequestException(com.google.gerrit.extensions.restapi.BadRequestException)

Aggregations

InvalidChangeOperationException (com.google.gerrit.server.project.InvalidChangeOperationException)20 ResourceConflictException (com.google.gerrit.extensions.restapi.ResourceConflictException)8 ObjectId (org.eclipse.jgit.lib.ObjectId)8 PatchSet (com.google.gerrit.entities.PatchSet)7 BadRequestException (com.google.gerrit.extensions.restapi.BadRequestException)7 Repository (org.eclipse.jgit.lib.Repository)7 ProjectState (com.google.gerrit.server.project.ProjectState)6 AuthException (com.google.gerrit.extensions.restapi.AuthException)5 Change (com.google.gerrit.entities.Change)4 Project (com.google.gerrit.entities.Project)4 NoSuchChangeException (com.google.gerrit.server.project.NoSuchChangeException)4 ChangeData (com.google.gerrit.server.query.change.ChangeData)4 MergeConflictException (com.google.gerrit.extensions.restapi.MergeConflictException)3 PatchSet (com.google.gerrit.reviewdb.client.PatchSet)3 GerritPersonIdent (com.google.gerrit.server.GerritPersonIdent)3 IdentifiedUser (com.google.gerrit.server.IdentifiedUser)3 ObjectInserter (org.eclipse.jgit.lib.ObjectInserter)3 PersonIdent (org.eclipse.jgit.lib.PersonIdent)3 RevCommit (org.eclipse.jgit.revwalk.RevCommit)3 Nullable (com.google.gerrit.common.Nullable)2