changeset 1024:c0c4bf1db865

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
author Maxim Zaytsev <Maxim.Zaytsev@jetbrains.com>
date Mon, 15 Jun 2020 13:07:12 +0300
parents c11accb06d56
children 84d1ee4f7614 594fb8ee3032 10dc26b32c35 cb393afbafb7
files mercurial-common/src/jetbrains/buildServer/buildTriggers/vcs/mercurial/SubRepo.java mercurial-server/src/jetbrains/buildServer/buildTriggers/vcs/mercurial/MercurialVcsSupport.java
diffstat 2 files changed, 36 insertions(+), 20 deletions(-) [+]
line wrap: on
line diff
--- 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;
--- 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<String, SubRepo> 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<String, SubRepo> subrepos) throws VcsException, IOException {
+  private void fetchSubreposContent(@NotNull HgVcsRoot mainRoot,
+                                    @NotNull File mainRootDir,
+                                    @NotNull Map<String, SubRepo> subrepos,
+                                    boolean usingArchiveCommand) throws VcsException, IOException {
     for (Map.Entry<String, SubRepo> 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<String, SubRepo> 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
       }