changeset 552:ba4f9148d39e

Optimize changes collecting
author Dmitry Neverov <dmitry.neverov@jetbrains.com>
date Mon, 25 Feb 2013 17:53:40 +0400
parents 4a18bdd61aa6
children ccc305e56189
files mercurial-server/src/jetbrains/buildServer/buildTriggers/vcs/mercurial/MercurialVcsSupport.java mercurial-tests/src/jetbrains/buildServer/buildTriggers/vcs/mercurial/MercurialVcsSupportTest.java
diffstat 2 files changed, 62 insertions(+), 3 deletions(-) [+]
line wrap: on
line diff
--- a/mercurial-server/src/jetbrains/buildServer/buildTriggers/vcs/mercurial/MercurialVcsSupport.java	Mon Feb 25 16:49:13 2013 +0400
+++ b/mercurial-server/src/jetbrains/buildServer/buildTriggers/vcs/mercurial/MercurialVcsSupport.java	Mon Feb 25 17:53:40 2013 +0400
@@ -477,6 +477,8 @@
                                                @NotNull CheckoutRules rules) throws VcsException {
     Set<String> reportedCsetIds = new HashSet<String>();
     List<ModificationData> changes = new ArrayList<ModificationData>();
+    OperationContext ctx = new OperationContext(this, myRepoFactory);
+    Set<String> prevStateRevisions = new HashSet<String>(fromState.getBranchRevisions().values());
     for (Map.Entry<String, String> entry : toState.getBranchRevisions().entrySet()) {
       String branch = entry.getKey();
       String toRevision = entry.getValue();
@@ -485,7 +487,9 @@
         fromRevision = fromState.getBranchRevisions().get(fromState.getDefaultBranchName());
       if (toRevision.equals(fromRevision))
         continue;
-      List<ModificationData> branchChanges = collectChanges(root, fromRevision, toRevision, rules);
+
+      List<String> fromRevisions = getFromRevisionsForBranch(ctx, root, prevStateRevisions, fromRevision, toRevision);
+      List<ModificationData> branchChanges = collectChanges(ctx, root, fromRevisions, toRevision, rules);
       for (ModificationData change : branchChanges) {
         if (reportedCsetIds.add(change.getVersion()))
           changes.add(change);
@@ -494,6 +498,53 @@
     return changes;
   }
 
+
+  /**
+   * Collecting changes is per branch. We usually take branch revision in fromState,
+   * revision in toState and collect changes between them. This can lead to redundant
+   * changes being reported. Consider the following graph:
+   *
+   * default
+   * | topic
+   * |  |
+   * V  V
+   *101
+   * |\
+   * | 100
+   * | |
+   *99 |
+   *.....
+   * | |
+   * |/
+   * 1
+   *
+   * When changes are collected between states {default:99, topic:100} and {default: 101, topic:100},
+   * plugin reports changes from 1 to 101, even though it probably has reported changes reachable
+   * from 100 earlier.
+   *
+   * This method detects such a case and returns [99, 100] as fromRevisions for 101.
+   */
+  @NotNull
+  private List<String> getFromRevisionsForBranch(@NotNull OperationContext ctx,
+                                                 @NotNull VcsRoot root,
+                                                 @NotNull Set<String> prevStateRevisions,
+                                                 @NotNull String fromRevision,
+                                                 @NotNull String toRevision) throws VcsException {
+    List<String> fromRevisions = new ArrayList<String>();
+    fromRevisions.add(fromRevision);
+
+    HgVcsRoot hgRoot = myHgVcsRootFactory.createHgRoot(root);
+    ctx.syncRepository(hgRoot);
+    ServerHgRepo repo = createRepo(ctx, hgRoot);
+    List<String> parentRevisions = repo.parents().ofRevision(toRevision).call();
+    for (String parent : parentRevisions) {
+      if (!fromRevision.equals(parent) && prevStateRevisions.contains(parent))
+        fromRevisions.add(parent);
+    }
+
+    return fromRevisions;
+  }
+
   @NotNull
   public List<ModificationData> collectChanges(@NotNull VcsRoot fromRoot, @NotNull String fromRootRevision,
                                                @NotNull VcsRoot toRoot, @Nullable String toRootRevision,
--- a/mercurial-tests/src/jetbrains/buildServer/buildTriggers/vcs/mercurial/MercurialVcsSupportTest.java	Mon Feb 25 16:49:13 2013 +0400
+++ b/mercurial-tests/src/jetbrains/buildServer/buildTriggers/vcs/mercurial/MercurialVcsSupportTest.java	Mon Feb 25 17:53:40 2013 +0400
@@ -20,8 +20,6 @@
 import jetbrains.buildServer.vcs.*;
 import jetbrains.buildServer.vcs.impl.VcsRootImpl;
 import junit.framework.Assert;
-import org.hamcrest.Description;
-import org.hamcrest.TypeSafeMatcher;
 import org.jetbrains.annotations.NotNull;
 import org.testng.annotations.BeforeMethod;
 import org.testng.annotations.Test;
@@ -593,6 +591,16 @@
   }
 
 
+  public void should_not_report_redundant_changes_after_merge() throws Exception {
+    VcsRootImpl root = createVcsRoot(myRep2Path);
+    List<ModificationData> changes = myVcs.collectChanges(root,
+            RepositoryStateData.createVersionState("default", map("default", "505c5b9d01e6", "personal-branch", "9ec402c74298")),
+            RepositoryStateData.createVersionState("default", map("default", "df04faa7575a", "personal-branch", "9ec402c74298")),
+            CheckoutRules.DEFAULT);
+    assertEquals(changes.size(), 1);
+  }
+
+
   private void assertFiles(final List<String> expectedFiles, final ModificationData modificationData) {
     Set<String> actualFiles = new HashSet<String>();
     for (VcsChange vc: modificationData.getChanges()) {