Mercurial > hg > mercurial
view mercurial-server/src/jetbrains/buildServer/buildTriggers/vcs/mercurial/MercurialMergeSupport.java @ 1027:10dc26b32c35
Update code according to new Java
author | nikolai.kulakov@DESKTOP-Q4QCGIH |
---|---|
date | Wed, 05 Aug 2020 13:19:53 +0300 |
parents | 7bf4d943d5bb |
children |
line wrap: on
line source
/* * Copyright 2000-2018 JetBrains s.r.o. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package jetbrains.buildServer.buildTriggers.vcs.mercurial; import com.intellij.openapi.diagnostic.Logger; import jetbrains.buildServer.buildTriggers.vcs.mercurial.command.HgVcsRoot; import jetbrains.buildServer.buildTriggers.vcs.mercurial.command.PushCommand; import jetbrains.buildServer.buildTriggers.vcs.mercurial.command.exception.MergeConflictException; import jetbrains.buildServer.buildTriggers.vcs.mercurial.command.exception.MergeWithWorkingDirAncestor; import jetbrains.buildServer.buildTriggers.vcs.mercurial.command.exception.NothingToMergeException; import jetbrains.buildServer.vcs.*; import org.jetbrains.annotations.NotNull; import java.io.File; import java.util.ArrayList; import java.util.HashMap; import java.util.List; import java.util.Map; import static jetbrains.buildServer.buildTriggers.vcs.mercurial.HgFileUtil.deleteDir; public class MercurialMergeSupport implements MergeSupport, MercurialServerExtension { private final static Logger LOG = Logger.getInstance(MercurialMergeSupport.class.getName()); private final MirrorManager myMirrorManager; private final ServerPluginConfig myConfig; private final HgVcsRootFactory myHgVcsRootFactory; private final HgRepoFactory myHgRepoFactory; public MercurialMergeSupport(@NotNull MercurialVcsSupport vcs, @NotNull MirrorManager mirrorManager, @NotNull ServerPluginConfig config, @NotNull HgVcsRootFactory vcsRootFactory, @NotNull HgRepoFactory hgRepoFactory) { vcs.addExtension(this); myMirrorManager = mirrorManager; myConfig = config; myHgVcsRootFactory = vcsRootFactory; myHgRepoFactory = hgRepoFactory; } @NotNull public Map<MergeTask, MergeResult> tryMerge(@NotNull VcsRoot root, @NotNull List<MergeTask> tasks, @NotNull MergeOptions options) throws VcsException { File tmpDir = null; try { tmpDir = HgFileUtil.createTempDir(); HgVcsRoot hgRoot = myHgVcsRootFactory.createHgRoot(root); HgRepo repo = myHgRepoFactory.createRepo(hgRoot, tmpDir); Map<MergeTask, MergeResult> results = new HashMap<>(); for (MergeTask task : tasks) { try { new CheckoutRepository(myMirrorManager, myHgRepoFactory, myConfig.getPullTimeout(), myConfig.useTagsAsBranches(), hgRoot, tmpDir) .setRevision(task.getDestinationRevision()).checkout(); repo.merge().withMergeTool(myConfig.getMergeTool()).revision(task.getSourceRevision()).call(); results.put(task, MergeResult.createMergeSuccessResult()); } catch (MergeConflictException e) { results.put(task, MergeResult.createMergeError(detectConflicts(hgRoot, "", repo))); } catch (MergeWithWorkingDirAncestor e) { //ignore } catch (VcsException e) { results.put(task, MergeResult.createMergeError(e.getMessage())); } finally { repo.update().toRevision(task.getDestinationRevision()).call(); } } return results; } catch (Exception e) { if (e instanceof VcsException) throw (VcsException) e; throw new VcsException(e); } finally { deleteDir(tmpDir, LOG); } } @NotNull public MergeResult merge(@NotNull VcsRoot root, @NotNull String srcRevision, @NotNull String dstBranch, @NotNull String message, @NotNull MergeOptions options) throws VcsException { LOG.info("Merge in root " + root + ", revision " + srcRevision + ", destination " + dstBranch); File tmpDir = null; try { tmpDir = HgFileUtil.createTempDir(); HgVcsRoot hgRoot = myHgVcsRootFactory.createHgRoot(root); new CheckoutRepository(myMirrorManager, myHgRepoFactory, myConfig.getPullTimeout(), myConfig.useTagsAsBranches(), hgRoot, tmpDir) .setBranch(dstBranch).checkout(); HgRepo repo = myHgRepoFactory.createRepo(hgRoot, tmpDir); boolean bookmark = repo.isBookmark(dstBranch); try { repo.merge().withMergeTool(myConfig.getMergeTool()).revision(srcRevision).call(); } catch (MergeConflictException e) { List<String> conflicts = detectConflicts(hgRoot, "", repo); LOG.info("Merge failed with conflicts, root " + root + ", revision " + srcRevision + ", destination " + dstBranch + ", conflicts " + conflicts, e); return MergeResult.createMergeError(conflicts); } catch (MergeWithWorkingDirAncestor e) { LOG.info("Merge is not performed: revision already merged into destination, root " + root + ", revision " + srcRevision + ", destination " + dstBranch, e); return MergeResult.createMergeNotPerformedResult("Revision " + srcRevision + " is already merged into " + dstBranch); } catch (NothingToMergeException e) { //happens when revision of the dstBranch is merged into srcRevision if (bookmark) { //emulate fast-forward merge repo.updateBookmark().name(dstBranch).setRevision(srcRevision).call(); push(root, srcRevision, dstBranch, hgRoot, repo, bookmark); LOG.info("Merge successfully finished in root " + root + ", revision " + srcRevision + ", destination " + dstBranch); return MergeResult.createMergeSuccessResult(); } else { return MergeResult.createMergeError("Revision of branch " + dstBranch + " is reachable from " + srcRevision); } } repo.commit().by(hgRoot.getUserForTag()).message(message).call(); if (bookmark) repo.updateBookmark().name(dstBranch).call(); push(root, srcRevision, dstBranch, hgRoot, repo, bookmark); LOG.info("Merge successfully finished in root " + root + ", revision " + srcRevision + ", destination " + dstBranch); return MergeResult.createMergeSuccessResult(); } catch (Exception e) { if (e instanceof VcsException) throw (VcsException) e; throw new VcsException(e); } finally { deleteDir(tmpDir, LOG); } } private void push(VcsRoot root, String srcRevision, String dstBranch, HgVcsRoot hgRoot, HgRepo repo, boolean bookmark) throws VcsException { try { PushCommand push = repo.push().toRepository(hgRoot.getRepository()); if (bookmark) push.bookmark(dstBranch); push.call(); } catch (VcsException e) { LOG.info("Error while pushing a merge commit, root " + root + ", revision " + srcRevision + ", destination " + dstBranch, e); throw e; } } private List<String> detectConflicts(@NotNull HgVcsRoot root, @NotNull String prefix, @NotNull HgRepo repo) throws VcsException { List<String> conflicts = new ArrayList<>(); for (String conflict : repo.resolve().call()) { conflicts.add(prefix + conflict); } List<String> parents = repo.parents().call(); if (parents.isEmpty()) return conflicts; Map<String, SubRepo> subrepos = repo.getSubrepositories(parents.get(0)); for (SubRepo subrepo : subrepos.values()) { HgVcsRoot subrepoRoot = root.withUrl(subrepo.url()); HgRepo hgSubrepo = myHgRepoFactory.createRepo(subrepoRoot, new File(repo.getWorkingDir(), subrepo.path())); conflicts.addAll(detectConflicts(subrepoRoot, prefix + subrepo.path() + "/", hgSubrepo)); } return conflicts; } }