diff options
Diffstat (limited to 'libs')
6 files changed, 111 insertions, 5 deletions
diff --git a/libs/samba/build.gradle.kts b/libs/samba/build.gradle.kts index b7816c4..7fab391 100644 --- a/libs/samba/build.gradle.kts +++ b/libs/samba/build.gradle.kts @@ -46,6 +46,7 @@ android { dependencies { implementation(project(":libs:io")) + testImplementation(project(":libs:utils")) } listOf("Debug", "Release").forEach { buildType -> diff --git a/libs/samba/src/main/java/org/the_jk/cleversync/io/samba/SambaConnection.kt b/libs/samba/src/main/java/org/the_jk/cleversync/io/samba/SambaConnection.kt index 6eda092..a645804 100644 --- a/libs/samba/src/main/java/org/the_jk/cleversync/io/samba/SambaConnection.kt +++ b/libs/samba/src/main/java/org/the_jk/cleversync/io/samba/SambaConnection.kt @@ -43,6 +43,8 @@ internal class SambaConnection(uri: String, credentials: SambaCredentials) { fun openFile(path: String, read: NativeSamba.OpenMode): NativeSamba.File? = if (connected) context.openFile(join(url!!.path(), path), read) else null + override fun toString() = description + companion object { fun join(a: String, b: String): String { if (a.isEmpty() || b.startsWith("/")) return b diff --git a/libs/samba/src/main/java/org/the_jk/cleversync/io/samba/SambaDirectory.kt b/libs/samba/src/main/java/org/the_jk/cleversync/io/samba/SambaDirectory.kt index d9ec6aa..f5230b2 100644 --- a/libs/samba/src/main/java/org/the_jk/cleversync/io/samba/SambaDirectory.kt +++ b/libs/samba/src/main/java/org/the_jk/cleversync/io/samba/SambaDirectory.kt @@ -1,6 +1,10 @@ package org.the_jk.cleversync.io.samba +import android.os.Handler +import android.os.Looper import androidx.lifecycle.LiveData +import androidx.lifecycle.MutableLiveData +import androidx.lifecycle.map import org.the_jk.cleversync.io.Directory import org.the_jk.cleversync.io.File import org.the_jk.cleversync.io.ModifiableDirectory @@ -8,12 +12,48 @@ import org.the_jk.cleversync.io.ModifiableFile import org.the_jk.cleversync.io.ModifiableLink import java.io.IOException import java.time.Instant +import kotlin.time.Duration.Companion.seconds internal open class SambaDirectory( private val conn: SambaConnection, private val path: String, override val name: String, ) : ModifiableDirectory { + private val modifiableLiveContent = object : MutableLiveData<ModifiableDirectory.Content>() { + private val looper = Looper.myLooper() + private val handler = if (looper != null) Handler(looper) else null + private val updateCallback = Runnable { update() } + + override fun onActive() { + super.onActive() + + value = modifiableList() + handler?.postDelayed(updateCallback, LIVE_UPDATE_INTERVAL.inWholeMilliseconds) + } + + override fun onInactive() { + super.onInactive() + + handler?.removeCallbacks(updateCallback) + } + + private fun update() { + val newValue = modifiableList() + if (value != newValue) postValue(newValue) + handler?.postDelayed(updateCallback, LIVE_UPDATE_INTERVAL.inWholeMilliseconds) + } + } + + private val liveContent: LiveData<Directory.Content> by lazy { + modifiableLiveContent.map { + Directory.Content( + it.directories, + it.files, + it.links, + ) + } + } + override fun modifiableOpenDir(name: String): ModifiableDirectory? { val newPath = SambaConnection.join(path, name) val entry = conn.entry(newPath) ?: return null @@ -60,9 +100,7 @@ internal open class SambaDirectory( return ModifiableDirectory.Content(directories, files, links) } - override fun modifiableLiveList(): LiveData<ModifiableDirectory.Content> { - TODO("Not yet implemented") - } + override fun modifiableLiveList() = modifiableLiveContent override fun createDirectory(name: String): ModifiableDirectory { val newPath = SambaConnection.join(path, name) @@ -109,7 +147,13 @@ internal open class SambaDirectory( Directory.Content(directories, files, links) } - override fun liveList(): LiveData<Directory.Content> { - TODO("Not yet implemented") + override fun liveList() = liveContent + + override fun equals(other: Any?) = other is SambaDirectory && other.conn == conn && other.path == path + override fun hashCode() = path.hashCode() + override fun toString() = "$conn/$path" + + private companion object { + private val LIVE_UPDATE_INTERVAL = 10.seconds } } diff --git a/libs/samba/src/main/java/org/the_jk/cleversync/io/samba/SambaFile.kt b/libs/samba/src/main/java/org/the_jk/cleversync/io/samba/SambaFile.kt index 9913035..c8bb98d 100644 --- a/libs/samba/src/main/java/org/the_jk/cleversync/io/samba/SambaFile.kt +++ b/libs/samba/src/main/java/org/the_jk/cleversync/io/samba/SambaFile.kt @@ -119,6 +119,10 @@ internal class SambaFile( return entry.lastModified } + override fun equals(other: Any?) = other is SambaFile && other.conn == conn && other.path == path + override fun hashCode() = path.hashCode() + override fun toString() = "$conn/$path" + private fun useCached(): Boolean { return Instant.now().isBefore(cacheEndOfLife) } diff --git a/libs/samba/src/main/java/org/the_jk/cleversync/io/samba/SambaLink.kt b/libs/samba/src/main/java/org/the_jk/cleversync/io/samba/SambaLink.kt index 2d0d080..a9e6f04 100644 --- a/libs/samba/src/main/java/org/the_jk/cleversync/io/samba/SambaLink.kt +++ b/libs/samba/src/main/java/org/the_jk/cleversync/io/samba/SambaLink.kt @@ -51,6 +51,10 @@ internal class SambaLink( } } + override fun equals(other: Any?) = other is SambaLink && other.conn == conn && other.path == path + override fun hashCode() = path.hashCode() + override fun toString() = "$conn/$path" + private fun doResolve(): Pair<String, NativeSamba.DirEntry?> { var linkPath = path var entry: NativeSamba.DirEntry? = null diff --git a/libs/samba/src/test/java/org/the_jk/cleversync/samba/SambaTreeTest.kt b/libs/samba/src/test/java/org/the_jk/cleversync/samba/SambaTreeTest.kt index d2a2e04..b0ecf03 100644 --- a/libs/samba/src/test/java/org/the_jk/cleversync/samba/SambaTreeTest.kt +++ b/libs/samba/src/test/java/org/the_jk/cleversync/samba/SambaTreeTest.kt @@ -11,10 +11,15 @@ import org.junit.Test import org.junit.runner.RunWith import org.robolectric.RobolectricTestRunner import org.robolectric.annotation.Config +import org.robolectric.shadows.ShadowLooper +import org.the_jk.cleversync.io.Directory import org.the_jk.cleversync.io.samba.SambaCredentials +import org.the_jk.cleversync.safeValue import java.io.File import java.nio.charset.StandardCharsets import java.nio.file.Files +import java.util.concurrent.TimeUnit +import kotlin.time.Duration.Companion.seconds @Config(manifest=Config.NONE) @RunWith(RobolectricTestRunner::class) @@ -54,6 +59,16 @@ class SambaTreeTest { } @Test + fun listEmptyRootLive() { + SambaTreeFactory.tree(uri, credentials).getOrThrow().use { root -> + val content = root.liveList().safeValue() + assertThat(content?.directories).isEmpty() + assertThat(content?.files).isEmpty() + assertThat(content?.links).isEmpty() + } + } + + @Test fun listRootWithSymlink() { File(shareDir, "dir").mkdir() File(shareDir, "file").writeText("foo") @@ -148,6 +163,42 @@ class SambaTreeTest { assertThat(File(shareDir, "file").readText()).isEqualTo("foobar") } + @Test + fun createDirectory() { + SambaTreeFactory.modifiableTree(uri, credentials).getOrThrow().use { root -> + val foo = root.createDirectory("foo") + assertThat(foo.name).isEqualTo("foo") + val fooContent = foo.list() + assertThat(fooContent.directories).isEmpty() + assertThat(fooContent.files).isEmpty() + assertThat(fooContent.links).isEmpty() + val content = root.list() + assertThat(content.directories).contains(foo) + assertThat(content.files).isEmpty() + assertThat(content.links).isEmpty() + } + + assertThat(File(shareDir, "foo").isDirectory).isTrue() + } + + @Test(timeout = 10000) + fun observeCreateDirectory() { + SambaTreeFactory.modifiableTree(uri, credentials).getOrThrow().use { root -> + val content = root.liveList() + var dir: Directory? = null + content.observeForever { + if (it.directories.size == 1) dir = it.directories[0] + } + root.createDirectory("foo") + while (dir == null) { + ShadowLooper.idleMainLooper(10, TimeUnit.SECONDS) + } + assertThat(dir?.name).isEqualTo("foo") + } + + assertThat(File(shareDir, "foo").isDirectory).isTrue() + } + companion object { private lateinit var uri: String private lateinit var credentials: SambaCredentials |
