# HG changeset patch # User Dmitry Neverov # Date 1370537994 -14400 # Node ID 3eb02fd5fd788441eedfbca32397ec17d16fa490 # Parent 256d3fc22a286e1b1d77170ac35595860631113a TW-24810 diff -r 256d3fc22a28 -r 3eb02fd5fd78 mercurial-common/src/jetbrains/buildServer/buildTriggers/vcs/mercurial/HgFileUtil.java --- 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; + } + } + } } diff -r 256d3fc22a28 -r 3eb02fd5fd78 mercurial-tests/src/jetbrains/buildServer/buildTriggers/vcs/mercurial/MercurialVcsSupportTest.java --- 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();