diff options
Diffstat (limited to 'libs/utils')
| -rw-r--r-- | libs/utils/src/main/java/org/the_jk/cleversync/PathUtils.kt | 27 | ||||
| -rw-r--r-- | libs/utils/src/test/java/org/the_jk/cleversync/PathUtilsTest.kt | 11 |
2 files changed, 38 insertions, 0 deletions
diff --git a/libs/utils/src/main/java/org/the_jk/cleversync/PathUtils.kt b/libs/utils/src/main/java/org/the_jk/cleversync/PathUtils.kt index 4202b24..77037cd 100644 --- a/libs/utils/src/main/java/org/the_jk/cleversync/PathUtils.kt +++ b/libs/utils/src/main/java/org/the_jk/cleversync/PathUtils.kt @@ -1,5 +1,7 @@ package org.the_jk.cleversync +import kotlin.math.min + object PathUtils { fun dirname(path: String): String { if (path.isEmpty()) return "." @@ -46,4 +48,29 @@ object PathUtils { } return parts.joinToString("/", prefix = if (prefixed) "/" else "") } + + // Return path relative to base. Returns path as-is if either path is not + // absolute. + fun relativeTo(base: String, path: String): String { + if (!base.startsWith('/') || !path.startsWith('/')) return path + val baseParts = base.split('/').filter { part -> + part.isNotEmpty() && part != "." + } + val pathParts = path.split('/').filter { part -> + part.isNotEmpty() && part != "." + } + var i = 0 + while (i < min(baseParts.size, pathParts.size)) { + if (baseParts[i] != pathParts[i]) break + i++ + } + if (i == baseParts.size) { + if (i == pathParts.size) return "." + return pathParts.subList(i, pathParts.size).joinToString("/") + } + return buildList { + repeat(baseParts.size - i) { add("..") } + addAll(pathParts.subList(i, pathParts.size)) + }.joinToString("/") + } } diff --git a/libs/utils/src/test/java/org/the_jk/cleversync/PathUtilsTest.kt b/libs/utils/src/test/java/org/the_jk/cleversync/PathUtilsTest.kt index eb1d63f..1d411ea 100644 --- a/libs/utils/src/test/java/org/the_jk/cleversync/PathUtilsTest.kt +++ b/libs/utils/src/test/java/org/the_jk/cleversync/PathUtilsTest.kt @@ -55,4 +55,15 @@ class PathUtilsTest { assertThat(PathUtils.resolve("foo/../../../bar/")).isEqualTo("bar") assertThat(PathUtils.resolve("/foo/../../../bar/")).isEqualTo("/bar") } + + @Test + fun relativeTo() { + assertThat(PathUtils.relativeTo("", "")).isEmpty() + assertThat(PathUtils.relativeTo("/", "/")).isEqualTo(".") + assertThat(PathUtils.relativeTo("/", "/foo")).isEqualTo("foo") + assertThat(PathUtils.relativeTo("/", "/foo/bar/")).isEqualTo("foo/bar") + assertThat(PathUtils.relativeTo("/foo", "/foo/bar/")).isEqualTo("bar") + assertThat(PathUtils.relativeTo("/foo", "/bar")).isEqualTo("../bar") + assertThat(PathUtils.relativeTo("/foo/bar", "/fum/bar")).isEqualTo("../../fum/bar") + } } |
