Skip to content

Commit cc2a31e

Browse files
Syyllinensschuberth
authored andcommitted
fix(pub): Improve support for custom package repositories
Signed-off-by: Timo Salmi <[email protected]>
1 parent c81fe19 commit cc2a31e

File tree

2 files changed

+53
-2
lines changed

2 files changed

+53
-2
lines changed

plugins/package-managers/pub/src/main/kotlin/PubCacheReader.kt

Lines changed: 20 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -84,13 +84,13 @@ internal class PubCacheReader(flutterHome: File? = null) {
8484
val path = if (type == "hosted" && url.isNotEmpty()) {
8585
// Packages with source set to "hosted" and "url" key in description set to "https://pub.dartlang.org".
8686
// The path should be resolved to "hosted/pub.dartlang.org/packageName-packageVersion".
87-
"hosted/${url.replace("https://", "")}/$packageName-$packageVersion"
87+
"hosted/${url.hostedUrlToDirectoryName()}/$packageName-$packageVersion"
8888
} else if (type == "git" && resolvedRef.isNotEmpty()) {
8989
// Packages with source set to "git" and a "resolved-ref" key in description set to a gitHash.
9090
// These packages do not define a packageName in the packageInfo, but by definition the path resolves to
9191
// the project name as given from the VcsHost and to the resolvedRef.
9292
val projectName = VcsHost.getProject(url) ?: return null
93-
if (resolvedPath.isNotEmpty()) {
93+
if (resolvedPath.isNotEmpty() && resolvedPath != ".") {
9494
"git/$projectName-$resolvedRef/$resolvedPath"
9595
} else {
9696
"git/$projectName-$resolvedRef"
@@ -106,3 +106,21 @@ internal class PubCacheReader(flutterHome: File? = null) {
106106
?: flutterPubCacheRoot?.resolve(path)?.takeIf { it.isDirectory }
107107
}
108108
}
109+
110+
// See https://github.com/dart-lang/pub/blob/ea4a1c854690d3abceb92c8cc2c6454470f9d5a7/lib/src/source/hosted.dart#L1899.
111+
private fun String.hostedUrlToDirectoryName(): String {
112+
val url = replace(schemeLocalhostRegex) { match ->
113+
// Do not include the scheme for HTTPS URLs. This makes the directory names nice for the default and most
114+
// recommended scheme. Also do not include it for localhost URLs, since they are always known to be HTTP.
115+
val localhost = if (match.groupValues.size == 3) "" else "localhost"
116+
val scheme = if (match.groupValues[1] == "https://" || localhost.isNotEmpty()) "" else match.groupValues[1]
117+
"$scheme$localhost"
118+
}
119+
120+
return url.replace(specialCharRegex) { match ->
121+
match.groupValues[0].map { char -> "%${char.code}" }.joinToString("")
122+
}
123+
}
124+
125+
private val schemeLocalhostRegex = """^(https?://)(127\.0\.0\.1|\[::1]|localhost)?""".toRegex()
126+
private val specialCharRegex = """[<>:"\\/|?*%]""".toRegex()

plugins/package-managers/pub/src/test/kotlin/PubCacheReaderTest.kt

Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -40,6 +40,9 @@ class PubCacheReaderTest : WordSpec({
4040
val gitPackageCacheDir = tmpPubCacheDir.resolve("git/$PACKAGE_NAME-$RESOLVED_REF")
4141
val gitPackageWithPathCacheDir = tmpPubCacheDir.resolve("git/$PACKAGE_NAME-$RESOLVED_REF/$PACKAGE_NAME")
4242
val hostedPackageCacheDir = tmpPubCacheDir.resolve("hosted/oss-review-toolkit.org/$PACKAGE_NAME-$PACKAGE_VERSION")
43+
val customPackageCacheDir = tmpPubCacheDir.resolve(
44+
"hosted/oss-review-toolkit.org%47api%47pub%47repository%47/$PACKAGE_NAME-$PACKAGE_VERSION"
45+
)
4346
val localPackagePathAbsolute = ABSOLUTE_PATH
4447
val localPackagePathRelative = ABSOLUTE_PATH.resolve(RELATIVE_PATH)
4548

@@ -49,6 +52,7 @@ class PubCacheReaderTest : WordSpec({
4952
gitPackageCacheDir.safeMkdirs()
5053
gitPackageWithPathCacheDir.safeMkdirs()
5154
hostedPackageCacheDir.safeMkdirs()
55+
customPackageCacheDir.safeMkdirs()
5256
}
5357

5458
"findProjectRoot()" should {
@@ -81,6 +85,21 @@ class PubCacheReaderTest : WordSpec({
8185
reader.findProjectRoot(packageInfo, ABSOLUTE_PATH) shouldBe gitPackageWithPathCacheDir
8286
}
8387

88+
"resolve the path of a Git dependency with special path" {
89+
val packageInfo = PackageInfo(
90+
dependency = "direct main",
91+
description = PackageInfo.Description(
92+
path = ".",
93+
resolvedRef = RESOLVED_REF,
94+
url = "https://github.com/oss-review-toolkit/$PACKAGE_NAME.git"
95+
),
96+
source = "git",
97+
version = "9.9.9"
98+
)
99+
100+
reader.findProjectRoot(packageInfo, ABSOLUTE_PATH) shouldBe gitPackageCacheDir
101+
}
102+
84103
"resolve the path of a hosted dependency" {
85104
val packageInfo = PackageInfo(
86105
dependency = "transitive",
@@ -95,6 +114,20 @@ class PubCacheReaderTest : WordSpec({
95114
reader.findProjectRoot(packageInfo, ABSOLUTE_PATH) shouldBe hostedPackageCacheDir
96115
}
97116

117+
"resolve the path of a custom package repository dependency" {
118+
val packageInfo = PackageInfo(
119+
dependency = "transitive",
120+
description = PackageInfo.Description(
121+
name = PACKAGE_NAME,
122+
url = "https://oss-review-toolkit.org/api/pub/repository/"
123+
),
124+
source = "hosted",
125+
version = PACKAGE_VERSION
126+
)
127+
128+
reader.findProjectRoot(packageInfo, ABSOLUTE_PATH) shouldBe customPackageCacheDir
129+
}
130+
98131
"resolve the relative path of a local dependency" {
99132
val packageInfo = PackageInfo(
100133
dependency = "transitive",

0 commit comments

Comments
 (0)