changeset 873:95e7d2ff8945

Run hg pull with progress
author Dmitry Neverov <dmitry.neverov@jetbrains.com>
date Tue, 30 Sep 2014 18:27:09 +0200
parents a6405f5aad54
children 894b7e0c9dd6
files mercurial-common/src/jetbrains/buildServer/buildTriggers/vcs/mercurial/command/PullCommand.java mercurial-server/src/jetbrains/buildServer/buildTriggers/vcs/mercurial/MercurialCollectChangesPolicy.java mercurial-server/src/jetbrains/buildServer/buildTriggers/vcs/mercurial/MercurialVcsSupport.java mercurial-server/src/jetbrains/buildServer/buildTriggers/vcs/mercurial/OperationContext.java mercurial-tests/src/jetbrains/buildServer/buildTriggers/vcs/mercurial/MercurialSupportBuilder.java
diffstat 5 files changed, 93 insertions(+), 17 deletions(-) [+]
line wrap: on
line diff
--- a/mercurial-common/src/jetbrains/buildServer/buildTriggers/vcs/mercurial/command/PullCommand.java	Wed Sep 24 20:38:50 2014 +0200
+++ b/mercurial-common/src/jetbrains/buildServer/buildTriggers/vcs/mercurial/command/PullCommand.java	Tue Sep 30 18:27:09 2014 +0200
@@ -88,12 +88,18 @@
       cli.addParameters("--config", "progress.format=topic number");
       cli.addParameters("--config", "progress.delay=0");
       cli.addParameters("--config", "progress.assume-tty=True");
+      myProgressConsumer.consume(-1f, "hg pull " + myAuthSettings.getRepositoryUrlWithHiddenPassword(myPullUrl));
       settings.setProgressConsumer(myProgressConsumer);
     }
 
     String pullUrl = myAuthSettings.getRepositoryUrlWithCredentials(myPullUrl);
     cli.addParameter(pullUrl);
-    runCommand(cli, settings);
+    try {
+      runCommand(cli, settings);
+    } finally {
+      if (myProgressConsumer != null)
+        myProgressConsumer.consume(-1f, "hg pull " + myAuthSettings.getRepositoryUrlWithHiddenPassword(myPullUrl) + " finished");
+    }
   }
 
   private void ensureRepositoryIsNotLocked() {
--- a/mercurial-server/src/jetbrains/buildServer/buildTriggers/vcs/mercurial/MercurialCollectChangesPolicy.java	Wed Sep 24 20:38:50 2014 +0200
+++ b/mercurial-server/src/jetbrains/buildServer/buildTriggers/vcs/mercurial/MercurialCollectChangesPolicy.java	Tue Sep 30 18:27:09 2014 +0200
@@ -16,10 +16,7 @@
 
 package jetbrains.buildServer.buildTriggers.vcs.mercurial;
 
-import jetbrains.buildServer.buildTriggers.vcs.mercurial.command.ChangeSet;
-import jetbrains.buildServer.buildTriggers.vcs.mercurial.command.ChangeSetRevision;
-import jetbrains.buildServer.buildTriggers.vcs.mercurial.command.HgVcsRoot;
-import jetbrains.buildServer.buildTriggers.vcs.mercurial.command.LogCommand;
+import jetbrains.buildServer.buildTriggers.vcs.mercurial.command.*;
 import jetbrains.buildServer.buildTriggers.vcs.mercurial.command.exception.UnknownRevisionException;
 import jetbrains.buildServer.buildTriggers.vcs.mercurial.command.exception.WrongSubrepoUrlException;
 import jetbrains.buildServer.log.Loggers;
@@ -38,18 +35,20 @@
 
   private final static AscendingRevNums ASCENDING_REV_NUMS = new AscendingRevNums();
 
+  private final VcsOperationProgressProvider myProgressProvider;
   private final MercurialVcsSupport myVcs;
   private final ServerPluginConfig myConfig;
   private final HgVcsRootFactory myHgVcsRootFactory;
   private final RepoFactory myRepoFactory;
   private final HgPathProvider myHgPathProvider;
 
-
-  public MercurialCollectChangesPolicy(@NotNull MercurialVcsSupport vcs,
+  public MercurialCollectChangesPolicy(@NotNull VcsOperationProgressProvider progressProvider,
+                                       @NotNull MercurialVcsSupport vcs,
                                        @NotNull ServerPluginConfig config,
                                        @NotNull HgVcsRootFactory hgVcsRootFactory,
                                        @NotNull RepoFactory repoFactory,
                                        @NotNull HgPathProvider hgPathProvider) {
+    myProgressProvider = progressProvider;
     myVcs = vcs;
     myConfig = config;
     myHgVcsRootFactory = hgVcsRootFactory;
@@ -66,7 +65,9 @@
         return getHeads(hgRoot);
       }
     };
-    Map<String, String> revisions = myVcs.syncRepository(hgRoot, new SyncSettings<Map<String, String>>(cmd));
+    SyncSettings<Map<String, String>> settings = new SyncSettings<Map<String, String>>(cmd);
+    settings.setProgressConsumer(createProgressConsumer());
+    Map<String, String> revisions = myVcs.syncRepository(hgRoot, settings);
     String defaultBranchName = hgRoot.getBranchName();
     if (revisions.get(defaultBranchName) == null && !hgRoot.isIgnoreMissingDefaultBranch()) {
       throw new VcsException("Cannot find revision of the default branch '" +
@@ -99,6 +100,7 @@
     List<ModificationData> changes = new ArrayList<ModificationData>();
     HgVcsRoot hgRoot = myHgVcsRootFactory.createHgRoot(root);
     OperationContext ctx = new OperationContext(myVcs, myRepoFactory, myHgPathProvider, fromState, toState);
+    ctx.setProgressConsumer(createProgressConsumer());
     for (Map.Entry<String, String> entry : toState.getBranchRevisions().entrySet()) {
       String branch = entry.getKey();
       String toRevision = entry.getValue();
@@ -129,7 +131,9 @@
                                                @Nullable String toRootRevision,
                                                @NotNull CheckoutRules checkoutRules) throws VcsException {
     HgVcsRoot hgRoot = myHgVcsRootFactory.createHgRoot(toRoot);
-    myVcs.syncRepository(hgRoot);
+    SyncSettings<Void> settings = new SyncSettings<Void>(VcsCallable.NO_OP);
+    settings.setProgressConsumer(createProgressConsumer());
+    myVcs.syncRepository(hgRoot, settings);
     String toRevision = toRootRevision;
     if (toRevision == null) {
       RepositoryStateData state = myVcs.getCollectChangesPolicy().getCurrentState(toRoot);
@@ -149,6 +153,7 @@
     if (currentVersion == null)
       return emptyList();
     OperationContext ctx = new OperationContext(myVcs, myRepoFactory, myHgPathProvider, fromVersion, currentVersion);
+    ctx.setProgressConsumer(createProgressConsumer());
     List<ModificationData> changes = collectChanges(ctx, root, asList(fromVersion), currentVersion, checkoutRules);
     changes.addAll(getSubrepoChanges(ctx, root, changes));
     return changes;
@@ -181,12 +186,15 @@
   }
 
 
-  public List<ModificationData> collectChanges(@NotNull OperationContext ctx,
-                                               @NotNull VcsRoot root,
-                                               @NotNull Collection<String> fromVersion,
-                                               @Nullable String currentVersion,
-                                               @NotNull CheckoutRules checkoutRules) throws VcsException {
+  @NotNull
+  private List<ModificationData> collectChanges(@NotNull OperationContext ctx,
+                                                @NotNull VcsRoot root,
+                                                @NotNull Collection<String> fromVersion,
+                                                @Nullable String currentVersion,
+                                                @NotNull CheckoutRules checkoutRules) throws VcsException {
     HgVcsRoot hgRoot = myHgVcsRootFactory.createHgRoot(root);
+    SyncSettings<Void> settings = new SyncSettings<Void>(VcsCallable.NO_OP);
+    settings.setProgressConsumer(ctx.getProgressConsumer());
     ctx.syncRepository(hgRoot);
     List<ModificationData> result = new ArrayList<ModificationData>();
     List<ChangeSet> csets = getChangesets(ctx, hgRoot, fromVersion, currentVersion);
@@ -386,4 +394,51 @@
       return 0;
     }
   }
+
+
+  @Nullable
+  private ProgressParser.ProgressConsumer createProgressConsumer() {
+    try {
+      final VcsOperationProgress progress = myProgressProvider.getProgress();
+      return new VcsOperationProgressConsumer(progress);
+    } catch (IllegalStateException e) {
+      return null;
+    }
+  }
+
+  private static class VcsOperationProgressConsumer implements ProgressParser.ProgressConsumer {
+    private final VcsOperationProgress myProgress;
+    private String myPrevMessage;
+    private int myPrevPercents;
+    public VcsOperationProgressConsumer(@NotNull VcsOperationProgress progress) {
+      myProgress = progress;
+    }
+
+    public void consume(float progressPercents, @NotNull String stage) {
+      if (progressPercents < 0) {
+        resetPrevProgress();
+        myProgress.reportProgress(stage);
+      } else {
+        int percents = (int) Math.floor(progressPercents * 100);
+        if (!isDuplicate(stage, percents)) {
+          myProgress.reportProgress(stage + " " + percents + "%");
+          updatePrevProgress(stage, percents);
+        }
+      }
+    }
+
+    private void resetPrevProgress() {
+      myPrevMessage = null;
+      myPrevPercents = -1;
+    }
+
+    private boolean isDuplicate(@NotNull String message, int percents) {
+      return message.equals(myPrevMessage) && percents == myPrevPercents;
+    }
+
+    private void updatePrevProgress(@NotNull String message, int percents) {
+      myPrevMessage = message;
+      myPrevPercents = percents;
+    }
+  }
 }
--- a/mercurial-server/src/jetbrains/buildServer/buildTriggers/vcs/mercurial/MercurialVcsSupport.java	Wed Sep 24 20:38:50 2014 +0200
+++ b/mercurial-server/src/jetbrains/buildServer/buildTriggers/vcs/mercurial/MercurialVcsSupport.java	Tue Sep 30 18:27:09 2014 +0200
@@ -55,6 +55,7 @@
  * <p>Personal builds (remote runs) are not yet supported, they require corresponding functionality from the IDE.
  */
 public class MercurialVcsSupport extends ServerVcsSupport implements LabelingSupport, VcsFileContentProvider, BuildPatchByCheckoutRules {
+  private final VcsOperationProgressProvider myProgressProvider;
   private final MirrorManager myMirrorManager;
   private final ServerPluginConfig myConfig;
   private final HgPathProvider myHgPathProvider;
@@ -66,7 +67,8 @@
   private final SubrepoCheckoutRulesProvider mySubrepoCheckoutRulesProvider;
   private final Collection<MercurialServerExtension> myExtensions = new ArrayList<MercurialServerExtension>();
 
-  public MercurialVcsSupport(@NotNull final EventDispatcher<ServerListener> dispatcher,
+  public MercurialVcsSupport(@NotNull final VcsOperationProgressProvider progressProvider,
+                             @NotNull final EventDispatcher<ServerListener> dispatcher,
                              @NotNull final ResetCacheRegister resetCacheHandlerManager,
                              @NotNull final ServerPluginConfig config,
                              @NotNull final HgPathProvider hgPathProvider,
@@ -75,6 +77,7 @@
                              @NotNull final HgVcsRootFactory hgVcsRootFactory,
                              @NotNull final HgTestConnectionSupport testConnection,
                              @NotNull final SubrepoCheckoutRulesProvider subrepoCheckoutRulesProvider) {
+    myProgressProvider = progressProvider;
     myConfig = config;
     myMirrorManager = mirrorManager;
     myHgPathProvider = hgPathProvider;
@@ -621,7 +624,7 @@
 
   @NotNull
   public MercurialCollectChangesPolicy getCollectChangesPolicy() {
-    return new MercurialCollectChangesPolicy(this, myConfig, myHgVcsRootFactory, myRepoFactory, myHgPathProvider);
+    return new MercurialCollectChangesPolicy(myProgressProvider, this, myConfig, myHgVcsRootFactory, myRepoFactory, myHgPathProvider);
   }
 
 
--- a/mercurial-server/src/jetbrains/buildServer/buildTriggers/vcs/mercurial/OperationContext.java	Wed Sep 24 20:38:50 2014 +0200
+++ b/mercurial-server/src/jetbrains/buildServer/buildTriggers/vcs/mercurial/OperationContext.java	Tue Sep 30 18:27:09 2014 +0200
@@ -19,6 +19,7 @@
 import com.intellij.openapi.util.Pair;
 import gnu.trove.TLongObjectHashMap;
 import jetbrains.buildServer.buildTriggers.vcs.mercurial.command.HgVcsRoot;
+import jetbrains.buildServer.buildTriggers.vcs.mercurial.command.ProgressParser;
 import jetbrains.buildServer.util.Hash;
 import jetbrains.buildServer.util.graph.BFSVisitorAdapter;
 import jetbrains.buildServer.util.graph.DAG;
@@ -50,6 +51,7 @@
   private Map<File, ServerHgRepo> myRepos = new HashMap<File, ServerHgRepo>();
   private boolean myIncludeFromRevisions = false;//by default don't include them, they should be included only for subrepos
   private TLongObjectHashMap<String> myStringPool = new TLongObjectHashMap<String>();
+  private ProgressParser.ProgressConsumer myProgressConsumer;
 
   public OperationContext(@NotNull MercurialVcsSupport vcs,
                           @NotNull RepoFactory repoFactory,
@@ -316,4 +318,13 @@
       }
     }
   }
+
+  @Nullable
+  public ProgressParser.ProgressConsumer getProgressConsumer() {
+    return myProgressConsumer;
+  }
+
+  public void setProgressConsumer(ProgressParser.ProgressConsumer progressConsumer) {
+    myProgressConsumer = progressConsumer;
+  }
 }
--- a/mercurial-tests/src/jetbrains/buildServer/buildTriggers/vcs/mercurial/MercurialSupportBuilder.java	Wed Sep 24 20:38:50 2014 +0200
+++ b/mercurial-tests/src/jetbrains/buildServer/buildTriggers/vcs/mercurial/MercurialSupportBuilder.java	Tue Sep 30 18:27:09 2014 +0200
@@ -24,6 +24,7 @@
 import jetbrains.buildServer.util.EventDispatcher;
 import jetbrains.buildServer.util.cache.ResetCacheHandler;
 import jetbrains.buildServer.util.cache.ResetCacheRegister;
+import jetbrains.buildServer.vcs.MockVcsOperationProgressProvider;
 import jetbrains.buildServer.vcs.SubrepoCheckoutRulesProviderImpl;
 import org.jetbrains.annotations.NotNull;
 import org.jmock.Expectations;
@@ -61,7 +62,7 @@
     myContext.checking(new Expectations() {{
       allowing(resetCacheManager).registerHandler(with(any(ResetCacheHandler.class)));
     }});
-    MercurialVcsSupport vcs = new MercurialVcsSupport(dispatcher, resetCacheManager, myConfig, myHgPathProvider,
+    MercurialVcsSupport vcs = new MercurialVcsSupport(new MockVcsOperationProgressProvider(), dispatcher, resetCacheManager, myConfig, myHgPathProvider,
             myRepoFactory, mirrorManager, myHgRootFactory, testConnection, new SubrepoCheckoutRulesProviderImpl());
     vcs.addExtensions(myExtensions);
     return vcs;