Mercurial > hg > mercurial
diff mercurial-server/src/jetbrains/buildServer/buildTriggers/vcs/mercurial/CheckoutRepository.java @ 645:4cf1ab3cd162
Merge in subrepos
author | Dmitry Neverov <dmitry.neverov@jetbrains.com> |
---|---|
date | Tue, 17 Sep 2013 18:48:51 +0400 |
parents | |
children | 0b50d7952a7d |
line wrap: on
line diff
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/mercurial-server/src/jetbrains/buildServer/buildTriggers/vcs/mercurial/CheckoutRepository.java Tue Sep 17 18:48:51 2013 +0400 @@ -0,0 +1,175 @@ +package jetbrains.buildServer.buildTriggers.vcs.mercurial; + +import jetbrains.buildServer.buildTriggers.vcs.mercurial.command.HgVcsRoot; +import jetbrains.buildServer.vcs.VcsException; +import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Nullable; + +import java.io.File; +import java.io.IOException; +import java.net.URISyntaxException; +import java.util.Map; + +import static jetbrains.buildServer.util.FileUtil.delete; + +/** + * Repository checkout which uses mirrors (updates them first) + * and supports subrepos. + */ +public class CheckoutRepository { + + private final MirrorManager myMirrorManager; + private final HgRepoFactory myHgRepoFactory; + private final int myPullTimeout; + private final HgVcsRoot myRoot; + private final File myWorkingDir; + private String myRevision; + private String myBranch; + + CheckoutRepository(@NotNull MirrorManager mirrorManager, + @NotNull HgRepoFactory hgRepoFactory, + int pullTimeout, + @NotNull HgVcsRoot root, + @NotNull File workingDir) { + myMirrorManager = mirrorManager; + myHgRepoFactory = hgRepoFactory; + myPullTimeout = pullTimeout; + myRoot = root; + myWorkingDir = workingDir; + } + + public CheckoutRepository setRevision(String revision) { + myRevision = revision; + return this; + } + + public CheckoutRepository setBranch(String branch) { + myBranch = branch; + return this; + } + + public void checkout() throws VcsException { + checkout(myRoot, myWorkingDir, myRevision); + } + + private void checkout(@NotNull HgVcsRoot root, + @NotNull File workingDir, + @Nullable String revision) throws VcsException { + updateRepository(root, workingDir, revision); + if (revision == null && myBranch != null) { + HgRepo repo = myHgRepoFactory.createRepo(root, workingDir); + Map<String, String> revisions = repo.getBranchRevisions(true); + revision = revisions.get(myBranch); + } + if (revision == null) + return; + updateSubrepos(root, workingDir, revision); + updateWorkingDir(root, workingDir, revision); + } + + + private void updateRepository(@NotNull HgVcsRoot root, + @NotNull File workingDir, + @Nullable String revision) throws VcsException { + HgRepo repo = myHgRepoFactory.createRepo(root, workingDir); + if (revision != null && repo.containsRevision(revision)) + return; + + updateMirror(root, revision); + String mirrorUrl = getMirrorUrl(root); + + if (repo.isValidRepository()) { + repo.pull().fromRepository(mirrorUrl) + .withTimeout(myPullTimeout) + .call(); + } else { + repo.doClone().fromRepository(mirrorUrl) + .setUpdateWorkingDir(false) + .call(); + + repo.setDefaultPath(root.getRepository()); + } + } + + + private void updateWorkingDir(@NotNull HgVcsRoot root, + @NotNull File workingDir, + @NotNull String revision) throws VcsException { + HgRepo repo = myHgRepoFactory.createRepo(root, workingDir); + repo.update().toRevision(revision).call(); + } + + + private void updateSubrepos(@NotNull HgVcsRoot root, + @NotNull File workingDir, + @Nullable String revision) throws VcsException { + HgRepo repo = myHgRepoFactory.createRepo(root, workingDir); + if (!repo.hasSubreposAtRevision(revision)) + return; + + String workingDirRevision = repo.getWorkingDirRevision(); + Map<String, SubRepo> workingDirSubrepos = repo.getSubrepositories(workingDirRevision); + Map<String, SubRepo> subrepos = repo.getSubrepositories(revision); + for (Map.Entry<String, SubRepo> entry : subrepos.entrySet()) { + String path = entry.getKey(); + SubRepo subrepoConfig = entry.getValue(); + SubRepo workingDirSubrepo = workingDirSubrepos.get(path); + if (workingDirSubrepo != null && subrepoConfig.hasDifferentUrlThan(workingDirSubrepo)) + delete(subrepoConfigDir(repo, subrepoConfig)); + + File subrepoDir = new File(workingDir, subrepoConfig.path()); + String subrepoUrl; + try { + subrepoUrl = subrepoConfig.resolveUrl(root.getRepository()); + if (subrepoConfig.vcsType() == SubRepo.VcsType.hg && !isRelativeUrl(subrepoUrl)) { + HgVcsRoot subrepoRoot = root.withUrl(subrepoUrl); + updateRepository(subrepoRoot, subrepoDir, subrepoConfig.revision()); + } + } catch (URISyntaxException e) { + subrepoUrl = subrepoConfig.url(); + } + + updateSubrepos(root.withUrl(subrepoUrl), subrepoDir, subrepoConfig.revision()); + } + } + + + private boolean isRelativeUrl(@NotNull String url) { + return url.startsWith("."); + } + + + private File subrepoConfigDir(@NotNull HgRepo parentRepo, @NotNull SubRepo subrepo) { + return new File(parentRepo.getWorkingDir(), subrepo.path()); + } + + + private void updateMirror(@NotNull HgVcsRoot root, @Nullable String revision) throws VcsException { + String url = root.getRepository(); + File mirrorDir = myMirrorManager.getMirrorDir(url); + HgRepo repo = myHgRepoFactory.createRepo(root, mirrorDir); + if (revision != null && repo.containsRevision(revision)) { + return; + } + + if (repo.isValidRepository()) { + repo.pull().fromRepository(root.getRepository()) + .withTimeout(myPullTimeout) + .call(); + } else { + repo.doClone().fromRepository(root.getRepository()) + .setUpdateWorkingDir(false) + .useUncompressedTransfer(root.isUncompressedTransfer()) + .call(); + repo.setDefaultPath(root.getRepository()); + } + } + + private String getMirrorUrl(@NotNull HgVcsRoot root) throws VcsException { + try { + return myMirrorManager.getMirrorDir(root.getRepository()).getCanonicalPath(); + } catch (IOException e) { + throw new VcsException(e); + } + } +}