diff mercurial-server/src/jetbrains/buildServer/buildTriggers/vcs/mercurial/MercurialVcsSupport.java @ 44:1490e2981799

labeling/tagging support
author Pavel.Sher
date Fri, 05 Sep 2008 01:15:29 +0400
parents 1c11478f515b
children 13d5f0f56e70
line wrap: on
line diff
--- a/mercurial-server/src/jetbrains/buildServer/buildTriggers/vcs/mercurial/MercurialVcsSupport.java	Fri Aug 22 20:21:48 2008 +0400
+++ b/mercurial-server/src/jetbrains/buildServer/buildTriggers/vcs/mercurial/MercurialVcsSupport.java	Fri Sep 05 01:15:29 2008 +0400
@@ -53,7 +53,7 @@
  * <p>Personal builds (remote runs) are not yet supported, they require corresponding functionality from the IDE.
  * <p>Checkout on agent mode is not yet supported too.
  */
-public class MercurialVcsSupport extends VcsSupport implements CollectChangesByIncludeRule {
+public class MercurialVcsSupport extends VcsSupport implements CollectChangesByIncludeRule, LabelingSupport {
   private ConcurrentMap<String, Lock> myWorkDirLocks= new ConcurrentHashMap<String, Lock>();
   private static final int OLD_WORK_DIRS_CLEANUP_PERIOD = 600;
   private VcsManager myVcsManager;
@@ -76,7 +76,7 @@
                                                     @NotNull final String fromVersion,
                                                     @NotNull final String currentVersion,
                                                     final CheckoutRules checkoutRules) throws VcsException {
-    updateWorkingDirectory(root);
+    syncClonedRepository(root);
     return VcsSupportUtil.collectBuildChanges(root, fromVersion, currentVersion, checkoutRules, this);
   }
 
@@ -86,7 +86,7 @@
                                                     final IncludeRule includeRule) throws VcsException {
     // first obtain changes between specified versions
     List<ModificationData> result = new ArrayList<ModificationData>();
-    Settings settings = new Settings(myDefaultWorkFolderParent, root);
+    Settings settings = createSettings(root);
     LogCommand lc = new LogCommand(settings);
     lc.setFromRevId(new ChangeSet(fromVersion).getId());
     lc.setToRevId(new ChangeSet(currentVersion).getId());
@@ -146,15 +146,15 @@
                            final VcsChangeInfo change,
                            final VcsChangeInfo.ContentType contentType,
                            final VcsRoot vcsRoot) throws VcsException {
-    updateWorkingDirectory(vcsRoot);
+    syncClonedRepository(vcsRoot);
     String version = contentType == VcsChangeInfo.ContentType.AFTER_CHANGE ? change.getAfterChangeRevisionNumber() : change.getBeforeChangeRevisionNumber();
     return getContent(change.getRelativeFileName(), vcsRoot, version);
   }
 
   @NotNull
   public byte[] getContent(final String filePath, final VcsRoot vcsRoot, final String version) throws VcsException {
-    updateWorkingDirectory(vcsRoot);
-    Settings settings = new Settings(myDefaultWorkFolderParent, vcsRoot);
+    syncClonedRepository(vcsRoot);
+    Settings settings = createSettings(vcsRoot);
     CatCommand cc = new CatCommand(settings);
     ChangeSet cs = new ChangeSet(version);
     cc.setRevId(cs.getId());
@@ -208,8 +208,8 @@
   @NotNull
   public String getCurrentVersion(final VcsRoot root) throws VcsException {
     // we will return full version of the most recent change as current version
-    updateWorkingDirectory(root);
-    Settings settings = new Settings(myDefaultWorkFolderParent, root);
+    syncClonedRepository(root);
+    Settings settings = createSettings(root);
     TipCommand lc = new TipCommand(settings);
     ChangeSet changeSet = lc.execute();
     return changeSet.getFullVersion();
@@ -225,7 +225,7 @@
 
   @Nullable
   public String testConnection(final VcsRoot vcsRoot) throws VcsException {
-    Settings settings = new Settings(myDefaultWorkFolderParent, vcsRoot);
+    Settings settings = createSettings(vcsRoot);
     IdentifyCommand id = new IdentifyCommand(settings);
     StringBuilder res = new StringBuilder();
     res.append(quoteIfNeeded(settings.getHgCommandPath()));
@@ -273,8 +273,8 @@
                          @NotNull final String toVersion,
                          final PatchBuilder builder,
                          final CheckoutRules checkoutRules) throws IOException, VcsException {
-    updateWorkingDirectory(root);
-    Settings settings = new Settings(myDefaultWorkFolderParent, root);
+    syncClonedRepository(root);
+    Settings settings = createSettings(root);
     if (fromVersion == null) {
       buildFullPatch(settings, new ChangeSet(toVersion), builder);
     } else {
@@ -366,8 +366,8 @@
   }
 
   // updates current working copy of repository by pulling changes from the repository specified in VCS root
-  private void updateWorkingDirectory(final VcsRoot root) throws VcsException {
-    Settings settings = new Settings(myDefaultWorkFolderParent, root);
+  private void syncClonedRepository(final VcsRoot root) throws VcsException {
+    Settings settings = createSettings(root);
     File workDir = settings.getWorkingDir();
     lockWorkDir(workDir);
     try {
@@ -387,6 +387,11 @@
     }
   }
 
+  @Override
+  public LabelingSupport getLabelingSupport() {
+    return this;
+  }
+
   private void lockWorkDir(@NotNull File workDir) {
     getWorkDirLock(workDir).lock();
   }
@@ -433,7 +438,7 @@
 
     for (VcsRoot vcsRoot: myVcsManager.getAllRegisteredVcsRoots()) {
       if (getName().equals(vcsRoot.getVcsName())) {
-        Settings s = new Settings(myDefaultWorkFolderParent, vcsRoot);
+        Settings s = createSettings(vcsRoot);
         workDirs.remove(FileUtil.getCanonicalFile(s.getWorkingDir()));
       }
     }
@@ -447,4 +452,41 @@
       }
     }
   }
+
+  public String label(@NotNull String label, @NotNull String version, @NotNull VcsRoot root, @NotNull CheckoutRules checkoutRules) throws VcsException {
+    syncClonedRepository(root);
+
+    Settings settings = createSettings(root);
+
+    // I do not know why but hg tag does not work correctly if
+    // update command was not invoked for the current repo
+    // in such case if there were no tags before Mercurial attempts to
+    // create new head when tag is pushed to the parent repository
+    UpdateCommand uc = new UpdateCommand(settings);
+    uc.execute();
+
+    String fixedTagname = fixTagName(label);
+    TagCommand tc = new TagCommand(settings);
+    tc.setRevId(new ChangeSet(version).getId());
+    tc.setTag(fixedTagname);
+    tc.execute();
+
+    PushCommand pc = new PushCommand(settings);
+    pc.execute();
+    return fixedTagname;
+  }
+
+  private String fixTagName(final String label) {
+    // according to Mercurial documentation http://hgbook.red-bean.com/hgbookch8.html#x12-1570008
+    // tag name must not contain:
+    // Colon (ASCII 58, “:”)
+    // Carriage return (ASCII 13, “\r”)
+    // Newline (ASCII 10, “\n”)
+    // all these characters will be replaced with _ (underscore)
+    return label.replace(':', '_').replace('\r', '_').replace('\n', '_');
+  }
+
+  private Settings createSettings(final VcsRoot root) {
+    return new Settings(myDefaultWorkFolderParent, root);
+  }
 }