Skip to content

Commit

Permalink
Move NodeJsFileSystem into its own module (#913)
Browse files Browse the repository at this point in the history
This removes SYSTEM as a statically-available FileSystem instance
on the JS platform, and converts FileSystem into an expect class.
  • Loading branch information
swankjesse committed Apr 1, 2021
1 parent 57cf11c commit 039d996
Show file tree
Hide file tree
Showing 20 changed files with 454 additions and 107 deletions.
5 changes: 3 additions & 2 deletions gradle/gradle-mvn-mpp-push.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -109,8 +109,9 @@ publishing {
kotlinMultiplatform {
artifactId = POM_ARTIFACT_ID + '-multiplatform'
}
jvm {
artifactId = POM_ARTIFACT_ID
def jvm = findByName("jvm")
if (jvm != null) {
jvm.artifactId = POM_ARTIFACT_ID
}
}

Expand Down
52 changes: 52 additions & 0 deletions okio-nodefilesystem/build.gradle
Original file line number Diff line number Diff line change
@@ -0,0 +1,52 @@
if (!kmpJsEnabled) {
return // This module is JS-only; do nothing if JS is off.
}

apply plugin: 'org.jetbrains.kotlin.multiplatform'

kotlin {
js {
configure([compilations.main, compilations.test]) {
tasks.getByName(compileKotlinTaskName).kotlinOptions {
moduleKind = "umd"
sourceMap = true
metaInfo = true
}
}
nodejs {
testTask {
useMocha {
timeout = "30s"
}
}
}
}
sourceSets {
all {
languageSettings {
useExperimentalAnnotation('kotlin.RequiresOptIn')
}
}
jsMain {
dependencies {
implementation project(":okio")
api deps.kotlin.stdLib.common
// Uncomment this to generate fs.fs.module_node.kt. Use it when updating fs.kt.
// implementation(npm("@types/node", "14.14.16", true))
api deps.kotlin.stdLib.js
}
}
jsTest {
dependencies {
implementation deps.kotlin.test.common
implementation deps.kotlin.test.annotations
implementation deps.kotlin.time

implementation project(":okio-fakefilesystem")
implementation deps.kotlin.test.js
}
}
}
}

apply from: "$rootDir/gradle/gradle-mvn-mpp-push.gradle"
2 changes: 2 additions & 0 deletions okio-nodefilesystem/gradle.properties
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
POM_ARTIFACT_ID=okio-nodefilesystem
POM_NAME=Okio Fake Node.js System
File renamed without changes.
File renamed without changes.
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,7 @@ import okio.Path.Companion.toPath
* [node_fs]: https://nodejs.org/dist/latest-v14.x/docs/api/fs.html
*/
@ExperimentalFileSystem
internal object NodeJsFileSystem : FileSystem() {
object NodeJsFileSystem : FileSystem() {
private var S_IFMT = 0xf000 // fs.constants.S_IFMT
private var S_IFREG = 0x8000 // fs.constants.S_IFREG
private var S_IFDIR = 0x4000 // fs.constants.S_IFDIR
Expand Down
File renamed without changes.
24 changes: 24 additions & 0 deletions okio-nodefilesystem/src/jsMain/kotlin/okio/os.kt
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
/*
* Copyright (C) 2020 Square, Inc.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/

/**
* See `fs.kt` for information on what this file does and how to keep it up-to-date.
*/
@file:JsModule("os")
@file:JsNonModule
package okio

internal external fun tmpdir(): String
42 changes: 23 additions & 19 deletions okio/build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -7,27 +7,28 @@ apply plugin: 'org.jetbrains.kotlin.multiplatform'
* ```
* common
* |-- jvm
* '-- nonJvm
* |-- js
* '-- native
* |- unix
* | |-- apple
* | | |-- iosArm64
* | | |-- iosX64
* | | |-- macosX64
* | | |-- watchosArm32
* | | |-- watchosArm64
* | | '-- watchosX86
* | '-- linux
* | '-- linuxX64
* '-- mingw
* '-- mingwX64
* |-- js
* '-- native
* |- unix
* | |-- apple
* | | |-- iosArm64
* | | |-- iosX64
* | | |-- macosX64
* | | |-- watchosArm32
* | | |-- watchosArm64
* | | '-- watchosX86
* | '-- linux
* | '-- linuxX64
* '-- mingw
* '-- mingwX64
* ```
*
* Every child of `unix` also includes a source set that depends on the pointer size:
*
* * sizet32 for watchOS, including watchOS 64-bit architectures
* * sizet64 for everything else
* * `sizet32` for watchOS, including watchOS 64-bit architectures
* * `sizet64` for everything else
*
* The `nonJvm` and `nonJs` source sets exist and exclude a platform.
*
* The `hashFunctions` source set builds on all platforms. It ships as a main source set on non-JVM
* platforms and as a test source set on the JVM platform.
Expand Down Expand Up @@ -85,10 +86,13 @@ kotlin {
implementation project(":okio-fakefilesystem")
}
}
nonJsMain {
}
nonJvmMain {
kotlin.srcDirs += 'src/hashFunctions/kotlin'
}
jvmMain {
dependsOn nonJsMain
dependencies {
api deps.kotlin.stdLib.jdk8
compileOnly deps.animalSniffer.annotations
Expand All @@ -105,18 +109,18 @@ kotlin {
jsMain {
dependsOn nonJvmMain
dependencies {
// Uncomment this to generate fs.fs.module_node.kt. Use it when updating fs.kt.
// implementation(npm("@types/node", "14.14.16", true))
api deps.kotlin.stdLib.js
}
}
jsTest {
dependencies {
implementation deps.kotlin.test.js
implementation project(":okio-nodefilesystem")
}
}

nativeMain {
dependsOn nonJsMain
dependsOn nonJvmMain
}
nativeTest {
Expand Down
6 changes: 0 additions & 6 deletions okio/src/commonMain/kotlin/okio/-Platform.kt
Original file line number Diff line number Diff line change
Expand Up @@ -16,12 +16,6 @@

package okio

@ExperimentalFileSystem
internal expect val PLATFORM_FILE_SYSTEM: FileSystem

@ExperimentalFileSystem
internal expect val PLATFORM_TEMPORARY_DIRECTORY: Path

internal expect fun ByteArray.toUtf8String(): String

internal expect fun String.asUtf8ToByteArray(): ByteArray
Expand Down
78 changes: 10 additions & 68 deletions okio/src/commonMain/kotlin/okio/FileSystem.kt
Original file line number Diff line number Diff line change
Expand Up @@ -15,9 +15,6 @@
*/
package okio

import okio.FileSystem.Companion.SYSTEM
import kotlin.jvm.JvmField

/**
* Read and write access to a hierarchical collection of files, addressed by [paths][Path]. This
* is a natural interface to the [current computer's local file system][SYSTEM].
Expand Down Expand Up @@ -84,7 +81,8 @@ import kotlin.jvm.JvmField
* I/O with.
*/
@ExperimentalFileSystem
abstract class FileSystem {
expect abstract class FileSystem() {

/**
* Resolves [path] against the current working directory and symlinks in this file system. The
* returned path identifies the same file as [path], but with an absolute path that does not
Expand All @@ -106,9 +104,7 @@ abstract class FileSystem {
* @throws IOException if [path] does not exist or its metadata cannot be read.
*/
@Throws(IOException::class)
fun metadata(path: Path): FileMetadata {
return metadataOrNull(path) ?: throw FileNotFoundException("no such file: $path")
}
fun metadata(path: Path): FileMetadata

/**
* Returns metadata of the file, directory, or object identified by [path]. This returns null if
Expand All @@ -127,9 +123,7 @@ abstract class FileSystem {
* problem, or other issue.
*/
@Throws(IOException::class)
fun exists(path: Path): Boolean {
return metadataOrNull(path) != null
}
fun exists(path: Path): Boolean

/**
* Returns the children of the directory identified by [dir]. The returned list is sorted using
Expand Down Expand Up @@ -158,11 +152,7 @@ abstract class FileSystem {
* source. This is a compact way to read the contents of a file.
*/
@Throws(IOException::class)
inline fun <T> read(file: Path, readerAction: BufferedSource.() -> T): T {
return source(file).buffer().use {
it.readerAction()
}
}
inline fun <T> read(file: Path, readerAction: BufferedSource.() -> T): T

/**
* Returns a sink that writes bytes to [file] from beginning to end. If [file] already exists it
Expand All @@ -180,11 +170,7 @@ abstract class FileSystem {
* This is a compact way to write a file.
*/
@Throws(IOException::class)
inline fun <T> write(file: Path, writerAction: BufferedSink.() -> T): T {
return sink(file).buffer().use {
it.writerAction()
}
}
inline fun <T> write(file: Path, writerAction: BufferedSink.() -> T): T

/**
* Returns a sink that appends bytes to the end of [file], creating it if it doesn't already
Expand Down Expand Up @@ -214,20 +200,7 @@ abstract class FileSystem {
* @throws IOException if any [metadata] or [createDirectory] operation fails.
*/
@Throws(IOException::class)
fun createDirectories(dir: Path) {
// Compute the sequence of directories to create.
val directories = ArrayDeque<Path>()
var path: Path? = dir
while (path != null && !exists(path)) {
directories.addFirst(path)
path = path.parent
}

// Create them.
for (toCreate in directories) {
createDirectory(toCreate)
}
}
fun createDirectories(dir: Path)

/**
* Moves [source] to [target] in-place if the underlying file system supports it. If [target]
Expand Down Expand Up @@ -290,13 +263,7 @@ abstract class FileSystem {
* @throws IOException if [source] cannot be read or if [target] cannot be written.
*/
@Throws(IOException::class)
open fun copy(source: Path, target: Path) {
source(source).use { bytesIn ->
sink(target).buffer().use { bytesOut ->
bytesOut.writeAll(bytesIn)
}
}
}
open fun copy(source: Path, target: Path)

/**
* Deletes the file or directory at [path].
Expand All @@ -320,33 +287,9 @@ abstract class FileSystem {
* @throws IOException if any [metadata], [list], or [delete] operation fails.
*/
@Throws(IOException::class)
open fun deleteRecursively(fileOrDirectory: Path) {
val stack = ArrayDeque<Path>()
stack += fileOrDirectory

while (stack.isNotEmpty()) {
val toDelete = stack.removeLast()

val metadata = metadata(toDelete)
val children = if (metadata.isDirectory) list(toDelete) else listOf()

if (children.isNotEmpty()) {
stack += toDelete
stack += children
} else {
delete(toDelete)
}
}
}
open fun deleteRecursively(fileOrDirectory: Path)

companion object {
/**
* The current process's host file system. Use this instance directly, or dependency inject a
* [FileSystem] to make code testable.
*/
@JvmField
val SYSTEM: FileSystem = PLATFORM_FILE_SYSTEM

/**
* Returns a writable temporary directory on [SYSTEM].
*
Expand All @@ -356,7 +299,6 @@ abstract class FileSystem {
* * **Linux, iOS, and macOS**: the path in the `TMPDIR` environment variable.
* * **Windows**: the first non-null of `TEMP`, `TMP`, and `USERPROFILE` environment variables.
*/
@JvmField
val SYSTEM_TEMPORARY_DIRECTORY: Path = PLATFORM_TEMPORARY_DIRECTORY
val SYSTEM_TEMPORARY_DIRECTORY: Path
}
}

0 comments on commit 039d996

Please sign in to comment.