changeset 339:b799355b4016

Merge branch Eluru-6.5.x
author Dmitry Neverov <dmitry.neverov@jetbrains.com>
date Fri, 02 Dec 2011 15:35:00 +0300
parents ae189ede9756 (current diff) d31d7c81b637 (diff)
children abfaa81ee52b
files mercurial-common/src/jetbrains/buildServer/buildTriggers/vcs/mercurial/command/BaseCommand.java mercurial-common/src/jetbrains/buildServer/buildTriggers/vcs/mercurial/command/CatCommand.java mercurial-common/src/jetbrains/buildServer/buildTriggers/vcs/mercurial/command/CommandUtil.java mercurial-server/src/jetbrains/buildServer/buildTriggers/vcs/mercurial/MercurialVcsSupport.java mercurial-tests/src/jetbrains/buildServer/buildTriggers/vcs/mercurial/MercurialVcsSupportTest.java
diffstat 9 files changed, 116 insertions(+), 24 deletions(-) [+]
line wrap: on
line diff
--- a/mercurial-common/src/jetbrains/buildServer/buildTriggers/vcs/mercurial/command/BaseCommand.java	Thu Dec 01 14:51:35 2011 +0300
+++ b/mercurial-common/src/jetbrains/buildServer/buildTriggers/vcs/mercurial/command/BaseCommand.java	Fri Dec 02 15:35:00 2011 +0300
@@ -72,9 +72,9 @@
   }
 
   /**
-   * Since mercurial 1.7 on Windows the only file inside '<mercurial_install_dir>/bin' is 'hg.cmd' 
-   * which run hg.exe placed in the parent dir. GeneralCommandLine will not find hg.cmd, in the 
-   * case when $PATH contains <mercurial_install_dir>/bin and doesn't contain <mercurial_install_dir> 
+   * Since mercurial 1.7 on Windows the only file inside '<mercurial_install_dir>/bin' is 'hg.cmd'
+   * which run hg.exe placed in the parent dir. GeneralCommandLine will not find hg.cmd, in the
+   * case when $PATH contains <mercurial_install_dir>/bin and doesn't contain <mercurial_install_dir>
    * and hg executable is set to 'hg'. To fix it - run hg using windows shell which expand
    * hg to hg.cmd correctly.
    * @param cli command line in which to setup hg executable
--- a/mercurial-common/src/jetbrains/buildServer/buildTriggers/vcs/mercurial/command/CommandUtil.java	Thu Dec 01 14:51:35 2011 +0300
+++ b/mercurial-common/src/jetbrains/buildServer/buildTriggers/vcs/mercurial/command/CommandUtil.java	Fri Dec 02 15:35:00 2011 +0300
@@ -31,9 +31,8 @@
   private static final int DEFAULT_COMMAND_TIMEOUT_SEC = 3600;
 
   public static void checkCommandFailed(@NotNull String cmdName, @NotNull ExecResult res) throws VcsException {
-    if (res.getExitCode() != 0 || res.getException() != null) {
+    if (res.getExitCode() != 0 || res.getException() != null)
       commandFailed(cmdName, res);
-    }
     if (res.getStderr().length() > 0) {
       Loggers.VCS.warn("Error output produced by: " + cmdName);
       Loggers.VCS.warn(res.getStderr());
@@ -41,18 +40,21 @@
   }
 
   public static void commandFailed(final String cmdName, final ExecResult res) throws VcsException {
+    final String message = createCommandLogMessage(cmdName, res);
+    Loggers.VCS.warn(message);
+    if (hasImportantException(res))
+      Loggers.VCS.error("Error during executing '" + cmdName + "'", res.getException());
+    throw new VcsException(message);
+  }
+
+  private static String createCommandLogMessage(final String cmdName, final ExecResult res) {
     String stderr = res.getStderr();
     String stdout = res.getStdout();
     String exceptionMessage = getExceptionMessage(res);
-    final String message = "'" + cmdName + "' command failed.\n" +
+    return "'" + cmdName + "' command failed.\n" +
             (!StringUtil.isEmpty(stdout) ? "stdout: " + stdout + "\n" : "") +
             (!StringUtil.isEmpty(stderr) ? "stderr: " + stderr + "\n" : "") +
             (exceptionMessage != null ? "exception: " + exceptionMessage : "");
-    Loggers.VCS.warn(message);
-    if (hasImportantException(res)) {
-      Loggers.VCS.error("Error during executing '" + cmdName + "'", res.getException());
-    }
-    throw new VcsException(message);
   }
 
   @Nullable
--- a/mercurial-server/src/jetbrains/buildServer/buildTriggers/vcs/mercurial/MercurialVcsSupport.java	Thu Dec 01 14:51:35 2011 +0300
+++ b/mercurial-server/src/jetbrains/buildServer/buildTriggers/vcs/mercurial/MercurialVcsSupport.java	Fri Dec 02 15:35:00 2011 +0300
@@ -33,6 +33,7 @@
 import org.jetbrains.annotations.Nullable;
 
 import java.io.File;
+import java.io.FileFilter;
 import java.io.FileInputStream;
 import java.io.IOException;
 import java.util.*;
@@ -41,6 +42,8 @@
 import java.util.concurrent.locks.Lock;
 import java.util.concurrent.locks.ReentrantLock;
 
+import static com.intellij.openapi.util.text.StringUtil.isEmptyOrSpaces;
+
 /**
  * Mercurial VCS plugin for TeamCity works as follows:
  * <ul>
@@ -61,6 +64,8 @@
   private final ServerPluginConfig myConfig;
   private final HgPathProvider myHgPathProvider;
   private final CommandFactory myCommandFactory;
+  private final FileFilter myIgnoreDotHgFilter = new IgnoreDotHgFilter();
+  private final FileFilter myAcceptAllFilter = new AcceptAllFilter();
 
   public MercurialVcsSupport(@NotNull final VcsManager vcsManager,
                              @NotNull final SBuildServer server,
@@ -350,22 +355,73 @@
     File tempDir = FileUtil.createTempDirectory("mercurial", toVer.getId());
     try {
       File mirrorDir = getWorkingDir(settings);
-      ArchiveCommand archive = new ArchiveCommand(settings, mirrorDir);
-      archive.setDestDir(tempDir);
-      archive.setToId(toVer.getId());
-      archive.execute();
-      buildPatchFromDirectory(builder, tempDir, checkoutRules);
+      if (hasSubrepositories(settings, toVer)) {
+        Loggers.VCS.debug("Repository '" + settings.getRepository() + "' has submodules at revision " + toVer.getId() + ", use 'hg clone' to build clean patch");
+        CloneCommand cl = new CloneCommand(settings, tempDir);
+        cl.setRepository(mirrorDir.getAbsolutePath());
+        cl.setToId(toVer.getId());
+        cl.setUpdateWorkingDir(false);
+        cl.setUsePullProtocol(myConfig.isUsePullProtocol());
+        cl.execute();
+
+        UpdateCommand up = new UpdateCommand(settings, tempDir);
+        up.setToId(toVer.getId());
+        up.execute();
+
+        buildPatchFromDirectory(builder, tempDir, checkoutRules, myIgnoreDotHgFilter);
+      } else {
+        Loggers.VCS.debug("Repository '" + settings.getRepository() + "' doesn't have submodules at revision " + toVer.getId() + ", use 'hg archive' to build clean patch");
+        ArchiveCommand archive = new ArchiveCommand(settings, mirrorDir);
+        archive.setDestDir(tempDir);
+        archive.setToId(toVer.getId());
+        archive.execute();
+        buildPatchFromDirectory(builder, tempDir, checkoutRules, myAcceptAllFilter);
+      }
     } finally {
       FileUtil.delete(tempDir);
     }
   }
 
-  private void buildPatchFromDirectory(final PatchBuilder builder, final File repRoot, final CheckoutRules checkoutRules) throws IOException {
-    buildPatchFromDirectory(repRoot, builder, repRoot, checkoutRules);
+  private boolean hasSubrepositories(@NotNull final Settings settings, @NotNull final ChangeSet cset) throws VcsException {
+    String hgsub = getFileContent(".hgsub", settings, cset);
+    return !isEmptyOrSpaces(hgsub);
   }
 
-  private void buildPatchFromDirectory(File curDir, final PatchBuilder builder, final File repRoot, final CheckoutRules checkoutRules) throws IOException {
-    File[] files = curDir.listFiles();
+  /**
+   * Returns file's content or empty string if it doesn't exist.
+   * @param path path of the file of interest
+   * @param settings root settings
+   * @param cset repository cset (should be present in the repository)
+   * @return see above
+   */
+  @NotNull
+  private String getFileContent(@NotNull final String path, @NotNull final Settings settings, @NotNull final ChangeSet cset) throws VcsException {
+    File dir = getWorkingDir(settings);
+    CatCommand cat = new CatCommand(settings, dir);
+    cat.setRevId(cset.getId());
+    File parentDir = null;
+    try {
+      parentDir = cat.execute(Collections.singletonList(path), false);
+      File f = new File(parentDir, path);
+      if (f.isFile())
+        return FileUtil.readText(f);
+      else
+        return "";
+    } catch (Exception e) {
+      return "";
+    } finally {
+      if (parentDir != null)
+        deleteTmpDir(parentDir);
+    }
+  }
+
+
+  private void buildPatchFromDirectory(final PatchBuilder builder, final File repRoot, final CheckoutRules checkoutRules, @NotNull final FileFilter filter) throws IOException {
+    buildPatchFromDirectory(repRoot, builder, repRoot, checkoutRules, filter);
+  }
+
+  private void buildPatchFromDirectory(File curDir, final PatchBuilder builder, final File repRoot, final CheckoutRules checkoutRules, @NotNull final FileFilter filter) throws IOException {
+    File[] files = curDir.listFiles(filter);
     if (files != null) {
       for (File realFile: files) {
         String relPath = realFile.getAbsolutePath().substring(repRoot.getAbsolutePath().length());
@@ -374,7 +430,7 @@
           final File virtualFile = new File(mappedPath);
           if (realFile.isDirectory()) {
             builder.createDirectory(virtualFile);
-            buildPatchFromDirectory(realFile, builder, repRoot, checkoutRules);
+            buildPatchFromDirectory(realFile, builder, repRoot, checkoutRules, filter);
           } else {
             final FileInputStream is = new FileInputStream(realFile);
             try {
@@ -385,7 +441,7 @@
           }
         } else {
           if (realFile.isDirectory()) {
-            buildPatchFromDirectory(realFile, builder, repRoot, checkoutRules);
+            buildPatchFromDirectory(realFile, builder, repRoot, checkoutRules, filter);
           }
         }
       }
@@ -782,4 +838,16 @@
   public boolean isDAGBasedVcs() {
     return true;
   }
+
+  private static class IgnoreDotHgFilter implements FileFilter {
+    public boolean accept(final File file) {
+      return !(file.isDirectory() && ".hg".equals(file.getName()));
+    }
+  }
+
+  private static class AcceptAllFilter implements FileFilter {
+    public boolean accept(File pathname) {
+      return true;
+    }
+  }
 }
--- a/mercurial-tests/src/jetbrains/buildServer/buildTriggers/vcs/mercurial/MercurialVcsSupportTest.java	Thu Dec 01 14:51:35 2011 +0300
+++ b/mercurial-tests/src/jetbrains/buildServer/buildTriggers/vcs/mercurial/MercurialVcsSupportTest.java	Fri Dec 02 15:35:00 2011 +0300
@@ -34,6 +34,9 @@
 import java.io.IOException;
 import java.util.*;
 
+import static com.intellij.openapi.util.io.FileUtil.copyDir;
+import static com.intellij.openapi.util.io.FileUtil.moveDirWithContent;
+
 @Test
 public class MercurialVcsSupportTest extends BaseMercurialTestCase {
 
@@ -127,7 +130,7 @@
     builder.close();
     return output;
   }
-  
+
   @Test
   public void test_build_patch() throws IOException, VcsException {
     setName("cleanPatch1");
@@ -181,6 +184,20 @@
     checkPatchResult(output.toByteArray());
   }
 
+  public void test_clean_patch_with_subrepositories() throws Exception {
+    File r1 = new File(myPluginConfig.getCachesDir(), "r1");
+    File r3 = new File(myPluginConfig.getCachesDir(), "r3");
+    copyDir(new File("mercurial-tests/testData/subrepos/r1"), r1);
+    copyDir(new File("mercurial-tests/testData/subrepos/r3"), r3);
+    moveDirWithContent(new File(r1, "hg"), new File(r1, ".hg"));
+    moveDirWithContent(new File(r3, "hg"), new File(r3, ".hg"));
+
+    VcsRootImpl root = createVcsRoot(r1.getAbsolutePath());
+
+    setName("clean_patch_with_subrepositories");
+    checkPatchResult(buildPatch(root, null, "3:d350e7209906", CheckoutRules.DEFAULT).toByteArray());
+  }
+
   public void test_get_content() throws IOException, VcsException {
     VcsRootImpl vcsRoot = createVcsRoot(simpleRepo());
 
@@ -488,4 +505,4 @@
     assertTrue(myVcs.getCollectChangesPolicy() instanceof CollectChangesByCheckoutRules);
   }
 }
- 
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/mercurial-tests/testData/clean_patch_with_subrepositories/after/.hgsub	Fri Dec 02 15:35:00 2011 +0300
@@ -0,0 +1,1 @@
+r2 = ../r3
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/mercurial-tests/testData/clean_patch_with_subrepositories/after/.hgsubstate	Fri Dec 02 15:35:00 2011 +0300
@@ -0,0 +1,1 @@
+9e4a2fef1a1c04623a0d89edb4f3ba290cf2666e r2
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/mercurial-tests/testData/clean_patch_with_subrepositories/after/a	Fri Dec 02 15:35:00 2011 +0300
@@ -0,0 +1,1 @@
+a
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/mercurial-tests/testData/clean_patch_with_subrepositories/after/r2/c	Fri Dec 02 15:35:00 2011 +0300
@@ -0,0 +1,1 @@
+c
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/mercurial-tests/testData/clean_patch_with_subrepositories/before/a	Fri Dec 02 15:35:00 2011 +0300
@@ -0,0 +1,1 @@
+a