Skip to content

Commit c9e3285

Browse files
ilgonmicSpace Team
authored and
Space Team
committed
[Gradle,JS]make downloadBaseUrl nullable to work with FAIL_ON_PROJECT_REPOS
^KT-56300 fixed ^KT-55620 fixed
1 parent f4d18da commit c9e3285

File tree

16 files changed

+414
-266
lines changed

16 files changed

+414
-266
lines changed

libraries/tools/kotlin-gradle-plugin-integration-tests/src/test/kotlin/org/jetbrains/kotlin/gradle/Kotlin2JsGradlePluginIT.kt

+71
Original file line numberDiff line numberDiff line change
@@ -1782,4 +1782,75 @@ class Kotlin2JsIrGradlePluginIT : KGPBaseTest() {
17821782
}
17831783
}
17841784
}
1785+
1786+
@DisplayName("test FAIL_ON_PROJECT_REPOS using custom repository")
1787+
@GradleTest
1788+
fun testFailOnProjectReposUsingCustomRepo(gradleVersion: GradleVersion) {
1789+
project("js-project-repos", gradleVersion) {
1790+
settingsGradleKts.modify {
1791+
it + """
1792+
1793+
dependencyResolutionManagement {
1794+
repositories {
1795+
ivy {
1796+
name = "Node.JS dist"
1797+
url = URI("https://nodejs.org/dist")
1798+
patternLayout {
1799+
artifact("v[revision]/[artifact](-v[revision]-[classifier]).[ext]")
1800+
}
1801+
metadataSources {
1802+
artifact()
1803+
}
1804+
content {
1805+
includeModule("org.nodejs", "node")
1806+
}
1807+
}
1808+
ivy {
1809+
name = "Yarn dist"
1810+
url = URI("https://github.com/yarnpkg/yarn/releases/download")
1811+
patternLayout {
1812+
artifact("v[revision]/[artifact](-v[revision]).[ext]")
1813+
}
1814+
metadataSources {
1815+
artifact()
1816+
}
1817+
content {
1818+
includeModule("com.yarnpkg", "yarn")
1819+
}
1820+
}
1821+
}
1822+
}
1823+
""".trimIndent()
1824+
}
1825+
1826+
build("kotlinNodeJsSetup", "kotlinYarnSetup") {
1827+
assertTasksExecuted(":kotlinNodeJsSetup")
1828+
assertTasksExecuted(":kotlinYarnSetup")
1829+
}
1830+
}
1831+
}
1832+
1833+
@DisplayName("test FAIL_ON_PROJECT_REPOS no download")
1834+
@GradleTest
1835+
fun testFailOnProjectReposNoDownload(gradleVersion: GradleVersion) {
1836+
project("js-project-repos", gradleVersion) {
1837+
buildGradleKts.modify {
1838+
it + """
1839+
1840+
rootProject.plugins.withType<org.jetbrains.kotlin.gradle.targets.js.nodejs.NodeJsRootPlugin> {
1841+
rootProject.the<org.jetbrains.kotlin.gradle.targets.js.nodejs.NodeJsRootExtension>().download = false
1842+
}
1843+
1844+
rootProject.plugins.withType<org.jetbrains.kotlin.gradle.targets.js.yarn.YarnPlugin> {
1845+
rootProject.the<org.jetbrains.kotlin.gradle.targets.js.yarn.YarnRootExtension>().download = false
1846+
}
1847+
""".trimIndent()
1848+
}
1849+
1850+
build("kotlinNodeJsSetup", "kotlinYarnSetup") {
1851+
assertTasksSkipped(":kotlinNodeJsSetup")
1852+
assertTasksSkipped(":kotlinYarnSetup")
1853+
}
1854+
}
1855+
}
17851856
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
plugins {
2+
kotlin("js")
3+
}
4+
5+
kotlin {
6+
js(IR) {
7+
binaries.executable()
8+
nodejs {
9+
}
10+
}
11+
}
12+
13+
rootProject.plugins.withType<org.jetbrains.kotlin.gradle.targets.js.nodejs.NodeJsRootPlugin> {
14+
rootProject.the<org.jetbrains.kotlin.gradle.targets.js.nodejs.NodeJsRootExtension>().downloadBaseUrl = null
15+
}
16+
17+
rootProject.plugins.withType<org.jetbrains.kotlin.gradle.targets.js.yarn.YarnPlugin> {
18+
rootProject.the<org.jetbrains.kotlin.gradle.targets.js.yarn.YarnRootExtension>().downloadBaseUrl = null
19+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
import java.net.URI
2+
3+
dependencyResolutionManagement {
4+
repositories {
5+
repositoriesMode.set(RepositoriesMode.FAIL_ON_PROJECT_REPOS)
6+
}
7+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
/*
2+
* Copyright 2010-2022 JetBrains s.r.o. and Kotlin Programming Language contributors.
3+
* Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file.
4+
*/
5+
6+
package example
7+
8+
@JsExport
9+
class Child {
10+
val name: String = "Child"
11+
}
12+
13+
fun main() {
14+
println("Hello there!")
15+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
package org.jetbrains.kotlin.gradle.targets.js
2+
3+
import java.io.File
4+
5+
interface AbstractEnv {
6+
7+
val download: Boolean
8+
9+
val downloadBaseUrl: String?
10+
11+
val ivyDependency: String
12+
13+
val dir: File
14+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
package org.jetbrains.kotlin.gradle.targets.js
2+
3+
import org.gradle.work.DisableCachingByDefault
4+
import org.jetbrains.kotlin.gradle.internal.ConfigurationPhaseAware
5+
import java.io.File
6+
7+
abstract class AbstractSettings<Env : AbstractEnv> : ConfigurationPhaseAware<Env>() {
8+
9+
abstract var download: Boolean
10+
11+
abstract var downloadBaseUrl: String?
12+
13+
abstract var installationDir: File
14+
15+
abstract var version: String
16+
17+
abstract var command: String
18+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,165 @@
1+
package org.jetbrains.kotlin.gradle.targets.js
2+
3+
import org.gradle.api.DefaultTask
4+
import org.gradle.api.artifacts.Configuration
5+
import org.gradle.api.file.ArchiveOperations
6+
import org.gradle.api.file.FileSystemOperations
7+
import org.gradle.api.model.ObjectFactory
8+
import org.gradle.api.provider.Provider
9+
import org.gradle.api.tasks.*
10+
import org.gradle.internal.hash.FileHasher
11+
import org.gradle.work.DisableCachingByDefault
12+
import org.jetbrains.kotlin.gradle.logging.kotlinInfo
13+
import org.jetbrains.kotlin.gradle.plugin.statistics.KotlinBuildStatsService
14+
import org.jetbrains.kotlin.statistics.metrics.NumericalMetrics
15+
import java.io.File
16+
import java.net.URI
17+
import javax.inject.Inject
18+
19+
@DisableCachingByDefault
20+
abstract class AbstractSetupTask<Env : AbstractEnv, Settings : AbstractSettings<Env>> : DefaultTask() {
21+
@get:Internal
22+
protected abstract val settings: Settings
23+
24+
@get:Internal
25+
protected abstract val artifactPattern: String
26+
27+
@get:Internal
28+
protected abstract val artifactModule: String
29+
30+
@get:Internal
31+
protected abstract val artifactName: String
32+
33+
@get:Internal
34+
protected val env: Env by lazy { settings.requireConfigured() }
35+
36+
private val shouldDownload by lazy {
37+
env.download
38+
}
39+
40+
@get:Inject
41+
internal abstract val archiveOperations: ArchiveOperations
42+
43+
@get:Inject
44+
internal abstract val fileHasher: FileHasher
45+
46+
@get:Inject
47+
internal abstract val objects: ObjectFactory
48+
49+
@get:Inject
50+
internal abstract val fs: FileSystemOperations
51+
52+
val ivyDependency: String
53+
@Input get() = env.ivyDependency
54+
55+
val downloadBaseUrl: String?
56+
@Input
57+
@Optional
58+
get() = env.downloadBaseUrl
59+
60+
val destination: File
61+
@OutputDirectory get() = env.dir
62+
63+
val destinationHashFile: File
64+
@OutputFile get() = destination.parentFile.resolve("${destination.name}.hash")
65+
66+
@Transient
67+
@get:Internal
68+
internal var configuration: Provider<Configuration>? = null
69+
70+
@get:Classpath
71+
@get:Optional
72+
val dist: File? by lazy {
73+
if (!shouldDownload) return@lazy null
74+
75+
withUrlRepo {
76+
val startDownloadTime = System.currentTimeMillis()
77+
configuration!!.get().files.single().also {
78+
val downloadDuration = System.currentTimeMillis() - startDownloadTime
79+
if (downloadDuration > 0) {
80+
KotlinBuildStatsService.getInstance()
81+
?.report(NumericalMetrics.ARTIFACTS_DOWNLOAD_SPEED, it.length() * 1000 / downloadDuration)
82+
}
83+
}
84+
}
85+
}
86+
87+
init {
88+
onlyIf {
89+
shouldDownload
90+
}
91+
}
92+
93+
@Suppress("unused")
94+
@TaskAction
95+
fun exec() {
96+
if (!shouldDownload) return
97+
98+
logger.kotlinInfo("Using distribution from '$dist'")
99+
100+
extractWithUpToDate(
101+
destination,
102+
destinationHashFile,
103+
dist!!,
104+
fileHasher,
105+
::extract
106+
)
107+
}
108+
109+
private fun <T> withUrlRepo(action: () -> T): T {
110+
val repo = downloadBaseUrl?.let {
111+
project.repositories.ivy { repo ->
112+
repo.name = "Distributions at ${it}"
113+
repo.url = URI(it)
114+
115+
repo.patternLayout {
116+
it.artifact(artifactPattern)
117+
}
118+
repo.metadataSources { it.artifact() }
119+
repo.content { it.includeModule(artifactModule, artifactName) }
120+
}
121+
}
122+
123+
return action().also {
124+
repo?.let { project.repositories.remove(it) }
125+
}
126+
}
127+
128+
private fun extractWithUpToDate(
129+
destination: File,
130+
destinationHashFile: File,
131+
dist: File,
132+
fileHasher: FileHasher,
133+
extract: (File, File) -> Unit,
134+
) {
135+
var distHash: String? = null
136+
val upToDate = destinationHashFile.let { file ->
137+
if (file.exists()) {
138+
file.useLines { seq ->
139+
val list = seq.first().split(" ")
140+
list.size == 2 &&
141+
list[0] == fileHasher.calculateDirHash(destination) &&
142+
list[1] == fileHasher.hash(dist).toByteArray().toHex().also { distHash = it }
143+
}
144+
} else false
145+
}
146+
147+
if (upToDate) {
148+
return
149+
}
150+
151+
if (destination.isDirectory) {
152+
destination.deleteRecursively()
153+
}
154+
155+
extract(dist, destination.parentFile)
156+
157+
destinationHashFile.writeText(
158+
fileHasher.calculateDirHash(destination)!! +
159+
" " +
160+
(distHash ?: fileHasher.hash(dist).toByteArray().toHex())
161+
)
162+
}
163+
164+
abstract fun extract(archive: File, destination: File)
165+
}
Original file line numberDiff line numberDiff line change
@@ -1,23 +1,24 @@
11
package org.jetbrains.kotlin.gradle.targets.js.nodejs
22

3+
import org.jetbrains.kotlin.gradle.targets.js.AbstractEnv
34
import org.jetbrains.kotlin.gradle.targets.js.npm.NpmApi
45
import org.jetbrains.kotlin.gradle.tasks.internal.CleanableStore
56
import java.io.File
67

78
data class NodeJsEnv(
9+
override val download: Boolean,
810
val cleanableStore: CleanableStore,
911
val rootPackageDir: File,
10-
val nodeDir: File,
12+
override val dir: File,
1113
val nodeBinDir: File,
1214
val nodeExecutable: String,
13-
1415
val platformName: String,
1516
val architectureName: String,
16-
val ivyDependency: String,
17-
val downloadBaseUrl: String,
17+
override val ivyDependency: String,
18+
override val downloadBaseUrl: String?,
1819

1920
val packageManager: NpmApi,
20-
) {
21+
) : AbstractEnv {
2122
val isWindows: Boolean
2223
get() = platformName == "win"
2324
}

0 commit comments

Comments
 (0)