changeset 584:49b11c289395

Speed up subrepo changes collecting By default do not calculate file status in subrepo changes, report 'edited' in all the cases. Calculating file status is the most expensive mercurial operation. Also report only actually changed files in subrepo merge commits, otherwise they contain thousands of changed files from merged branches.
author Dmitry Neverov <dmitry.neverov@jetbrains.com>
date Tue, 09 Apr 2013 21:18:11 +0400
parents 23abd5aa1115
children d1203382ce76
files mercurial-common/src/jetbrains/buildServer/buildTriggers/vcs/mercurial/command/HgVcsRoot.java mercurial-server/resources/buildServerResources/fastlog.template mercurial-server/src/jetbrains/buildServer/buildTriggers/vcs/mercurial/RepoFactory.java mercurial-server/src/jetbrains/buildServer/buildTriggers/vcs/mercurial/ServerHgRepo.java mercurial-server/src/jetbrains/buildServer/buildTriggers/vcs/mercurial/ServerPluginConfig.java mercurial-server/src/jetbrains/buildServer/buildTriggers/vcs/mercurial/ServerPluginConfigImpl.java mercurial-server/src/jetbrains/buildServer/buildTriggers/vcs/mercurial/command/CollectChangesNoRevsets.java mercurial-server/src/jetbrains/buildServer/buildTriggers/vcs/mercurial/command/CollectChangesWithRevsets.java mercurial-tests/src/jetbrains/buildServer/buildTriggers/vcs/mercurial/ServerPluginConfigBuilder.java
diffstat 9 files changed, 93 insertions(+), 71 deletions(-) [+]
line wrap: on
line diff
--- a/mercurial-common/src/jetbrains/buildServer/buildTriggers/vcs/mercurial/command/HgVcsRoot.java	Mon Apr 08 13:06:17 2013 +0400
+++ b/mercurial-common/src/jetbrains/buildServer/buildTriggers/vcs/mercurial/command/HgVcsRoot.java	Tue Apr 09 21:18:11 2013 +0400
@@ -126,6 +126,10 @@
     return myDetectSubrepoChanges;
   }
 
+  public boolean isSubrepo() {
+    return Boolean.valueOf(getProperty("teamcity.internal.subrepo"));
+  }
+
 
   public String getVcsName() {
     return myRoot.getVcsName();
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/mercurial-server/resources/buildServerResources/fastlog.template	Tue Apr 09 21:18:11 2013 +0400
@@ -0,0 +1,8 @@
+header = '<?xml version="1.0"?>\n<log>\n'
+footer = '</log>\n'
+
+changeset = '<logentry revision="{rev}" shortnode="{node|short}">\n{parents}<author original="{author|xmlescape}"/>\n<date>{date|date|xmlescape}</date>\n<msg xml:space="preserve">{desc|xmlescape}</msg>\n<paths>\n{files}</paths>\n</logentry>\n'
+
+file  = '<path action="M">{file|xmlescape}</path>\n'
+
+parent = '<parent revision="{rev}" shortnode="{node|short}"/>\n'
--- a/mercurial-server/src/jetbrains/buildServer/buildTriggers/vcs/mercurial/RepoFactory.java	Mon Apr 08 13:06:17 2013 +0400
+++ b/mercurial-server/src/jetbrains/buildServer/buildTriggers/vcs/mercurial/RepoFactory.java	Tue Apr 09 21:18:11 2013 +0400
@@ -19,17 +19,15 @@
 
   private final ServerPluginConfig myConfig;
   private final CommandSettingsFactory myCommandSettingsFactory;
-  private File myLogTemplate;
-  private File myLogNoFilesTemplate;
-  private File myDagTemplate;
 
-  public RepoFactory(@NotNull ServerPluginConfig config,
-                     @NotNull CommandSettingsFactory commandSettingsFactory) throws IOException {
+  private final MercurialLogTemplate myLogTemplate = new MercurialLogTemplate("/buildServerResources/log.template", "hg.log.template");
+  private final MercurialLogTemplate myLogNoFilesTemplate = new MercurialLogTemplate("/buildServerResources/log.no.files.template", "hg.short.log.template");
+  private final MercurialLogTemplate myDagTemplate = new MercurialLogTemplate("/buildServerResources/dag.template", "hg.dag.template");
+  private final MercurialLogTemplate myFastLogTemplate = new MercurialLogTemplate("/buildServerResources/fastlog.template", "hg.fastlog.template");
+
+  public RepoFactory(@NotNull ServerPluginConfig config, @NotNull CommandSettingsFactory commandSettingsFactory) throws IOException {
     myConfig = config;
     myCommandSettingsFactory = commandSettingsFactory;
-    myLogTemplate = createLogTemplate();
-    myLogNoFilesTemplate = createLogNoFilesTemplate();
-    myDagTemplate = createDagTemplate();
   }
 
   @NotNull
@@ -37,61 +35,50 @@
                              @NotNull String hgPath,
                              @NotNull AuthSettings authSettings) throws VcsException {
     return new ServerHgRepo(myCommandSettingsFactory, myConfig, workingDir, hgPath, authSettings)
-            .withLogTemplates(getTemplate(), getLogNoFilesTemplate(), getDagTemplate());
+            .withLogTemplates(myLogTemplate.getTemplate(),
+                    myLogNoFilesTemplate.getTemplate(),
+                    myDagTemplate.getTemplate(),
+                    myFastLogTemplate.getTemplate());
   }
 
   public void dispose() {
-    delete(myLogTemplate);
-  }
-
-  private File getTemplate() throws VcsException {
-    if (myLogTemplate.isFile() && myLogTemplate.exists())
-      return myLogTemplate;
-    try {
-      myLogTemplate = createLogTemplate();
-      return myLogTemplate;
-    } catch (IOException e) {
-      throw new VcsException("Cannot create mercurial log template", e);
-    }
-  }
-
-  private File getLogNoFilesTemplate() throws VcsException {
-    if (myLogNoFilesTemplate.isFile() && myLogNoFilesTemplate.exists())
-      return myLogNoFilesTemplate;
-    try {
-      myLogNoFilesTemplate = createLogNoFilesTemplate();
-      return myLogNoFilesTemplate;
-    } catch (IOException e) {
-      throw new VcsException("Cannot create mercurial log template", e);
-    }
+    myLogTemplate.dispose();
+    myLogNoFilesTemplate.dispose();
+    myDagTemplate.dispose();
+    myFastLogTemplate.dispose();
   }
 
-  private File getDagTemplate() throws VcsException {
-    if (myDagTemplate.isFile() && myDagTemplate.exists())
-      return myDagTemplate;
-    try {
-      myDagTemplate = createLogNoFilesTemplate();
-      return myDagTemplate;
-    } catch (IOException e) {
-      throw new VcsException("Cannot create mercurial log template", e);
+  private static class MercurialLogTemplate {
+    private final String myResourcePath;
+    private final String myTmpFileSuffix;
+    private File myFile;
+
+    private MercurialLogTemplate(@NotNull String resourcePath, @NotNull String tmpFileSuffix) throws IOException {
+      myResourcePath = resourcePath;
+      myTmpFileSuffix = tmpFileSuffix;
+      copyTemplate();
+    }
+
+    @NotNull
+    public File getTemplate() throws VcsException {
+      if (myFile.isFile() && myFile.exists())
+        return myFile;
+      try {
+        copyTemplate();
+        return myFile;
+      } catch (IOException e) {
+        throw new VcsException("Cannot create mercurial log template", e);
+      }
+    }
+
+    public void dispose() {
+      delete(myFile);
+    }
+
+    private void copyTemplate() throws IOException {
+      File template = createTempFile("teamcity", myTmpFileSuffix);
+      FileUtil.copyResource(RepoFactory.class, myResourcePath, template);
+      myFile = template;
     }
   }
-
-  private File createLogTemplate() throws IOException {
-    return createTmpTemplateFile("hg.log.template", "/buildServerResources/log.template");
-  }
-
-  private File createLogNoFilesTemplate() throws IOException {
-    return createTmpTemplateFile("hg.short.log.template", "/buildServerResources/log.no.files.template");
-  }
-
-  private File createDagTemplate() throws IOException {
-    return createTmpTemplateFile("hg.dag.template", "/buildServerResources/dag.template");
-  }
-
-  private File createTmpTemplateFile(@NotNull String tmpFileSuffix, @NotNull String resourcePath) throws IOException {
-    File template = createTempFile("teamcity", tmpFileSuffix);
-    FileUtil.copyResource(RepoFactory.class, resourcePath, template);
-    return template;
-  }
 }
--- a/mercurial-server/src/jetbrains/buildServer/buildTriggers/vcs/mercurial/ServerHgRepo.java	Mon Apr 08 13:06:17 2013 +0400
+++ b/mercurial-server/src/jetbrains/buildServer/buildTriggers/vcs/mercurial/ServerHgRepo.java	Tue Apr 09 21:18:11 2013 +0400
@@ -21,6 +21,7 @@
   private File myLogTemplate;
   private File myLogNoFilesTemplate;
   private File myDagTemplate;
+  private File myFastLogTemplate;
   private OperationContext myContext;
 
   public ServerHgRepo(@NotNull CommandSettingsFactory commandSettingsFactory,
@@ -39,10 +40,12 @@
 
   public ServerHgRepo withLogTemplates(@NotNull File logTemplate,
                                        @NotNull File logNoFilesTemplate,
-                                       @NotNull File dagTemplate) {
+                                       @NotNull File dagTemplate,
+                                       @NotNull File fastLogTemplate) {
     myLogTemplate = logTemplate;
     myLogNoFilesTemplate = logNoFilesTemplate;
     myDagTemplate = dagTemplate;
+    myFastLogTemplate = fastLogTemplate;
     return this;
   }
 
@@ -50,6 +53,11 @@
     return new LogCommand(myCommandSettingsFactory.create(), myHgPath, myWorkingDir, myAuthSettings).withTemplate(myLogTemplate);
   }
 
+  public LogCommand log(@NotNull HgVcsRoot root) {
+    File template = root.isSubrepo() && !myConfig.reportSubrepoChangesFileStatus() ? myFastLogTemplate : myLogTemplate;
+    return new LogCommand(myCommandSettingsFactory.create(), myHgPath, myWorkingDir, myAuthSettings).withTemplate(template);
+  }
+
   public MergeBaseCommand mergeBase() throws VcsException {
     HgVersion hgVersion = getHgVersion();
     if (hgVersion.isEqualsOrGreaterThan(REVSET_HG_VERSION))
@@ -61,13 +69,13 @@
   @NotNull
   public CollectChangesCommand collectChanges(@NotNull HgVcsRoot root) throws VcsException {
     if (myConfig.dontUseRevsets())
-      return new CollectChangesNoRevsets(this, myLogNoFilesTemplate);
+      return new CollectChangesNoRevsets(root, this, myLogNoFilesTemplate);
 
     HgVersion hgVersion = getHgVersion();
     if (hgVersion.isEqualsOrGreaterThan(REVSET_HG_VERSION)) {
-      return new CollectChangesWithRevsets(this);
+      return new CollectChangesWithRevsets(root, this);
     } else {
-      return new CollectChangesNoRevsets(this, myLogNoFilesTemplate);
+      return new CollectChangesNoRevsets(root, this, myLogNoFilesTemplate);
     }
   }
 
--- a/mercurial-server/src/jetbrains/buildServer/buildTriggers/vcs/mercurial/ServerPluginConfig.java	Mon Apr 08 13:06:17 2013 +0400
+++ b/mercurial-server/src/jetbrains/buildServer/buildTriggers/vcs/mercurial/ServerPluginConfig.java	Tue Apr 09 21:18:11 2013 +0400
@@ -31,4 +31,6 @@
 
   @Nullable
   public CronExpression getCleanupCronExpression();
+
+  public boolean reportSubrepoChangesFileStatus();
 }
--- a/mercurial-server/src/jetbrains/buildServer/buildTriggers/vcs/mercurial/ServerPluginConfigImpl.java	Mon Apr 08 13:06:17 2013 +0400
+++ b/mercurial-server/src/jetbrains/buildServer/buildTriggers/vcs/mercurial/ServerPluginConfigImpl.java	Tue Apr 09 21:18:11 2013 +0400
@@ -84,4 +84,8 @@
       return null;
     }
   }
+
+  public boolean reportSubrepoChangesFileStatus() {
+    return TeamCityProperties.getBoolean("teamcity.hg.reportSubrepoChangesFileStatus");
+  }
 }
--- a/mercurial-server/src/jetbrains/buildServer/buildTriggers/vcs/mercurial/command/CollectChangesNoRevsets.java	Mon Apr 08 13:06:17 2013 +0400
+++ b/mercurial-server/src/jetbrains/buildServer/buildTriggers/vcs/mercurial/command/CollectChangesNoRevsets.java	Tue Apr 09 21:18:11 2013 +0400
@@ -16,10 +16,12 @@
  */
 public class CollectChangesNoRevsets extends CollectChangesCommand {
 
-  private ServerHgRepo myRepo;
-  private File myLogNoFilesTemplate;
+  private final HgVcsRoot myRoot;
+  private final ServerHgRepo myRepo;
+  private final File myLogNoFilesTemplate;
 
-  public CollectChangesNoRevsets(@NotNull ServerHgRepo repo, @NotNull File logNoFilesTemplate) {
+  public CollectChangesNoRevsets(@NotNull HgVcsRoot root, @NotNull ServerHgRepo repo, @NotNull File logNoFilesTemplate) {
+    myRoot = root;
     myRepo = repo;
     myLogNoFilesTemplate = logNoFilesTemplate;
   }
@@ -117,7 +119,7 @@
 
 
   private List<ChangeSet> getAllHistoryUpTo(@NotNull final String revision) throws VcsException {
-    return myRepo.log()
+    return myRepo.log(myRoot)
             .fromRevision(revision)
             .toRevision("0")
             .showCommitsFromAllBranches()
@@ -127,7 +129,7 @@
 
 
   private List<ChangeSet> getRevisionsBetween(@NotNull String fromCommit, @NotNull String toCommit) throws VcsException {
-    return myRepo.log()
+    return myRepo.log(myRoot)
             .fromRevision(toCommit)
             .toRevision(fromCommit)
             .showCommitsFromAllBranches()
@@ -135,7 +137,7 @@
   }
 
   private List<ChangeSet> getRevisionsBetween(int fromRevNum, @NotNull String toCommit) throws VcsException {
-    return myRepo.log()
+    return myRepo.log(myRoot)
             .fromRevision(toCommit)
             .toRevision(String.valueOf(fromRevNum))
             .showCommitsFromAllBranches()
--- a/mercurial-server/src/jetbrains/buildServer/buildTriggers/vcs/mercurial/command/CollectChangesWithRevsets.java	Mon Apr 08 13:06:17 2013 +0400
+++ b/mercurial-server/src/jetbrains/buildServer/buildTriggers/vcs/mercurial/command/CollectChangesWithRevsets.java	Tue Apr 09 21:18:11 2013 +0400
@@ -1,6 +1,7 @@
 package jetbrains.buildServer.buildTriggers.vcs.mercurial.command;
 
 import jetbrains.buildServer.buildTriggers.vcs.mercurial.HgRepo;
+import jetbrains.buildServer.buildTriggers.vcs.mercurial.ServerHgRepo;
 import jetbrains.buildServer.vcs.VcsException;
 import org.jetbrains.annotations.NotNull;
 
@@ -11,9 +12,11 @@
  */
 public class CollectChangesWithRevsets extends CollectChangesCommand {
 
-  private HgRepo myRepo;
+  private final HgVcsRoot myRoot;
+  private final ServerHgRepo myRepo;
 
-  public CollectChangesWithRevsets(@NotNull HgRepo repo) {
+  public CollectChangesWithRevsets(@NotNull HgVcsRoot root, @NotNull ServerHgRepo repo) {
+    myRoot = root;
     myRepo = repo;
   }
 
@@ -34,7 +37,7 @@
         revsets.append(" + ").append(from);
       }
     }
-    return myRepo.log()
+    return myRepo.log(myRoot)
             .showCommitsFromAllBranches()
             .withRevsets(revsets.toString())
             .call();
--- a/mercurial-tests/src/jetbrains/buildServer/buildTriggers/vcs/mercurial/ServerPluginConfigBuilder.java	Mon Apr 08 13:06:17 2013 +0400
+++ b/mercurial-tests/src/jetbrains/buildServer/buildTriggers/vcs/mercurial/ServerPluginConfigBuilder.java	Tue Apr 09 21:18:11 2013 +0400
@@ -69,6 +69,10 @@
       public CronExpression getCleanupCronExpression() {
         return null;
       }
+
+      public boolean reportSubrepoChangesFileStatus() {
+        return false;
+      }
     };
   }