changeset 604:3eb02fd5fd78

TW-24810
author Dmitry Neverov <dmitry.neverov@jetbrains.com>
date Thu, 06 Jun 2013 20:59:54 +0400
parents 256d3fc22a28
children 0e21f908b10d
files mercurial-common/src/jetbrains/buildServer/buildTriggers/vcs/mercurial/HgFileUtil.java mercurial-tests/src/jetbrains/buildServer/buildTriggers/vcs/mercurial/MercurialVcsSupportTest.java
diffstat 2 files changed, 62 insertions(+), 2 deletions(-) [+]
line wrap: on
line diff
--- a/mercurial-common/src/jetbrains/buildServer/buildTriggers/vcs/mercurial/HgFileUtil.java	Thu Jun 06 09:22:34 2013 +0200
+++ b/mercurial-common/src/jetbrains/buildServer/buildTriggers/vcs/mercurial/HgFileUtil.java	Thu Jun 06 20:59:54 2013 +0400
@@ -6,6 +6,7 @@
 import org.jetbrains.annotations.Nullable;
 
 import java.io.File;
+import java.io.FileFilter;
 import java.io.IOException;
 
 /**
@@ -40,8 +41,32 @@
   public static void deleteDir(@Nullable File dir, @NotNull Logger logger) {
     if (dir == null)
       return;
-    boolean dirDeleted = FileUtil.delete(dir);
-    if (!dirDeleted)
+    final String dirPath;
+    try {
+      dirPath = dir.getCanonicalPath();
+    } catch (IOException e) {
+      logger.warn("Cannot get canonical path " + dir.getAbsolutePath());
+      return;
+    }
+    FileUtil.delete(dir, new AcceptOnlyChildren(dirPath), 10);
+    if (dir.exists())
       logger.warn("Cannot delete directory " + dir.getAbsolutePath());
   }
+
+  private static class AcceptOnlyChildren implements FileFilter {
+    private final String myRootDirPath;
+
+    private AcceptOnlyChildren(@NotNull String rootDirPath) {
+      myRootDirPath = rootDirPath;
+    }
+
+    public boolean accept(File pathname) {
+      try {
+        String childFilePath = pathname.getCanonicalPath();
+        return childFilePath.startsWith(myRootDirPath);
+      } catch (IOException e) {
+        return false;
+      }
+    }
+  }
 }
--- a/mercurial-tests/src/jetbrains/buildServer/buildTriggers/vcs/mercurial/MercurialVcsSupportTest.java	Thu Jun 06 09:22:34 2013 +0200
+++ b/mercurial-tests/src/jetbrains/buildServer/buildTriggers/vcs/mercurial/MercurialVcsSupportTest.java	Thu Jun 06 20:59:54 2013 +0400
@@ -15,7 +15,9 @@
  */
 package jetbrains.buildServer.buildTriggers.vcs.mercurial;
 
+import com.intellij.openapi.util.SystemInfo;
 import jetbrains.buildServer.buildTriggers.vcs.mercurial.command.*;
+import jetbrains.buildServer.util.FileUtil;
 import jetbrains.buildServer.util.TestFor;
 import jetbrains.buildServer.vcs.*;
 import jetbrains.buildServer.vcs.impl.VcsRootImpl;
@@ -35,6 +37,7 @@
 import static jetbrains.buildServer.buildTriggers.vcs.mercurial.ModificationDataMatcher.modificationData;
 import static jetbrains.buildServer.buildTriggers.vcs.mercurial.Util.buildPatch;
 import static jetbrains.buildServer.buildTriggers.vcs.mercurial.Util.copyRepository;
+import static jetbrains.buildServer.buildTriggers.vcs.mercurial.Util.getHgPath;
 import static jetbrains.buildServer.buildTriggers.vcs.mercurial.VcsRootBuilder.vcsRoot;
 import static jetbrains.buildServer.util.Util.map;
 import static org.hamcrest.MatcherAssert.assertThat;
@@ -528,6 +531,38 @@
   }
 
 
+  @TestFor(issues = "TW-24810")
+  public void do_not_delete_symlinked_dir() throws Exception {
+    if (!SystemInfo.isUnix)
+      return;
+
+    RepoFactory repoFactory = new RepoFactory(myPluginConfig, new TestCommandSettingsFactory());
+
+    //create a file on the server
+    File dirOnTheServer = myTempFiles.createTempDir();
+    File fileOnTheServer = new File(dirOnTheServer, "file.on.server");
+    FileUtil.writeFile(fileOnTheServer, "some text");
+
+    //create a remote repository with symlink pointing to the file on the server
+    File repository = copyRepository(myTempFiles, simpleRepo());
+    ServerHgRepo repo = repoFactory.create(repository, getHgPath(), new AuthSettings());
+    repo.update().toRevision("9c6a6b4aede0").call();
+    new ProcessBuilder("ln", "-s", dirOnTheServer.getCanonicalPath()).directory(repository).start().waitFor();
+    new ProcessBuilder(getHgPath(), "add", dirOnTheServer.getName()).directory(repository).start().waitFor();
+    new ProcessBuilder(getHgPath(), "commit", "-m", "add a symlink").directory(repository).start().waitFor();
+
+    String revisionWithSymlink = repo.branches().call().get("default");
+
+    //build a clean patch on revision wich contain a symlink
+    VcsRoot root = vcsRoot().withUrl(repository.getCanonicalPath()).build();
+    buildPatch(myVcs, root, null, revisionWithSymlink, CheckoutRules.DEFAULT);
+
+    //check file & dir still exist
+    assertTrue(dirOnTheServer.exists());
+    assertTrue(fileOnTheServer.exists());
+  }
+
+
   public void hg_version_should_not_depend_on_locale() throws IOException, VcsException {
     HgRepo repo = new HgRepo(new TestCommandSettingsFactory(), new File(simpleRepo()), Util.getHgPath(), new AuthSettings(null, null));
     HgVersion defaultLocaleVersion = repo.version().call();