changeset 529:33a6be414903

TW-17489 support bookmarks Now they can be used in the branch and branch spec fields
author Dmitry Neverov <dmitry.neverov@jetbrains.com>
date Sat, 29 Dec 2012 18:32:56 +0400
parents 6df6580646b9
children a827c3756535
files .idea/libraries/TestNG.xml mercurial-common/src/jetbrains/buildServer/buildTriggers/vcs/mercurial/HgRepo.java mercurial-common/src/jetbrains/buildServer/buildTriggers/vcs/mercurial/command/BookmarksCommand.java mercurial-common/src/jetbrains/buildServer/buildTriggers/vcs/mercurial/command/BranchesCommand.java mercurial-server-tc/src/jetbrains/buildServer/buildTriggers/vcs/mercurial/MercurialBranchSupport.java mercurial-server/src/jetbrains/buildServer/buildTriggers/vcs/mercurial/MercurialVcsSupport.java mercurial-server/src/jetbrains/buildServer/buildTriggers/vcs/mercurial/ServerPluginConfig.java mercurial-server/src/jetbrains/buildServer/buildTriggers/vcs/mercurial/ServerPluginConfigImpl.java mercurial-tests/lib/testng-5.7-jdk15.jar mercurial-tests/lib/testng-6.8.jar mercurial-tests/src/jetbrains/buildServer/buildTriggers/vcs/mercurial/BookmarksTest.java mercurial-tests/src/jetbrains/buildServer/buildTriggers/vcs/mercurial/HgVersionConstraint.java mercurial-tests/src/jetbrains/buildServer/buildTriggers/vcs/mercurial/RequiredHgVersion.java mercurial-tests/src/jetbrains/buildServer/buildTriggers/vcs/mercurial/ServerPluginConfigBuilder.java mercurial-tests/testData/bookmarks/1/hg/00changelog.i mercurial-tests/testData/bookmarks/1/hg/bookmarks mercurial-tests/testData/bookmarks/1/hg/bookmarks.current mercurial-tests/testData/bookmarks/1/hg/branch mercurial-tests/testData/bookmarks/1/hg/cache/branchheads mercurial-tests/testData/bookmarks/1/hg/cache/tags mercurial-tests/testData/bookmarks/1/hg/dirstate mercurial-tests/testData/bookmarks/1/hg/last-message.txt mercurial-tests/testData/bookmarks/1/hg/requires mercurial-tests/testData/bookmarks/1/hg/store/00changelog.i mercurial-tests/testData/bookmarks/1/hg/store/00manifest.i mercurial-tests/testData/bookmarks/1/hg/store/data/a.i mercurial-tests/testData/bookmarks/1/hg/store/fncache mercurial-tests/testData/bookmarks/1/hg/store/undo mercurial-tests/testData/bookmarks/1/hg/undo.branch mercurial-tests/testData/bookmarks/1/hg/undo.desc mercurial-tests/testData/bookmarks/1/hg/undo.dirstate mercurial-tests/testData/bookmarks/2/hg/00changelog.i mercurial-tests/testData/bookmarks/2/hg/bookmarks mercurial-tests/testData/bookmarks/2/hg/bookmarks.current mercurial-tests/testData/bookmarks/2/hg/branch mercurial-tests/testData/bookmarks/2/hg/cache/branchheads mercurial-tests/testData/bookmarks/2/hg/cache/tags mercurial-tests/testData/bookmarks/2/hg/dirstate mercurial-tests/testData/bookmarks/2/hg/last-message.txt mercurial-tests/testData/bookmarks/2/hg/requires mercurial-tests/testData/bookmarks/2/hg/store/00changelog.i mercurial-tests/testData/bookmarks/2/hg/store/00manifest.i mercurial-tests/testData/bookmarks/2/hg/store/data/a.i mercurial-tests/testData/bookmarks/2/hg/store/fncache mercurial-tests/testData/bookmarks/2/hg/store/undo mercurial-tests/testData/bookmarks/2/hg/undo.bookmarks mercurial-tests/testData/bookmarks/2/hg/undo.branch mercurial-tests/testData/bookmarks/2/hg/undo.desc mercurial-tests/testData/bookmarks/2/hg/undo.dirstate mercurial-tests/testData/bookmarks/3/hg/00changelog.i mercurial-tests/testData/bookmarks/3/hg/bookmarks mercurial-tests/testData/bookmarks/3/hg/bookmarks.current mercurial-tests/testData/bookmarks/3/hg/branch mercurial-tests/testData/bookmarks/3/hg/cache/branchheads mercurial-tests/testData/bookmarks/3/hg/cache/tags mercurial-tests/testData/bookmarks/3/hg/dirstate mercurial-tests/testData/bookmarks/3/hg/last-message.txt mercurial-tests/testData/bookmarks/3/hg/requires mercurial-tests/testData/bookmarks/3/hg/store/00changelog.i mercurial-tests/testData/bookmarks/3/hg/store/00manifest.i mercurial-tests/testData/bookmarks/3/hg/store/data/a.i mercurial-tests/testData/bookmarks/3/hg/store/fncache mercurial-tests/testData/bookmarks/3/hg/store/undo mercurial-tests/testData/bookmarks/3/hg/undo.bookmarks mercurial-tests/testData/bookmarks/3/hg/undo.branch mercurial-tests/testData/bookmarks/3/hg/undo.desc mercurial-tests/testData/bookmarks/3/hg/undo.dirstate mercurial-tests/testData/bookmarks/4/hg/00changelog.i mercurial-tests/testData/bookmarks/4/hg/bookmarks mercurial-tests/testData/bookmarks/4/hg/bookmarks.current mercurial-tests/testData/bookmarks/4/hg/branch mercurial-tests/testData/bookmarks/4/hg/cache/branchheads mercurial-tests/testData/bookmarks/4/hg/cache/tags mercurial-tests/testData/bookmarks/4/hg/dirstate mercurial-tests/testData/bookmarks/4/hg/last-message.txt mercurial-tests/testData/bookmarks/4/hg/requires mercurial-tests/testData/bookmarks/4/hg/store/00changelog.i mercurial-tests/testData/bookmarks/4/hg/store/00manifest.i mercurial-tests/testData/bookmarks/4/hg/store/data/a.i mercurial-tests/testData/bookmarks/4/hg/store/fncache mercurial-tests/testData/bookmarks/4/hg/store/undo mercurial-tests/testData/bookmarks/4/hg/undo.bookmarks mercurial-tests/testData/bookmarks/4/hg/undo.branch mercurial-tests/testData/bookmarks/4/hg/undo.desc mercurial-tests/testData/bookmarks/4/hg/undo.dirstate mercurial-tests/testData/bookmarks/5/hg/00changelog.i mercurial-tests/testData/bookmarks/5/hg/bookmarks mercurial-tests/testData/bookmarks/5/hg/bookmarks.current mercurial-tests/testData/bookmarks/5/hg/branch mercurial-tests/testData/bookmarks/5/hg/cache/branchheads mercurial-tests/testData/bookmarks/5/hg/cache/tags mercurial-tests/testData/bookmarks/5/hg/dirstate mercurial-tests/testData/bookmarks/5/hg/last-message.txt mercurial-tests/testData/bookmarks/5/hg/requires mercurial-tests/testData/bookmarks/5/hg/store/00changelog.i mercurial-tests/testData/bookmarks/5/hg/store/00manifest.i mercurial-tests/testData/bookmarks/5/hg/store/data/a.i mercurial-tests/testData/bookmarks/5/hg/store/fncache mercurial-tests/testData/bookmarks/5/hg/store/undo mercurial-tests/testData/bookmarks/5/hg/undo.bookmarks mercurial-tests/testData/bookmarks/5/hg/undo.branch mercurial-tests/testData/bookmarks/5/hg/undo.desc mercurial-tests/testData/bookmarks/5/hg/undo.dirstate mercurial-tests/testData/bookmarks/README
diffstat 101 files changed, 478 insertions(+), 19 deletions(-) [+]
line wrap: on
line diff
--- a/.idea/libraries/TestNG.xml	Sat Dec 29 12:17:37 2012 +0400
+++ b/.idea/libraries/TestNG.xml	Sat Dec 29 18:32:56 2012 +0400
@@ -1,7 +1,7 @@
 <component name="libraryTable">
   <library name="TestNG">
     <CLASSES>
-      <root url="jar://$PROJECT_DIR$/mercurial-tests/lib/testng-5.7-jdk15.jar!/" />
+      <root url="jar://$PROJECT_DIR$/mercurial-tests/lib/testng-6.8.jar!/" />
     </CLASSES>
     <JAVADOC />
     <SOURCES />
--- a/mercurial-common/src/jetbrains/buildServer/buildTriggers/vcs/mercurial/HgRepo.java	Sat Dec 29 12:17:37 2012 +0400
+++ b/mercurial-common/src/jetbrains/buildServer/buildTriggers/vcs/mercurial/HgRepo.java	Sat Dec 29 18:32:56 2012 +0400
@@ -69,6 +69,10 @@
     return new BranchesCommand(myCommandSettingsFactory.create(), myHgPath, myWorkingDir, myAuthSettings);
   }
 
+  public BookmarksCommand bookmarks() {
+    return new BookmarksCommand(myCommandSettingsFactory.create(), myHgPath, myWorkingDir, myAuthSettings);
+  }
+
   public StatusCommand status() {
     return new StatusCommand(myCommandSettingsFactory.create(), myHgPath, myWorkingDir, myAuthSettings);
   }
@@ -105,6 +109,12 @@
     return isEmptyDir(myWorkingDir);
   }
 
+  public void resetBookmarks() {
+    File dotHg = new File(getWorkingDir(), ".hg");
+    FileUtil.delete(new File(dotHg, "bookmarks"));
+    FileUtil.delete(new File(dotHg, "bookmarks.current"));
+  }
+
   @NotNull
   public List<String> listFiles(@NotNull String revision) throws VcsException {
     List<FileStatus> fileStatuses = status()
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/mercurial-common/src/jetbrains/buildServer/buildTriggers/vcs/mercurial/command/BookmarksCommand.java	Sat Dec 29 18:32:56 2012 +0400
@@ -0,0 +1,25 @@
+package jetbrains.buildServer.buildTriggers.vcs.mercurial.command;
+
+import jetbrains.buildServer.buildTriggers.vcs.mercurial.HgVersion;
+import org.jetbrains.annotations.NotNull;
+import java.io.File;
+
+
+public class BookmarksCommand extends BranchesCommand {
+
+  //hg 2.4 automatically pulls bookmarks
+  public static final HgVersion REQUIRED_HG_VERSION = new HgVersion(2, 4, 0);
+
+  public BookmarksCommand(@NotNull CommandSettings commandSettings,
+                          @NotNull String hgPath,
+                          @NotNull File workingDir,
+                          @NotNull AuthSettings authSettings) {
+    super(commandSettings, hgPath, workingDir, authSettings);
+  }
+
+  @NotNull
+  @Override
+  protected String getBranchesCommand() {
+    return "bookmarks";
+  }
+}
--- a/mercurial-common/src/jetbrains/buildServer/buildTriggers/vcs/mercurial/command/BranchesCommand.java	Sat Dec 29 12:17:37 2012 +0400
+++ b/mercurial-common/src/jetbrains/buildServer/buildTriggers/vcs/mercurial/command/BranchesCommand.java	Sat Dec 29 18:32:56 2012 +0400
@@ -42,21 +42,26 @@
    * @return see above
    * @throws jetbrains.buildServer.vcs.VcsException if error occurs
    */
-  public Map<String, ChangeSet> call() throws VcsException {
+  public Map<String, String> call() throws VcsException {
     MercurialCommandLine cli = createCommandLine();
-    cli.addParameter("branches");
+    cli.addParameter(getBranchesCommand());
     CommandResult res = runCommand(cli);
     String stdout = res.getStdout();
-    Map<String, ChangeSet> result = new HashMap<String, ChangeSet>();
+    Map<String, String> result = new HashMap<String, String>();
     Pattern branchPattern = Pattern.compile("(.*)[\\s]+([0-9]+:[A-Za-z0-9]+).*");
     for (String line: stdout.split("[\r\n]+")) {
       Matcher matcher = branchPattern.matcher(line);
       if (matcher.matches()) {
         String branchName = matcher.group(1).trim();
         String changeId = matcher.group(2).trim();
-        result.put(branchName, new ChangeSet(changeId));
+        result.put(branchName, new ChangeSet(changeId).getId());
       }
     }
     return result;
   }
+
+  @NotNull
+  protected String getBranchesCommand() {
+    return "branches";
+  }
 }
--- a/mercurial-server-tc/src/jetbrains/buildServer/buildTriggers/vcs/mercurial/MercurialBranchSupport.java	Sat Dec 29 12:17:37 2012 +0400
+++ b/mercurial-server-tc/src/jetbrains/buildServer/buildTriggers/vcs/mercurial/MercurialBranchSupport.java	Sat Dec 29 18:32:56 2012 +0400
@@ -4,7 +4,7 @@
 import org.jetbrains.annotations.NotNull;
 
 
-public class MercurialBranchSupport implements BranchSupport, MercurialServerExtension {
+public class MercurialBranchSupport implements /*BranchSupport,*/ MercurialServerExtension {
   @NotNull
   public String getRemoteRunOnBranchPattern() {
     return "remote-run/*";
--- a/mercurial-server/src/jetbrains/buildServer/buildTriggers/vcs/mercurial/MercurialVcsSupport.java	Sat Dec 29 12:17:37 2012 +0400
+++ b/mercurial-server/src/jetbrains/buildServer/buildTriggers/vcs/mercurial/MercurialVcsSupport.java	Sat Dec 29 18:32:56 2012 +0400
@@ -37,6 +37,7 @@
 import java.io.IOException;
 import java.util.*;
 
+import static java.util.Collections.emptyMap;
 import static jetbrains.buildServer.buildTriggers.vcs.mercurial.HgFileUtil.deleteDir;
 
 /**
@@ -194,11 +195,11 @@
     HgVcsRoot hgRoot = myHgVcsRootFactory.createHgRoot(root);
     syncRepository(hgRoot);
     HgRepo repo = createRepo(hgRoot);
-    Map<String, ChangeSet> result = repo.branches().call();
-    ChangeSet cset = result.get(hgRoot.getBranchName());
-    if (cset == null)
+    Map<String, String> result = repo.branches().call();
+    String revision = result.get(hgRoot.getBranchName());
+    if (revision == null)
       throw new VcsException("Unable to find current version for the branch: " + hgRoot.getBranchName());
-    return cset.getId();
+    return revision;
   }
 
   public boolean sourcesUpdatePossibleIfChangesNotFound(@NotNull final VcsRoot root) {
@@ -385,6 +386,7 @@
     try {
       if (repo.isValidRepository()) {
         try {
+          resetBookmarks(repo);
           repo.pull().fromRepository(root.getRepository())
                   .withTimeout(myConfig.getPullTimeout())
                   .call();
@@ -405,6 +407,15 @@
     }
   }
 
+
+  private void resetBookmarks(HgRepo repo) throws VcsException {
+    if (!myConfig.bookmarksEnabled())
+      return;
+    HgVersion v = repo.version().call();
+    if (v.isEqualsOrGreaterThan(BookmarksCommand.REQUIRED_HG_VERSION))
+      repo.resetBookmarks();
+  }
+
   @Override
   public LabelingSupport getLabelingSupport() {
     return this;
@@ -418,24 +429,33 @@
   @NotNull
   public RepositoryStateData getCurrentState(@NotNull VcsRoot root) throws VcsException {
     HgVcsRoot hgRoot = myHgVcsRootFactory.createHgRoot(root);
-    Map<String, String> branchRevisions = getBranchesRevisions(hgRoot);
+    syncRepository(hgRoot);
+    Map<String, String> revisions = new HashMap<String, String>();
+    revisions.putAll(getBookmarkRevisions(hgRoot));
+    revisions.putAll(getBranchesRevisions(hgRoot));
     String defaultBranchName = hgRoot.getBranchName();
-    if (branchRevisions.get(defaultBranchName) == null) {
+    if (revisions.get(defaultBranchName) == null) {
       throw new VcsException("Cannot find revision of the default branch '" +
               defaultBranchName + "' of vcs root " + LogUtil.describe(root));
     }
-    return RepositoryStateData.createVersionState(defaultBranchName, branchRevisions);
+    return RepositoryStateData.createVersionState(defaultBranchName, revisions);
   }
 
   @NotNull
   private Map<String, String> getBranchesRevisions(@NotNull HgVcsRoot root) throws VcsException {
-    syncRepository(root);
     HgRepo repo = createRepo(root);
-    Map<String, String> result = new HashMap<String, String>();
-    for (Map.Entry<String, ChangeSet> entry : repo.branches().call().entrySet()) {
-      result.put(entry.getKey(), entry.getValue().getId());
-    }
-    return result;
+    return repo.branches().call();
+  }
+
+  @NotNull
+  private Map<String, String> getBookmarkRevisions(@NotNull HgVcsRoot root) throws VcsException {
+    ServerHgRepo repo = createRepo(root);
+    if (!myConfig.bookmarksEnabled())
+      return emptyMap();
+    HgVersion v = repo.version().call();
+    if (!v.isEqualsOrGreaterThan(BookmarksCommand.REQUIRED_HG_VERSION))
+      return emptyMap();
+    return repo.bookmarks().call();
   }
 
   @NotNull
--- a/mercurial-server/src/jetbrains/buildServer/buildTriggers/vcs/mercurial/ServerPluginConfig.java	Sat Dec 29 12:17:37 2012 +0400
+++ b/mercurial-server/src/jetbrains/buildServer/buildTriggers/vcs/mercurial/ServerPluginConfig.java	Sat Dec 29 18:32:56 2012 +0400
@@ -23,4 +23,6 @@
   Set<Long> getRevsetParentRootIds();
 
   public boolean detectSubrepoChanges();
+
+  public boolean bookmarksEnabled();
 }
--- a/mercurial-server/src/jetbrains/buildServer/buildTriggers/vcs/mercurial/ServerPluginConfigImpl.java	Sat Dec 29 12:17:37 2012 +0400
+++ b/mercurial-server/src/jetbrains/buildServer/buildTriggers/vcs/mercurial/ServerPluginConfigImpl.java	Sat Dec 29 18:32:56 2012 +0400
@@ -72,4 +72,8 @@
   public boolean detectSubrepoChanges() {
     return false;
   }
+
+  public boolean bookmarksEnabled() {
+    return TeamCityProperties.getBooleanOrTrue("teamcity.hg.enableBookmarks");
+  }
 }
Binary file mercurial-tests/lib/testng-5.7-jdk15.jar has changed
Binary file mercurial-tests/lib/testng-6.8.jar has changed
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/mercurial-tests/src/jetbrains/buildServer/buildTriggers/vcs/mercurial/BookmarksTest.java	Sat Dec 29 18:32:56 2012 +0400
@@ -0,0 +1,180 @@
+package jetbrains.buildServer.buildTriggers.vcs.mercurial;
+
+import com.intellij.openapi.diagnostic.Logger;
+import jetbrains.buildServer.TempFiles;
+import jetbrains.buildServer.log.Log4jFactory;
+import jetbrains.buildServer.vcs.RepositoryStateData;
+
+import jetbrains.buildServer.vcs.VcsRoot;
+import org.hamcrest.Description;
+import org.hamcrest.TypeSafeMatcher;
+import org.jetbrains.annotations.NotNull;
+import org.testng.annotations.*;
+
+import java.io.File;
+import java.io.IOException;
+
+import static com.intellij.openapi.util.io.FileUtil.delete;
+import static jetbrains.buildServer.buildTriggers.vcs.mercurial.BookmarksTest.RepositoryStateDataMatcher.hasBranch;
+import static jetbrains.buildServer.buildTriggers.vcs.mercurial.BookmarksTest.RepositoryStateDataMatcher.hasNoBranch;
+import static jetbrains.buildServer.buildTriggers.vcs.mercurial.MercurialSupportBuilder.mercurialSupport;
+import static jetbrains.buildServer.buildTriggers.vcs.mercurial.ServerPluginConfigBuilder.serverPluginConfig;
+import static jetbrains.buildServer.buildTriggers.vcs.mercurial.VcsRootBuilder.vcsRoot;
+import static org.hamcrest.MatcherAssert.assertThat;
+
+
+@RequiredHgVersion(min = "2.4")
+@Test(dataProviderClass = HgVersionConstraint.class, dataProvider = "create")
+public class BookmarksTest {
+
+  static {
+    Logger.setFactory(new Log4jFactory());
+  }
+
+  private TempFiles myTempFiles;
+  private File myRemoteRepository;
+  private ServerPluginConfig myConfig;
+  private MercurialVcsSupport myVcs;
+  private VcsRoot myRoot;
+
+  @BeforeMethod
+  public void setUp() throws Exception {
+    myTempFiles = new TempFiles();
+    myRemoteRepository = myTempFiles.createTempDir();
+    myConfig = serverPluginConfig()
+            .cachesDir(myTempFiles.createTempDir())
+            .hgPath(/*Util.getHgPath()*/"/home/nd/sandbox/3rdparty/mercurial/hg")
+            .build();
+    myVcs = mercurialSupport().withConfig(myConfig).build();
+
+    myRoot = vcsRoot().withUrl(myRemoteRepository.getAbsolutePath()).build();
+  }
+
+  @AfterMethod
+  public void tearDown() {
+    myTempFiles.cleanup();
+  }
+
+
+  public void current_state_should_include_bookmarks(@NotNull HgVersion _) throws Exception {
+    setupRemoteRepositoryWithTwoBookmarks();
+    RepositoryStateData state = myVcs.getCurrentState(myRoot);
+    assertThat(state, hasBranch("bookmark1").withRevision("15b4a116520d"));
+    assertThat(state, hasBranch("bookmark2").withRevision("e9f8f67888f5"));
+  }
+
+
+  public void remove_bookmark_when_it_is_removed_from_remote_repo(@NotNull HgVersion _) throws Exception {
+    cloneRepositoryWithTwoBookmarks();
+
+    allBookmarksRemoved();
+
+    RepositoryStateData state = myVcs.getCurrentState(myRoot);
+    assertThat(state, hasNoBranch("bookmark1"));
+    assertThat(state, hasNoBranch("bookmark2"));
+  }
+
+
+  public void update_bookmark_when_it_is_updated_in_remote_repo(@NotNull HgVersion _) throws Exception {
+    cloneRepositoryWithTwoBookmarks();
+
+    bookmark1Updated();
+
+    RepositoryStateData state = myVcs.getCurrentState(myRoot);
+    assertThat(state, hasBranch("bookmark1").withRevision("7597a4da7195"));
+  }
+
+
+  public void update_bookmark_when_it_is_deverged_in_remote_repo(@NotNull HgVersion _) throws Exception {
+    cloneRepositoryWithTwoBookmarks();
+
+    bookmark1Diverged();
+
+    RepositoryStateData state = myVcs.getCurrentState(myRoot);
+    assertThat(state, hasBranch("bookmark1").withRevision("e9f8f67888f5"));
+  }
+
+
+  public void prefer_branch_to_bookmark_when_their_names_collide(@NotNull HgVersion _) throws Exception {
+    cloneRepositoryWithTwoBookmarks();
+
+    branchWithNameBookmark2Created();
+
+    RepositoryStateData state = myVcs.getCurrentState(myRoot);
+    assertThat(state, hasBranch("bookmark2").withRevision("f63a14e873d6"));
+  }
+
+
+  private void setupRemoteRepositoryWithTwoBookmarks() throws IOException {
+    Util.copyRepository(new File("mercurial-tests/testData/bookmarks/1"), myRemoteRepository);
+  }
+
+  private void cloneRepositoryWithTwoBookmarks() throws Exception {
+    setupRemoteRepositoryWithTwoBookmarks();
+    myVcs.getCurrentState(myRoot);
+  }
+
+  private void bookmark1Updated() throws IOException {
+    updateRepository("mercurial-tests/testData/bookmarks/2");
+  }
+
+  private void allBookmarksRemoved() throws IOException {
+    updateRepository("mercurial-tests/testData/bookmarks/3");
+  }
+
+  private void bookmark1Diverged() throws IOException {
+    updateRepository("mercurial-tests/testData/bookmarks/4");
+  }
+
+  private void branchWithNameBookmark2Created() throws IOException {
+    updateRepository("mercurial-tests/testData/bookmarks/");
+    delete(myRemoteRepository);
+    Util.copyRepository(new File("mercurial-tests/testData/bookmarks/5"), myRemoteRepository);
+  }
+
+  private void updateRepository(@NotNull String path) throws IOException {
+    delete(myRemoteRepository);
+    Util.copyRepository(new File(path), myRemoteRepository);
+  }
+
+
+  static class RepositoryStateDataMatcher extends TypeSafeMatcher<RepositoryStateData> {
+
+    private String myBranch;
+    private String myRevision;
+
+    RepositoryStateDataMatcher(@NotNull String branch) {
+      myBranch = branch;
+    }
+
+    public static RepositoryStateDataMatcher hasBranch(@NotNull String branch) {
+      return new RepositoryStateDataMatcher(branch);
+    }
+
+    public static RepositoryStateDataMatcher hasNoBranch(@NotNull String branch) {
+      return new RepositoryStateDataMatcher(branch);
+    }
+
+    public RepositoryStateDataMatcher withRevision(@NotNull String revision) {
+      myRevision = revision;
+      return this;
+    }
+
+    @Override
+    public boolean matchesSafely(RepositoryStateData repositoryStateData) {
+      String actualRevision = repositoryStateData.getBranchRevisions().get(myBranch);
+      if (myRevision == null && actualRevision != null ||
+          myRevision != null && !myRevision.equals(actualRevision))
+        return false;
+      return true;
+    }
+
+    public void describeTo(Description description) {
+      if (myRevision == null) {
+        description.appendText("a repository state without branch ").appendValue(myBranch);
+      } else {
+        description.appendText("a repository state where branch ").appendValue(myBranch).appendText(" has revision ").appendValue(myRevision);
+      }
+    }
+  }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/mercurial-tests/src/jetbrains/buildServer/buildTriggers/vcs/mercurial/HgVersionConstraint.java	Sat Dec 29 18:32:56 2012 +0400
@@ -0,0 +1,37 @@
+package jetbrains.buildServer.buildTriggers.vcs.mercurial;
+
+import jetbrains.buildServer.buildTriggers.vcs.mercurial.command.TestCommandSettingsFactory;
+import jetbrains.buildServer.buildTriggers.vcs.mercurial.command.VersionCommand;
+import jetbrains.buildServer.buildTriggers.vcs.mercurial.command.exception.ParseHgVersionException;
+import org.jetbrains.annotations.NotNull;
+import org.testng.annotations.DataProvider;
+
+import java.io.File;
+import java.lang.reflect.Method;
+
+public class HgVersionConstraint {
+
+  @DataProvider
+  public static Object[][] create(Method testMethod) throws Exception {
+    HgVersion actualVersion = getHgVersion();
+    RequiredHgVersion constaint = testMethod.getAnnotation(RequiredHgVersion.class);
+    if (constaint == null)
+      constaint = testMethod.getDeclaringClass().getAnnotation(RequiredHgVersion.class);
+    if (constaint == null)
+      return new Object[][] { new Object[] { actualVersion }};
+    HgVersion requiredMinVersion = parse(constaint.min());
+    if (!actualVersion.isEqualsOrGreaterThan(requiredMinVersion))
+      return new Object[0][];
+    return new Object[][] { new Object[] { actualVersion }};
+  }
+
+  private static HgVersion getHgVersion() throws Exception {
+    VersionCommand versionCommand = new VersionCommand(new TestCommandSettingsFactory().create(), "/home/nd/sandbox/3rdparty/mercurial/hg"/*Util.getHgPath()*/, new File(".."));
+    return versionCommand.call();
+  }
+
+  private static HgVersion parse(@NotNull String version) throws ParseHgVersionException {
+    return HgVersion.parse("Mercurial Distributed SCM (version " + version);
+  }
+
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/mercurial-tests/src/jetbrains/buildServer/buildTriggers/vcs/mercurial/RequiredHgVersion.java	Sat Dec 29 18:32:56 2012 +0400
@@ -0,0 +1,9 @@
+package jetbrains.buildServer.buildTriggers.vcs.mercurial;
+
+import java.lang.annotation.ElementType;
+
+@java.lang.annotation.Retention(java.lang.annotation.RetentionPolicy.RUNTIME)
+@java.lang.annotation.Target({java.lang.annotation.ElementType.METHOD, ElementType.TYPE})
+public @interface RequiredHgVersion {
+  java.lang.String min() default "1.5.2";
+}
--- a/mercurial-tests/src/jetbrains/buildServer/buildTriggers/vcs/mercurial/ServerPluginConfigBuilder.java	Sat Dec 29 12:17:37 2012 +0400
+++ b/mercurial-tests/src/jetbrains/buildServer/buildTriggers/vcs/mercurial/ServerPluginConfigBuilder.java	Sat Dec 29 18:32:56 2012 +0400
@@ -52,10 +52,18 @@
       public boolean detectSubrepoChanges() {
         return myDetectSubrepoChanges;
       }
+
+      public boolean bookmarksEnabled() {
+        return true;
+      }
     };
   }
 
 
+  public static ServerPluginConfigBuilder serverPluginConfig() {
+    return new ServerPluginConfigBuilder();
+  }
+
   public ServerPluginConfigBuilder userPullProtocol(boolean doUse) {
     myUsePullProtocol = doUse;
     return this;
Binary file mercurial-tests/testData/bookmarks/1/hg/00changelog.i has changed
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/mercurial-tests/testData/bookmarks/1/hg/bookmarks	Sat Dec 29 18:32:56 2012 +0400
@@ -0,0 +1,2 @@
+15b4a116520d5134941c01c8926cf1d6c669ffd9 bookmark1
+e9f8f67888f53a4dc962fb95ae69f01f29e6b98c bookmark2
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/mercurial-tests/testData/bookmarks/1/hg/branch	Sat Dec 29 18:32:56 2012 +0400
@@ -0,0 +1,1 @@
+default
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/mercurial-tests/testData/bookmarks/1/hg/cache/branchheads	Sat Dec 29 18:32:56 2012 +0400
@@ -0,0 +1,2 @@
+e052c89b1159cc0b3aae6ffcf68a04768fc64325 5
+e052c89b1159cc0b3aae6ffcf68a04768fc64325 default
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/mercurial-tests/testData/bookmarks/1/hg/cache/tags	Sat Dec 29 18:32:56 2012 +0400
@@ -0,0 +1,2 @@
+5 e052c89b1159cc0b3aae6ffcf68a04768fc64325
+
Binary file mercurial-tests/testData/bookmarks/1/hg/dirstate has changed
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/mercurial-tests/testData/bookmarks/1/hg/last-message.txt	Sat Dec 29 18:32:56 2012 +0400
@@ -0,0 +1,1 @@
+merge 3
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/mercurial-tests/testData/bookmarks/1/hg/requires	Sat Dec 29 18:32:56 2012 +0400
@@ -0,0 +1,4 @@
+revlogv1
+fncache
+store
+dotencode
Binary file mercurial-tests/testData/bookmarks/1/hg/store/00changelog.i has changed
Binary file mercurial-tests/testData/bookmarks/1/hg/store/00manifest.i has changed
Binary file mercurial-tests/testData/bookmarks/1/hg/store/data/a.i has changed
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/mercurial-tests/testData/bookmarks/1/hg/store/fncache	Sat Dec 29 18:32:56 2012 +0400
@@ -0,0 +1,1 @@
+data/a.i
Binary file mercurial-tests/testData/bookmarks/1/hg/store/undo has changed
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/mercurial-tests/testData/bookmarks/1/hg/undo.branch	Sat Dec 29 18:32:56 2012 +0400
@@ -0,0 +1,1 @@
+default
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/mercurial-tests/testData/bookmarks/1/hg/undo.desc	Sat Dec 29 18:32:56 2012 +0400
@@ -0,0 +1,2 @@
+5
+commit
Binary file mercurial-tests/testData/bookmarks/1/hg/undo.dirstate has changed
Binary file mercurial-tests/testData/bookmarks/2/hg/00changelog.i has changed
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/mercurial-tests/testData/bookmarks/2/hg/bookmarks	Sat Dec 29 18:32:56 2012 +0400
@@ -0,0 +1,2 @@
+7597a4da7195ddb9dcf5d1fc7b9d78f829b78a5e bookmark1
+e9f8f67888f53a4dc962fb95ae69f01f29e6b98c bookmark2
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/mercurial-tests/testData/bookmarks/2/hg/bookmarks.current	Sat Dec 29 18:32:56 2012 +0400
@@ -0,0 +1,1 @@
+bookmark1
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/mercurial-tests/testData/bookmarks/2/hg/branch	Sat Dec 29 18:32:56 2012 +0400
@@ -0,0 +1,1 @@
+default
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/mercurial-tests/testData/bookmarks/2/hg/cache/branchheads	Sat Dec 29 18:32:56 2012 +0400
@@ -0,0 +1,2 @@
+7597a4da7195ddb9dcf5d1fc7b9d78f829b78a5e 6
+7597a4da7195ddb9dcf5d1fc7b9d78f829b78a5e default
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/mercurial-tests/testData/bookmarks/2/hg/cache/tags	Sat Dec 29 18:32:56 2012 +0400
@@ -0,0 +1,2 @@
+6 7597a4da7195ddb9dcf5d1fc7b9d78f829b78a5e
+
Binary file mercurial-tests/testData/bookmarks/2/hg/dirstate has changed
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/mercurial-tests/testData/bookmarks/2/hg/last-message.txt	Sat Dec 29 18:32:56 2012 +0400
@@ -0,0 +1,1 @@
+4
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/mercurial-tests/testData/bookmarks/2/hg/requires	Sat Dec 29 18:32:56 2012 +0400
@@ -0,0 +1,4 @@
+revlogv1
+fncache
+store
+dotencode
Binary file mercurial-tests/testData/bookmarks/2/hg/store/00changelog.i has changed
Binary file mercurial-tests/testData/bookmarks/2/hg/store/00manifest.i has changed
Binary file mercurial-tests/testData/bookmarks/2/hg/store/data/a.i has changed
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/mercurial-tests/testData/bookmarks/2/hg/store/fncache	Sat Dec 29 18:32:56 2012 +0400
@@ -0,0 +1,1 @@
+data/a.i
Binary file mercurial-tests/testData/bookmarks/2/hg/store/undo has changed
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/mercurial-tests/testData/bookmarks/2/hg/undo.bookmarks	Sat Dec 29 18:32:56 2012 +0400
@@ -0,0 +1,2 @@
+15b4a116520d5134941c01c8926cf1d6c669ffd9 bookmark1
+e9f8f67888f53a4dc962fb95ae69f01f29e6b98c bookmark2
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/mercurial-tests/testData/bookmarks/2/hg/undo.branch	Sat Dec 29 18:32:56 2012 +0400
@@ -0,0 +1,1 @@
+default
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/mercurial-tests/testData/bookmarks/2/hg/undo.desc	Sat Dec 29 18:32:56 2012 +0400
@@ -0,0 +1,2 @@
+6
+commit
Binary file mercurial-tests/testData/bookmarks/2/hg/undo.dirstate has changed
Binary file mercurial-tests/testData/bookmarks/3/hg/00changelog.i has changed
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/mercurial-tests/testData/bookmarks/3/hg/branch	Sat Dec 29 18:32:56 2012 +0400
@@ -0,0 +1,1 @@
+default
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/mercurial-tests/testData/bookmarks/3/hg/cache/branchheads	Sat Dec 29 18:32:56 2012 +0400
@@ -0,0 +1,2 @@
+7597a4da7195ddb9dcf5d1fc7b9d78f829b78a5e 6
+7597a4da7195ddb9dcf5d1fc7b9d78f829b78a5e default
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/mercurial-tests/testData/bookmarks/3/hg/cache/tags	Sat Dec 29 18:32:56 2012 +0400
@@ -0,0 +1,2 @@
+6 7597a4da7195ddb9dcf5d1fc7b9d78f829b78a5e
+
Binary file mercurial-tests/testData/bookmarks/3/hg/dirstate has changed
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/mercurial-tests/testData/bookmarks/3/hg/last-message.txt	Sat Dec 29 18:32:56 2012 +0400
@@ -0,0 +1,1 @@
+4
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/mercurial-tests/testData/bookmarks/3/hg/requires	Sat Dec 29 18:32:56 2012 +0400
@@ -0,0 +1,4 @@
+revlogv1
+fncache
+store
+dotencode
Binary file mercurial-tests/testData/bookmarks/3/hg/store/00changelog.i has changed
Binary file mercurial-tests/testData/bookmarks/3/hg/store/00manifest.i has changed
Binary file mercurial-tests/testData/bookmarks/3/hg/store/data/a.i has changed
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/mercurial-tests/testData/bookmarks/3/hg/store/fncache	Sat Dec 29 18:32:56 2012 +0400
@@ -0,0 +1,1 @@
+data/a.i
Binary file mercurial-tests/testData/bookmarks/3/hg/store/undo has changed
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/mercurial-tests/testData/bookmarks/3/hg/undo.bookmarks	Sat Dec 29 18:32:56 2012 +0400
@@ -0,0 +1,2 @@
+15b4a116520d5134941c01c8926cf1d6c669ffd9 bookmark1
+e9f8f67888f53a4dc962fb95ae69f01f29e6b98c bookmark2
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/mercurial-tests/testData/bookmarks/3/hg/undo.branch	Sat Dec 29 18:32:56 2012 +0400
@@ -0,0 +1,1 @@
+default
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/mercurial-tests/testData/bookmarks/3/hg/undo.desc	Sat Dec 29 18:32:56 2012 +0400
@@ -0,0 +1,2 @@
+6
+commit
Binary file mercurial-tests/testData/bookmarks/3/hg/undo.dirstate has changed
Binary file mercurial-tests/testData/bookmarks/4/hg/00changelog.i has changed
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/mercurial-tests/testData/bookmarks/4/hg/bookmarks	Sat Dec 29 18:32:56 2012 +0400
@@ -0,0 +1,2 @@
+e9f8f67888f53a4dc962fb95ae69f01f29e6b98c bookmark1
+7597a4da7195ddb9dcf5d1fc7b9d78f829b78a5e bookmark2
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/mercurial-tests/testData/bookmarks/4/hg/bookmarks.current	Sat Dec 29 18:32:56 2012 +0400
@@ -0,0 +1,1 @@
+bookmark2
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/mercurial-tests/testData/bookmarks/4/hg/branch	Sat Dec 29 18:32:56 2012 +0400
@@ -0,0 +1,1 @@
+default
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/mercurial-tests/testData/bookmarks/4/hg/cache/branchheads	Sat Dec 29 18:32:56 2012 +0400
@@ -0,0 +1,2 @@
+7597a4da7195ddb9dcf5d1fc7b9d78f829b78a5e 6
+7597a4da7195ddb9dcf5d1fc7b9d78f829b78a5e default
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/mercurial-tests/testData/bookmarks/4/hg/cache/tags	Sat Dec 29 18:32:56 2012 +0400
@@ -0,0 +1,2 @@
+6 7597a4da7195ddb9dcf5d1fc7b9d78f829b78a5e
+
Binary file mercurial-tests/testData/bookmarks/4/hg/dirstate has changed
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/mercurial-tests/testData/bookmarks/4/hg/last-message.txt	Sat Dec 29 18:32:56 2012 +0400
@@ -0,0 +1,1 @@
+4
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/mercurial-tests/testData/bookmarks/4/hg/requires	Sat Dec 29 18:32:56 2012 +0400
@@ -0,0 +1,4 @@
+revlogv1
+fncache
+store
+dotencode
Binary file mercurial-tests/testData/bookmarks/4/hg/store/00changelog.i has changed
Binary file mercurial-tests/testData/bookmarks/4/hg/store/00manifest.i has changed
Binary file mercurial-tests/testData/bookmarks/4/hg/store/data/a.i has changed
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/mercurial-tests/testData/bookmarks/4/hg/store/fncache	Sat Dec 29 18:32:56 2012 +0400
@@ -0,0 +1,1 @@
+data/a.i
Binary file mercurial-tests/testData/bookmarks/4/hg/store/undo has changed
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/mercurial-tests/testData/bookmarks/4/hg/undo.bookmarks	Sat Dec 29 18:32:56 2012 +0400
@@ -0,0 +1,2 @@
+15b4a116520d5134941c01c8926cf1d6c669ffd9 bookmark1
+e9f8f67888f53a4dc962fb95ae69f01f29e6b98c bookmark2
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/mercurial-tests/testData/bookmarks/4/hg/undo.branch	Sat Dec 29 18:32:56 2012 +0400
@@ -0,0 +1,1 @@
+default
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/mercurial-tests/testData/bookmarks/4/hg/undo.desc	Sat Dec 29 18:32:56 2012 +0400
@@ -0,0 +1,2 @@
+6
+commit
Binary file mercurial-tests/testData/bookmarks/4/hg/undo.dirstate has changed
Binary file mercurial-tests/testData/bookmarks/5/hg/00changelog.i has changed
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/mercurial-tests/testData/bookmarks/5/hg/bookmarks	Sat Dec 29 18:32:56 2012 +0400
@@ -0,0 +1,2 @@
+e9f8f67888f53a4dc962fb95ae69f01f29e6b98c bookmark1
+7597a4da7195ddb9dcf5d1fc7b9d78f829b78a5e bookmark2
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/mercurial-tests/testData/bookmarks/5/hg/bookmarks.current	Sat Dec 29 18:32:56 2012 +0400
@@ -0,0 +1,1 @@
+bookmark2
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/mercurial-tests/testData/bookmarks/5/hg/branch	Sat Dec 29 18:32:56 2012 +0400
@@ -0,0 +1,1 @@
+bookmark2
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/mercurial-tests/testData/bookmarks/5/hg/cache/branchheads	Sat Dec 29 18:32:56 2012 +0400
@@ -0,0 +1,3 @@
+f63a14e873d65cbad50c3a15a4b7336d773e034f 7
+7597a4da7195ddb9dcf5d1fc7b9d78f829b78a5e default
+f63a14e873d65cbad50c3a15a4b7336d773e034f bookmark2
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/mercurial-tests/testData/bookmarks/5/hg/cache/tags	Sat Dec 29 18:32:56 2012 +0400
@@ -0,0 +1,2 @@
+7 f63a14e873d65cbad50c3a15a4b7336d773e034f
+
Binary file mercurial-tests/testData/bookmarks/5/hg/dirstate has changed
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/mercurial-tests/testData/bookmarks/5/hg/last-message.txt	Sat Dec 29 18:32:56 2012 +0400
@@ -0,0 +1,1 @@
+Create branch bookmark2
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/mercurial-tests/testData/bookmarks/5/hg/requires	Sat Dec 29 18:32:56 2012 +0400
@@ -0,0 +1,4 @@
+revlogv1
+fncache
+store
+dotencode
Binary file mercurial-tests/testData/bookmarks/5/hg/store/00changelog.i has changed
Binary file mercurial-tests/testData/bookmarks/5/hg/store/00manifest.i has changed
Binary file mercurial-tests/testData/bookmarks/5/hg/store/data/a.i has changed
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/mercurial-tests/testData/bookmarks/5/hg/store/fncache	Sat Dec 29 18:32:56 2012 +0400
@@ -0,0 +1,1 @@
+data/a.i
Binary file mercurial-tests/testData/bookmarks/5/hg/store/undo has changed
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/mercurial-tests/testData/bookmarks/5/hg/undo.bookmarks	Sat Dec 29 18:32:56 2012 +0400
@@ -0,0 +1,2 @@
+e9f8f67888f53a4dc962fb95ae69f01f29e6b98c bookmark1
+7597a4da7195ddb9dcf5d1fc7b9d78f829b78a5e bookmark2
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/mercurial-tests/testData/bookmarks/5/hg/undo.branch	Sat Dec 29 18:32:56 2012 +0400
@@ -0,0 +1,1 @@
+bookmark2
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/mercurial-tests/testData/bookmarks/5/hg/undo.desc	Sat Dec 29 18:32:56 2012 +0400
@@ -0,0 +1,2 @@
+7
+commit
Binary file mercurial-tests/testData/bookmarks/5/hg/undo.dirstate has changed
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/mercurial-tests/testData/bookmarks/README	Sat Dec 29 18:32:56 2012 +0400
@@ -0,0 +1,69 @@
+1) repository with 2 bookmarks (base for tests):
+
+o    5:e052c89b1159 merge 3 [bookmark2]
+|\
+| o  4:e9f8f67888f5 test 1
+| |
+o |  3:15b4a116520d 3 [bookmark1]
+| |
+o |  2:c17933ca5f6e 2
+|/
+o  1:016d505d681f 1
+|
+o  0:121c31c787d1 initial
+
+
+2) bookmark1 udpated:
+
+o  6:7597a4da7195 4 [bookmark1]
+|
+o    5:e052c89b1159 merge 3 [bookmark2]
+|\
+| o  4:e9f8f67888f5 test 1
+| |
+o |  3:15b4a116520d 3
+| |
+o |  2:c17933ca5f6e 2
+|/
+o  1:016d505d681f 1
+|
+o  0:121c31c787d1 initial
+
+
+3) all bookmarks removed
+
+
+4) bookmark1 diverged
+
+o  6:7597a4da7195 4 [bookmark2]
+|
+o    5:e052c89b1159 merge 3
+|\
+| o  4:e9f8f67888f5 test 1 [bookmark1]
+| |
+o |  3:15b4a116520d 3
+| |
+o |  2:c17933ca5f6e 2
+|/
+o  1:016d505d681f 1
+|
+o  0:121c31c787d1 initial
+
+
+5) branch with name 'bookmark2' created:
+
+o  7:f63a14e873d6 Create branch bookmark2 (bookmark2)
+|
+o  6:7597a4da7195 4 [bookmark2]
+|
+o    5:e052c89b1159 merge 3
+|\
+| o  4:e9f8f67888f5 test 1 [bookmark1]
+| |
+o |  3:15b4a116520d 3
+| |
+o |  2:c17933ca5f6e 2
+|/
+o  1:016d505d681f 1
+|
+o  0:121c31c787d1 initial
\ No newline at end of file