From 416d12bce8a2ab2ac6cb8e7a0123f8c9f2f2ded0 Mon Sep 17 00:00:00 2001 From: Martin Petrov <357181+mpetrov@users.noreply.github.com> Date: Tue, 9 Nov 2021 03:30:30 -0500 Subject: [PATCH] [Native] Lazily create dependency & cache directories. (#4627) Previously initializing the DependencyProcessor will result in file IO. In a fully-hermetic environment where all dependencies are local, this IO is redundant and may require the build system (e.g. Bazel) to do extra setup to ensure there is a local writable directory specified for these directories. This change will instead cause the dependency processor to bail early and skip downloading dependencies if all are local anyway. Prior to this change kicking off a clean build with local dependencies would result in: ``` rm -rf ~/.konan/cache; fswatch -ax ~/.konan ~/.konan/cache Created IsDir ~/.konan/cache/.lock Created IsFile ``` After the change no FS operations are performed. --- .../kotlin/konan/util/DependencyProcessor.kt | 29 ++++++++++++++----- 1 file changed, 21 insertions(+), 8 deletions(-) diff --git a/kotlin-native/shared/src/main/kotlin/org/jetbrains/kotlin/konan/util/DependencyProcessor.kt b/kotlin-native/shared/src/main/kotlin/org/jetbrains/kotlin/konan/util/DependencyProcessor.kt index 7ad40cd88cc..08817b62597 100644 --- a/kotlin-native/shared/src/main/kotlin/org/jetbrains/kotlin/konan/util/DependencyProcessor.kt +++ b/kotlin-native/shared/src/main/kotlin/org/jetbrains/kotlin/konan/util/DependencyProcessor.kt @@ -96,10 +96,17 @@ class DependencyProcessor(dependenciesRoot: File, private val deleteArchives: Boolean = true, private val archiveType: ArchiveType = ArchiveType.systemDefault) { - private val dependenciesDirectory = dependenciesRoot.apply { mkdirs() } - private val cacheDirectory = homeDependencyCache.apply { mkdirs() } + private val dependenciesDirectory by lazy { + dependenciesRoot.apply { mkdirs() } + } - private val lockFile = File(cacheDirectory, ".lock").apply { if (!exists()) createNewFile() } + private val cacheDirectory by lazy { + homeDependencyCache.apply { mkdirs() } + } + + private val lockFile by lazy { + File(cacheDirectory, ".lock").apply { if (!exists()) createNewFile() } + } var showInfo = true private var isInfoShown = false @@ -289,18 +296,24 @@ class DependencyProcessor(dependenciesRoot: File, // String literals are internalized so we create a new instance to avoid synchronization on a shared object. java.lang.String("lock") } + + val remoteDependencies = resolvedDependencies.mapNotNull { (dependency, candidate) -> + when (candidate) { + is DependencySource.Local -> null + is DependencySource.Remote -> dependency to candidate + } + } + if (remoteDependencies.isEmpty()) { return } + synchronized(lock) { RandomAccessFile(lockFile, "rw").channel.lock().use { - resolvedDependencies.forEach { (dependency, candidate) -> + remoteDependencies.forEach { (dependency, candidate) -> val baseUrl = when (candidate) { - is DependencySource.Local -> null DependencySource.Remote.Public -> dependenciesUrl DependencySource.Remote.Internal -> InternalServer.url } // TODO: consider using different caches for different remotes. - if (baseUrl != null) { - downloadDependency(dependency, baseUrl) - } + downloadDependency(dependency, baseUrl) } } }