Search in sources :

Example 1 with MergeWithConflictsNotSupportedException

use of com.google.gerrit.exceptions.MergeWithConflictsNotSupportedException in project gerrit by GerritCodeReview.

the class MergeUtil method createMergeCommit.

public static CodeReviewCommit createMergeCommit(ObjectInserter inserter, Config repoConfig, RevCommit mergeTip, RevCommit originalCommit, String mergeStrategy, boolean allowConflicts, PersonIdent authorIdent, PersonIdent committerIdent, String commitMsg, CodeReviewRevWalk rw) throws IOException, MergeIdenticalTreeException, MergeConflictException, InvalidMergeStrategyException {
    if (!MergeStrategy.THEIRS.getName().equals(mergeStrategy) && rw.isMergedInto(originalCommit, mergeTip)) {
        throw new ChangeAlreadyMergedException("'" + originalCommit.getName() + "' has already been merged");
    }
    Merger m = newMerger(inserter, repoConfig, mergeStrategy);
    DirCache dc = DirCache.newInCore();
    if (allowConflicts && m instanceof ResolveMerger) {
        // The DirCache must be set on ResolveMerger before calling
        // ResolveMerger#merge(AnyObjectId...) otherwise the entries in DirCache don't get populated.
        ((ResolveMerger) m).setDirCache(dc);
    }
    ObjectId tree;
    ImmutableSet<String> filesWithGitConflicts;
    if (m.merge(false, mergeTip, originalCommit)) {
        filesWithGitConflicts = null;
        tree = m.getResultTreeId();
    } else {
        List<String> conflicts = ImmutableList.of();
        if (m instanceof ResolveMerger) {
            conflicts = ((ResolveMerger) m).getUnmergedPaths();
        }
        if (!allowConflicts) {
            throw new MergeConflictException(createConflictMessage(conflicts));
        }
        // For merging with conflict markers we need a ResolveMerger, double-check that we have one.
        if (!(m instanceof ResolveMerger)) {
            throw new MergeWithConflictsNotSupportedException(MergeStrategy.get(mergeStrategy));
        }
        Map<String, MergeResult<? extends Sequence>> mergeResults = ((ResolveMerger) m).getMergeResults();
        filesWithGitConflicts = mergeResults.entrySet().stream().filter(e -> e.getValue().containsConflicts()).map(Map.Entry::getKey).collect(toImmutableSet());
        tree = mergeWithConflicts(rw, inserter, dc, "TARGET BRANCH", mergeTip, "SOURCE BRANCH", originalCommit, mergeResults);
    }
    CommitBuilder mergeCommit = new CommitBuilder();
    mergeCommit.setTreeId(tree);
    mergeCommit.setParentIds(mergeTip, originalCommit);
    mergeCommit.setAuthor(authorIdent);
    mergeCommit.setCommitter(committerIdent);
    mergeCommit.setMessage(commitMsg);
    CodeReviewCommit commit = rw.parseCommit(inserter.insert(mergeCommit));
    commit.setFilesWithGitConflicts(filesWithGitConflicts);
    return commit;
}
Also used : ResourceNotFoundException(com.google.gerrit.extensions.restapi.ResourceNotFoundException) RevisionSyntaxException(org.eclipse.jgit.errors.RevisionSyntaxException) Comparator.naturalOrder(java.util.Comparator.naturalOrder) ObjectInserter(org.eclipse.jgit.lib.ObjectInserter) DynamicItem(com.google.gerrit.extensions.registration.DynamicItem) MissingObjectException(org.eclipse.jgit.errors.MissingObjectException) ThreeWayMergeStrategy(org.eclipse.jgit.merge.ThreeWayMergeStrategy) BadRequestException(com.google.gerrit.extensions.restapi.BadRequestException) Merger(org.eclipse.jgit.merge.Merger) Assisted(com.google.inject.assistedinject.Assisted) FooterKey(org.eclipse.jgit.revwalk.FooterKey) RevWalk(org.eclipse.jgit.revwalk.RevWalk) PatchSetApproval(com.google.gerrit.entities.PatchSetApproval) Config(org.eclipse.jgit.lib.Config) Preconditions.checkArgument(com.google.common.base.Preconditions.checkArgument) InvalidMergeStrategyException(com.google.gerrit.exceptions.InvalidMergeStrategyException) MergeConflictException(com.google.gerrit.extensions.restapi.MergeConflictException) FooterLine(org.eclipse.jgit.revwalk.FooterLine) LabelType(com.google.gerrit.entities.LabelType) Map(java.util.Map) AssistedInject(com.google.inject.assistedinject.AssistedInject) UrlFormatter(com.google.gerrit.server.config.UrlFormatter) ImmutableSortedSet.toImmutableSortedSet(com.google.common.collect.ImmutableSortedSet.toImmutableSortedSet) ImmutableSet(com.google.common.collect.ImmutableSet) Sequence(org.eclipse.jgit.diff.Sequence) GerritServerConfig(com.google.gerrit.server.config.GerritServerConfig) Collection(java.util.Collection) LargeObjectException(org.eclipse.jgit.errors.LargeObjectException) Account(com.google.gerrit.entities.Account) Set(java.util.Set) RevSort(org.eclipse.jgit.revwalk.RevSort) Constants(org.eclipse.jgit.lib.Constants) MethodNotAllowedException(com.google.gerrit.extensions.restapi.MethodNotAllowedException) Collectors.joining(java.util.stream.Collectors.joining) Sets(com.google.common.collect.Sets) BranchNameKey(com.google.gerrit.entities.BranchNameKey) ApprovalsUtil(com.google.gerrit.server.approval.ApprovalsUtil) MergeIdenticalTreeException(com.google.gerrit.server.submit.MergeIdenticalTreeException) MergeStrategy(org.eclipse.jgit.merge.MergeStrategy) Preconditions.checkState(com.google.common.base.Preconditions.checkState) Objects(java.util.Objects) PersonIdent(org.eclipse.jgit.lib.PersonIdent) List(java.util.List) Nullable(com.google.gerrit.common.Nullable) BooleanProjectConfig(com.google.gerrit.entities.BooleanProjectConfig) DirCache(org.eclipse.jgit.dircache.DirCache) Optional(java.util.Optional) FluentLogger(com.google.common.flogger.FluentLogger) AmbiguousObjectException(org.eclipse.jgit.errors.AmbiguousObjectException) Iterables(com.google.common.collect.Iterables) LabelId(com.google.gerrit.entities.LabelId) CodeReviewRevWalk(com.google.gerrit.server.git.CodeReviewCommit.CodeReviewRevWalk) RevCommit(org.eclipse.jgit.revwalk.RevCommit) CommitMergeStatus(com.google.gerrit.server.submit.CommitMergeStatus) IncorrectObjectTypeException(org.eclipse.jgit.errors.IncorrectObjectTypeException) RevFlag(org.eclipse.jgit.revwalk.RevFlag) DirCacheEntry(org.eclipse.jgit.dircache.DirCacheEntry) HashMap(java.util.HashMap) DirCacheBuilder(org.eclipse.jgit.dircache.DirCacheBuilder) MergeBaseFailureReason(org.eclipse.jgit.errors.NoMergeBaseException.MergeBaseFailureReason) ChangeAlreadyMergedException(com.google.gerrit.server.submit.ChangeAlreadyMergedException) ArrayList(java.util.ArrayList) Strings(com.google.common.base.Strings) ImmutableList(com.google.common.collect.ImmutableList) CommitBuilder(org.eclipse.jgit.lib.CommitBuilder) ResolveMerger(org.eclipse.jgit.merge.ResolveMerger) ImmutableSet.toImmutableSet(com.google.common.collect.ImmutableSet.toImmutableSet) MergeWithConflictsNotSupportedException(com.google.gerrit.exceptions.MergeWithConflictsNotSupportedException) Change(com.google.gerrit.entities.Change) PatchSet(com.google.gerrit.entities.PatchSet) ChangeUtil(com.google.gerrit.server.ChangeUtil) NoMergeBaseException(org.eclipse.jgit.errors.NoMergeBaseException) ImmutableSortedSet(com.google.common.collect.ImmutableSortedSet) TemporaryBuffer(org.eclipse.jgit.util.TemporaryBuffer) Iterator(java.util.Iterator) ObjectIds.abbreviateName(com.google.gerrit.git.ObjectIds.abbreviateName) UTF_8(java.nio.charset.StandardCharsets.UTF_8) StorageException(com.google.gerrit.exceptions.StorageException) ProjectState(com.google.gerrit.server.project.ProjectState) ChangeNotes(com.google.gerrit.server.notedb.ChangeNotes) IOException(java.io.IOException) ThreeWayMerger(org.eclipse.jgit.merge.ThreeWayMerger) ObjectId(org.eclipse.jgit.lib.ObjectId) MergeResult(org.eclipse.jgit.merge.MergeResult) MergeSorter(com.google.gerrit.server.submit.MergeSorter) MergeFormatter(org.eclipse.jgit.merge.MergeFormatter) IdentifiedUser(com.google.gerrit.server.IdentifiedUser) FooterConstants(com.google.gerrit.common.FooterConstants) Collections(java.util.Collections) Repository(org.eclipse.jgit.lib.Repository) InputStream(java.io.InputStream) ObjectId(org.eclipse.jgit.lib.ObjectId) MergeResult(org.eclipse.jgit.merge.MergeResult) CommitBuilder(org.eclipse.jgit.lib.CommitBuilder) Sequence(org.eclipse.jgit.diff.Sequence) ResolveMerger(org.eclipse.jgit.merge.ResolveMerger) DirCache(org.eclipse.jgit.dircache.DirCache) MergeConflictException(com.google.gerrit.extensions.restapi.MergeConflictException) DirCacheEntry(org.eclipse.jgit.dircache.DirCacheEntry) Merger(org.eclipse.jgit.merge.Merger) ResolveMerger(org.eclipse.jgit.merge.ResolveMerger) ThreeWayMerger(org.eclipse.jgit.merge.ThreeWayMerger) MergeWithConflictsNotSupportedException(com.google.gerrit.exceptions.MergeWithConflictsNotSupportedException) ChangeAlreadyMergedException(com.google.gerrit.server.submit.ChangeAlreadyMergedException)

Example 2 with MergeWithConflictsNotSupportedException

use of com.google.gerrit.exceptions.MergeWithConflictsNotSupportedException in project gerrit by GerritCodeReview.

the class CreateChange method createNewChange.

// TODO(issue-15517): Fix the JdkObsolete issue with Date once JGit's PersonIdent class supports
// Instants
@SuppressWarnings("JdkObsolete")
private ChangeInfo createNewChange(ChangeInput input, IdentifiedUser me, ProjectState projectState, BatchUpdate.Factory updateFactory) throws RestApiException, PermissionBackendException, IOException, ConfigInvalidException, UpdateException {
    logger.atFine().log("Creating new change for target branch %s in project %s" + " (new branch = %s, base change = %s, base commit = %s)", input.branch, projectState.getName(), input.newBranch, input.baseChange, input.baseCommit);
    try (Repository git = gitManager.openRepository(projectState.getNameKey());
        ObjectInserter oi = git.newObjectInserter();
        ObjectReader reader = oi.newReader();
        CodeReviewRevWalk rw = CodeReviewCommit.newRevWalk(reader)) {
        PatchSet basePatchSet = null;
        List<String> groups = Collections.emptyList();
        if (input.baseChange != null) {
            ChangeNotes baseChange = getBaseChange(input.baseChange);
            basePatchSet = psUtil.current(baseChange);
            groups = basePatchSet.groups();
            logger.atFine().log("base patch set = %s (groups = %s)", basePatchSet.id(), groups);
        }
        ObjectId parentCommit = getParentCommit(git, rw, input.branch, input.newBranch, basePatchSet, input.baseCommit, input.merge);
        logger.atFine().log("parent commit = %s", parentCommit != null ? parentCommit.name() : "NULL");
        RevCommit mergeTip = parentCommit == null ? null : rw.parseCommit(parentCommit);
        Instant now = TimeUtil.now();
        PersonIdent committer = me.newCommitterIdent(now, serverTimeZone);
        PersonIdent author = input.author == null ? committer : new PersonIdent(input.author.name, input.author.email, Date.from(now), serverTimeZone);
        String commitMessage = getCommitMessage(input.subject, me);
        CodeReviewCommit c;
        if (input.merge != null) {
            // create a merge commit
            c = newMergeCommit(git, oi, rw, projectState, mergeTip, input.merge, author, committer, commitMessage);
            if (!c.getFilesWithGitConflicts().isEmpty()) {
                logger.atFine().log("merge commit has conflicts in the following files: %s", c.getFilesWithGitConflicts());
            }
        } else {
            // create an empty commit
            c = newCommit(oi, rw, author, committer, mergeTip, commitMessage);
        }
        // Flush inserter so that commit becomes visible to validators
        oi.flush();
        Change.Id changeId = Change.id(seq.nextChangeId());
        ChangeInserter ins = changeInserterFactory.create(changeId, c, input.branch);
        ins.setMessage(messageForNewChange(ins.getPatchSetId(), c));
        ins.setTopic(input.topic);
        ins.setPrivate(input.isPrivate);
        ins.setWorkInProgress(input.workInProgress || !c.getFilesWithGitConflicts().isEmpty());
        ins.setGroups(groups);
        if (input.validationOptions != null) {
            ImmutableListMultimap.Builder<String, String> validationOptions = ImmutableListMultimap.builder();
            input.validationOptions.entrySet().forEach(e -> validationOptions.put(e.getKey(), e.getValue()));
            ins.setValidationOptions(validationOptions.build());
        }
        try (BatchUpdate bu = updateFactory.create(projectState.getNameKey(), me, now)) {
            bu.setRepository(git, rw, oi);
            bu.setNotify(notifyResolver.resolve(firstNonNull(input.notify, NotifyHandling.ALL), input.notifyDetails));
            bu.insertChange(ins);
            bu.execute();
        }
        ChangeInfo changeInfo = jsonFactory.noOptions().format(ins.getChange());
        changeInfo.containsGitConflicts = !c.getFilesWithGitConflicts().isEmpty() ? true : null;
        return changeInfo;
    } catch (InvalidMergeStrategyException | MergeWithConflictsNotSupportedException e) {
        throw new BadRequestException(e.getMessage());
    }
}
Also used : ChangeInfo(com.google.gerrit.extensions.common.ChangeInfo) ObjectId(org.eclipse.jgit.lib.ObjectId) Instant(java.time.Instant) CodeReviewRevWalk(com.google.gerrit.server.git.CodeReviewCommit.CodeReviewRevWalk) PatchSet(com.google.gerrit.entities.PatchSet) ChangeNotes(com.google.gerrit.server.notedb.ChangeNotes) Change(com.google.gerrit.entities.Change) CodeReviewCommit(com.google.gerrit.server.git.CodeReviewCommit) BatchUpdate(com.google.gerrit.server.update.BatchUpdate) Repository(org.eclipse.jgit.lib.Repository) ObjectInserter(org.eclipse.jgit.lib.ObjectInserter) PersonIdent(org.eclipse.jgit.lib.PersonIdent) GerritPersonIdent(com.google.gerrit.server.GerritPersonIdent) InvalidMergeStrategyException(com.google.gerrit.exceptions.InvalidMergeStrategyException) ImmutableListMultimap(com.google.common.collect.ImmutableListMultimap) MergeWithConflictsNotSupportedException(com.google.gerrit.exceptions.MergeWithConflictsNotSupportedException) BadRequestException(com.google.gerrit.extensions.restapi.BadRequestException) ObjectReader(org.eclipse.jgit.lib.ObjectReader) ChangeInserter(com.google.gerrit.server.change.ChangeInserter) RevCommit(org.eclipse.jgit.revwalk.RevCommit)

Example 3 with MergeWithConflictsNotSupportedException

use of com.google.gerrit.exceptions.MergeWithConflictsNotSupportedException in project gerrit by GerritCodeReview.

the class CreateMergePatchSet method apply.

// TODO(issue-15517): Fix the JdkObsolete issue with Date once JGit's PersonIdent class supports
// Instants
@SuppressWarnings("JdkObsolete")
@Override
public Response<ChangeInfo> apply(ChangeResource rsrc, MergePatchSetInput in) throws IOException, RestApiException, UpdateException, PermissionBackendException {
    // Not allowed to create a new patch set if the current patch set is locked.
    psUtil.checkPatchSetNotLocked(rsrc.getNotes());
    rsrc.permissions().check(ChangePermission.ADD_PATCH_SET);
    if (in.author != null) {
        permissionBackend.currentUser().project(rsrc.getProject()).ref(rsrc.getChange().getDest().branch()).check(RefPermission.FORGE_AUTHOR);
    }
    ProjectState projectState = projectCache.get(rsrc.getProject()).orElseThrow(illegalState(rsrc.getProject()));
    projectState.checkStatePermitsWrite();
    MergeInput merge = in.merge;
    if (merge == null || Strings.isNullOrEmpty(merge.source)) {
        throw new BadRequestException("merge.source must be non-empty");
    }
    if (in.author != null && (Strings.isNullOrEmpty(in.author.email) || Strings.isNullOrEmpty(in.author.name))) {
        throw new BadRequestException("Author must specify name and email");
    }
    in.baseChange = Strings.nullToEmpty(in.baseChange).trim();
    PatchSet ps = psUtil.current(rsrc.getNotes());
    Change change = rsrc.getChange();
    Project.NameKey project = change.getProject();
    BranchNameKey dest = change.getDest();
    try (Repository git = gitManager.openRepository(project);
        ObjectInserter oi = git.newObjectInserter();
        ObjectReader reader = oi.newReader();
        CodeReviewRevWalk rw = CodeReviewCommit.newRevWalk(reader)) {
        RevCommit sourceCommit = MergeUtil.resolveCommit(git, rw, merge.source);
        if (!commits.canRead(projectState, git, sourceCommit)) {
            throw new ResourceNotFoundException("cannot find source commit: " + merge.source + " to merge.");
        }
        RevCommit currentPsCommit;
        List<String> groups = null;
        if (!in.inheritParent && !in.baseChange.isEmpty()) {
            PatchSet basePS = findBasePatchSet(in.baseChange);
            currentPsCommit = rw.parseCommit(basePS.commitId());
            groups = basePS.groups();
        } else {
            currentPsCommit = rw.parseCommit(ps.commitId());
        }
        Instant now = TimeUtil.now();
        IdentifiedUser me = user.get().asIdentifiedUser();
        PersonIdent author = in.author == null ? me.newCommitterIdent(now, serverTimeZone) : new PersonIdent(in.author.name, in.author.email, Date.from(now), serverTimeZone);
        CodeReviewCommit newCommit = createMergeCommit(in, projectState, dest, git, oi, rw, currentPsCommit, sourceCommit, author, ObjectId.fromString(change.getKey().get().substring(1)));
        oi.flush();
        PatchSet.Id nextPsId = ChangeUtil.nextPatchSetId(ps.id());
        PatchSetInserter psInserter = patchSetInserterFactory.create(rsrc.getNotes(), nextPsId, newCommit);
        try (BatchUpdate bu = updateFactory.create(project, me, now)) {
            bu.setRepository(git, rw, oi);
            bu.setNotify(NotifyResolver.Result.none());
            psInserter.setMessage(messageForChange(nextPsId, newCommit)).setWorkInProgress(!newCommit.getFilesWithGitConflicts().isEmpty()).setCheckAddPatchSetPermission(false);
            if (groups != null) {
                psInserter.setGroups(groups);
            }
            bu.addOp(rsrc.getId(), psInserter);
            bu.execute();
        }
        ChangeJson json = jsonFactory.create(ListChangesOption.CURRENT_REVISION);
        ChangeInfo changeInfo = json.format(psInserter.getChange());
        changeInfo.containsGitConflicts = !newCommit.getFilesWithGitConflicts().isEmpty() ? true : null;
        return Response.ok(changeInfo);
    } catch (InvalidMergeStrategyException | MergeWithConflictsNotSupportedException e) {
        throw new BadRequestException(e.getMessage());
    }
}
Also used : MergeInput(com.google.gerrit.extensions.common.MergeInput) BatchUpdate(com.google.gerrit.server.update.BatchUpdate) BranchNameKey(com.google.gerrit.entities.BranchNameKey) ObjectInserter(org.eclipse.jgit.lib.ObjectInserter) ObjectReader(org.eclipse.jgit.lib.ObjectReader) ResourceNotFoundException(com.google.gerrit.extensions.restapi.ResourceNotFoundException) RevCommit(org.eclipse.jgit.revwalk.RevCommit) ChangeJson(com.google.gerrit.server.change.ChangeJson) ChangeInfo(com.google.gerrit.extensions.common.ChangeInfo) Instant(java.time.Instant) CodeReviewRevWalk(com.google.gerrit.server.git.CodeReviewCommit.CodeReviewRevWalk) PatchSet(com.google.gerrit.entities.PatchSet) Change(com.google.gerrit.entities.Change) IdentifiedUser(com.google.gerrit.server.IdentifiedUser) CodeReviewCommit(com.google.gerrit.server.git.CodeReviewCommit) Project(com.google.gerrit.entities.Project) Repository(org.eclipse.jgit.lib.Repository) PersonIdent(org.eclipse.jgit.lib.PersonIdent) GerritPersonIdent(com.google.gerrit.server.GerritPersonIdent) PatchSetInserter(com.google.gerrit.server.change.PatchSetInserter) InvalidMergeStrategyException(com.google.gerrit.exceptions.InvalidMergeStrategyException) BadRequestException(com.google.gerrit.extensions.restapi.BadRequestException) MergeWithConflictsNotSupportedException(com.google.gerrit.exceptions.MergeWithConflictsNotSupportedException) ProjectState(com.google.gerrit.server.project.ProjectState)

Aggregations

Change (com.google.gerrit.entities.Change)3 PatchSet (com.google.gerrit.entities.PatchSet)3 InvalidMergeStrategyException (com.google.gerrit.exceptions.InvalidMergeStrategyException)3 MergeWithConflictsNotSupportedException (com.google.gerrit.exceptions.MergeWithConflictsNotSupportedException)3 BadRequestException (com.google.gerrit.extensions.restapi.BadRequestException)3 CodeReviewRevWalk (com.google.gerrit.server.git.CodeReviewCommit.CodeReviewRevWalk)3 BranchNameKey (com.google.gerrit.entities.BranchNameKey)2 ChangeInfo (com.google.gerrit.extensions.common.ChangeInfo)2 ResourceNotFoundException (com.google.gerrit.extensions.restapi.ResourceNotFoundException)2 GerritPersonIdent (com.google.gerrit.server.GerritPersonIdent)2 IdentifiedUser (com.google.gerrit.server.IdentifiedUser)2 CodeReviewCommit (com.google.gerrit.server.git.CodeReviewCommit)2 ChangeNotes (com.google.gerrit.server.notedb.ChangeNotes)2 ProjectState (com.google.gerrit.server.project.ProjectState)2 BatchUpdate (com.google.gerrit.server.update.BatchUpdate)2 Instant (java.time.Instant)2 ObjectInserter (org.eclipse.jgit.lib.ObjectInserter)2 ObjectReader (org.eclipse.jgit.lib.ObjectReader)2 PersonIdent (org.eclipse.jgit.lib.PersonIdent)2 Repository (org.eclipse.jgit.lib.Repository)2