From c0000df5082e98bb40a2ea017d456aa13e6b0a78 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ren=C3=A9=20Pfeuffer?= Date: Fri, 23 Nov 2018 11:59:12 +0100 Subject: [PATCH] Use "real paths" instead of absolute paths See issue #82 for details: https://bitbucket.org/sdorra/scm-manager/issues/82/symbolic-link-in-hg-repository-path --- .../scm/repository/xml/XmlRepositoryDAO.java | 23 ++++++++++++----- .../repository/xml/XmlRepositoryDAOTest.java | 25 ++++++++++++++++--- .../sonia/scm/web/HgHookCallbackServlet.java | 4 --- 3 files changed, 39 insertions(+), 13 deletions(-) diff --git a/scm-dao-xml/src/main/java/sonia/scm/repository/xml/XmlRepositoryDAO.java b/scm-dao-xml/src/main/java/sonia/scm/repository/xml/XmlRepositoryDAO.java index 4496e233bd..079399fec4 100644 --- a/scm-dao-xml/src/main/java/sonia/scm/repository/xml/XmlRepositoryDAO.java +++ b/scm-dao-xml/src/main/java/sonia/scm/repository/xml/XmlRepositoryDAO.java @@ -45,8 +45,8 @@ import sonia.scm.store.ConfigurationStoreFactory; import sonia.scm.xml.AbstractXmlDAO; import java.io.File; +import java.io.IOException; import java.nio.file.Path; -import java.nio.file.Paths; import java.util.Collection; import java.util.Optional; @@ -158,11 +158,22 @@ public class XmlRepositoryDAO @Override public String getIdForDirectory(File path) { - return db.getPaths().stream() - .filter(p -> path.toPath().startsWith(context.getBaseDirectory().toPath().resolve(p.getPath()).toAbsolutePath())) - .map(RepositoryPath::getId) - .findAny() - .orElseThrow(() -> new RuntimeException("could not find repository for directory: " + path)); + for (RepositoryPath p : db.getPaths()) { + if (toRealPath(path.toPath()).startsWith(toRealPath(context.getBaseDirectory().toPath().resolve(p.getPath())))) { + return p.getId(); + } + } + throw new RuntimeException("could not find repository for directory: " + path); + } + + private Path toRealPath(Path path) { + try { + // resolve links and other indirections + // (see issue #82, https://bitbucket.org/sdorra/scm-manager/issues/82/symbolic-link-in-hg-repository-path) + return path.toRealPath(); + } catch (IOException e) { + throw new RuntimeException("could not get Path$toRealPath for path: " + path); + } } private Optional findExistingRepositoryPath(Repository repository) { diff --git a/scm-dao-xml/src/test/java/sonia/scm/repository/xml/XmlRepositoryDAOTest.java b/scm-dao-xml/src/test/java/sonia/scm/repository/xml/XmlRepositoryDAOTest.java index dfefc026ca..315aae8187 100644 --- a/scm-dao-xml/src/test/java/sonia/scm/repository/xml/XmlRepositoryDAOTest.java +++ b/scm-dao-xml/src/test/java/sonia/scm/repository/xml/XmlRepositoryDAOTest.java @@ -15,6 +15,7 @@ import sonia.scm.store.ConfigurationStoreFactory; import java.io.File; import java.io.IOException; +import java.nio.file.Files; import java.nio.file.Path; import static java.util.Collections.emptyList; @@ -118,6 +119,7 @@ public class XmlRepositoryDAOTest { @Test public void shouldFindRepositoryForRelativePath() { + new File(context.getBaseDirectory(), "relative/path/data").mkdirs(); Repository existingRepository = new Repository("id", "old", null, null); RepositoryPath repositoryPath = new RepositoryPath("relative/path", "id", existingRepository); when(db.getPaths()).thenReturn(asList(repositoryPath)); @@ -130,14 +132,31 @@ public class XmlRepositoryDAOTest { } @Test - public void shouldFindRepositoryForAbsolutePath() { + public void shouldFindRepositoryForAbsolutePath() throws IOException { Repository existingRepository = new Repository("id", "old", null, null); - RepositoryPath repositoryPath = new RepositoryPath("/tmp/somewhere/else", "id", existingRepository); + File folder = temporaryFolder.newFolder("somewhere", "data"); + RepositoryPath repositoryPath = new RepositoryPath(folder.getParent(), "id", existingRepository); when(db.getPaths()).thenReturn(asList(repositoryPath)); XmlRepositoryDAO dao = new XmlRepositoryDAO(storeFactory, new InitialRepositoryLocationResolver(context), context); - String id = dao.getIdForDirectory(new File("/tmp/somewhere/else/data")); + String id = dao.getIdForDirectory(folder); + + assertThat(id).isEqualTo("id"); + } + + @Test + public void shouldFindRepositoryForLinks() throws IOException { + Repository existingRepository = new Repository("id", "old", null, null); + File folder = temporaryFolder.newFolder("somewhere", "else", "data"); + File link = new File(folder.getParentFile().getParentFile(), "link"); + Files.createSymbolicLink(link.toPath(), folder.getParentFile().toPath()); + RepositoryPath repositoryPath = new RepositoryPath(new File(link, "data").getPath(), "id", existingRepository); + when(db.getPaths()).thenReturn(asList(repositoryPath)); + + XmlRepositoryDAO dao = new XmlRepositoryDAO(storeFactory, new InitialRepositoryLocationResolver(context), context); + + String id = dao.getIdForDirectory(folder); assertThat(id).isEqualTo("id"); } diff --git a/scm-plugins/scm-hg-plugin/src/main/java/sonia/scm/web/HgHookCallbackServlet.java b/scm-plugins/scm-hg-plugin/src/main/java/sonia/scm/web/HgHookCallbackServlet.java index b00c8f0496..0bb0d155a5 100644 --- a/scm-plugins/scm-hg-plugin/src/main/java/sonia/scm/web/HgHookCallbackServlet.java +++ b/scm-plugins/scm-hg-plugin/src/main/java/sonia/scm/web/HgHookCallbackServlet.java @@ -455,10 +455,6 @@ public class HgHookCallbackServlet extends HttpServlet String path = request.getParameter(PARAM_REPOSITORYPATH); if (Util.isNotEmpty(path)) { - /* - * use canonical path to fix symbolic links - * https://bitbucket.org/sdorra/scm-manager/issue/82/symbolic-link-in-hg-repository-path - */ id = repositoryDAO.getIdForDirectory(new File(path)); } else if (logger.isWarnEnabled())