# HG changeset patch # User Maxim Zaytsev # Date 1592215632 -10800 # Node ID c0c4bf1db865603cd5c9c24943ed75f99f34c4a7 # Parent c11accb06d56efb55f3648694328754d1422f10b TW-66329 fix using archive command for creating full patch: previous implementation using clone produces very large overhead for big project repositories in case when settings are stored in the project repo since in case of freezing build settings, core system asks plugin to build full patch and cloning repos into temp dir even from local mirror can take tens of minutes diff -r c11accb06d56 -r c0c4bf1db865 mercurial-common/src/jetbrains/buildServer/buildTriggers/vcs/mercurial/SubRepo.java --- a/mercurial-common/src/jetbrains/buildServer/buildTriggers/vcs/mercurial/SubRepo.java Wed May 13 02:06:56 2020 +0300 +++ b/mercurial-common/src/jetbrains/buildServer/buildTriggers/vcs/mercurial/SubRepo.java Mon Jun 15 13:07:12 2020 +0300 @@ -65,6 +65,10 @@ return HgRepo.shortId(myRevision); } + public String fullRevision() { + return myRevision; + } + @NotNull public VcsType vcsType() { return myVcsType; diff -r c11accb06d56 -r c0c4bf1db865 mercurial-server/src/jetbrains/buildServer/buildTriggers/vcs/mercurial/MercurialVcsSupport.java --- a/mercurial-server/src/jetbrains/buildServer/buildTriggers/vcs/mercurial/MercurialVcsSupport.java Wed May 13 02:06:56 2020 +0300 +++ b/mercurial-server/src/jetbrains/buildServer/buildTriggers/vcs/mercurial/MercurialVcsSupport.java Mon Jun 15 13:07:12 2020 +0300 @@ -22,10 +22,7 @@ import jetbrains.buildServer.buildTriggers.vcs.mercurial.command.exception.UnrelatedRepositoryException; import jetbrains.buildServer.buildTriggers.vcs.mercurial.command.exception.WrongSubrepoUrlException; import jetbrains.buildServer.log.Loggers; -import jetbrains.buildServer.serverSide.InvalidProperty; -import jetbrains.buildServer.serverSide.PropertiesProcessor; -import jetbrains.buildServer.serverSide.ServerListener; -import jetbrains.buildServer.serverSide.ServerListenerAdapter; +import jetbrains.buildServer.serverSide.*; import jetbrains.buildServer.util.EventDispatcher; import jetbrains.buildServer.util.FileUtil; import jetbrains.buildServer.util.cache.ResetCacheRegister; @@ -385,15 +382,23 @@ if (root.includeSubreposInPatch()) { final Map subrepos = repo.getSubrepositories(toVer); if (!subrepos.isEmpty()) { - Loggers.VCS.debug("Repository '" + root.getRepository() + "' has subrepos at revision " + toVer.getId() + ", use 'hg clone' to build clean patch"); - final File mirrorDir = getWorkingDir(root); - final HgRepo cloneOfTheMirror = createRepo(root, tempDir); - cloneOfTheMirror.init().call(); - cloneOfTheMirror.setDefaultPath(root.getRepository()); - cloneOfTheMirror.setTeamCityConfig(root.getCustomHgConfigServer()); - cloneOfTheMirror.pull().fromRepository(mirrorDir).call(); - cloneSubrepos(root, tempDir, subrepos); - cloneOfTheMirror.update().toRevision(toVer).call(); + final boolean useArchiveForBuildPath = TeamCityProperties.getBooleanOrTrue("teamcity.vcs.hg.useArchiveForBuildPatch"); + if (useArchiveForBuildPath) { + Loggers.VCS.debug("Repository '" + root.getRepository() + "' has subrepos at revision " + toVer.getId() + + ", use 'hg archive' recursively for each subrepo to build clean patch"); + repo.archive().revision(toVer).destination(tempDir).call(); + fetchSubreposContent(root, tempDir, subrepos, true); + } else { + Loggers.VCS.debug("Repository '" + root.getRepository() + "' has subrepos at revision " + toVer.getId() + ", use 'hg clone' to build clean patch"); + final File mirrorDir = getWorkingDir(root); + final HgRepo cloneOfTheMirror = createRepo(root, tempDir); + cloneOfTheMirror.init().call(); + cloneOfTheMirror.setDefaultPath(root.getRepository()); + cloneOfTheMirror.setTeamCityConfig(root.getCustomHgConfigServer()); + cloneOfTheMirror.pull().fromRepository(mirrorDir).call(); + fetchSubreposContent(root, tempDir, subrepos, false); + cloneOfTheMirror.update().toRevision(toVer).call(); + } buildPatchFromDirectory(builder, tempDir, checkoutRules, myIgnoreDotHgFilter); } else { Loggers.VCS.debug("Repository '" + root.getRepository() + "' doesn't have subrepos at revision " + toVer.getId() + ", use 'hg archive' to build clean patch"); @@ -422,7 +427,10 @@ } } - private void cloneSubrepos(@NotNull HgVcsRoot mainRoot, @NotNull File mainRootDir, @NotNull Map subrepos) throws VcsException, IOException { + private void fetchSubreposContent(@NotNull HgVcsRoot mainRoot, + @NotNull File mainRootDir, + @NotNull Map subrepos, + boolean usingArchiveCommand) throws VcsException, IOException { for (Map.Entry e : subrepos.entrySet()) { String path = e.getKey(); SubRepo subrepoConfig = e.getValue(); @@ -438,14 +446,18 @@ File subrepoMirrorDir = getWorkingDir(subrepoRoot); File subrepoDir = new File(mainRootDir, path); - HgRepo cloneOfSubrepoMirror = createRepo(subrepoRoot, subrepoDir); - cloneOfSubrepoMirror.init().call(); - cloneOfSubrepoMirror.setDefaultPath(subrepoUrl); - cloneOfSubrepoMirror.setTeamCityConfig(mainRoot.getCustomHgConfigServer()); - cloneOfSubrepoMirror.pull().fromRepository(subrepoMirrorDir).call(); + if (usingArchiveCommand) { + subrepo.archive().revision(new ChangeSet(subrepoConfig.fullRevision())).destination(subrepoDir).call(); + } else { + HgRepo cloneOfSubrepoMirror = createRepo(subrepoRoot, subrepoDir); + cloneOfSubrepoMirror.init().call(); + cloneOfSubrepoMirror.setDefaultPath(subrepoUrl); + cloneOfSubrepoMirror.setTeamCityConfig(mainRoot.getCustomHgConfigServer()); + cloneOfSubrepoMirror.pull().fromRepository(subrepoMirrorDir).call(); + } Map subSubrepos = subrepo.getSubrepositories(subrepoConfig.revision()); if (!subSubrepos.isEmpty()) - cloneSubrepos(subrepoRoot, subrepoDir, subSubrepos); + fetchSubreposContent(subrepoRoot, subrepoDir, subSubrepos, usingArchiveCommand); } catch (WrongSubrepoUrlException error) { //ignore it, will try to clone from network during main repository update }