From 911d6ba563aece61f65a4b119fb5e6299ba14e5f Mon Sep 17 00:00:00 2001 From: Harsh Shandilya Date: Mon, 22 Jul 2024 22:28:44 +0530 Subject: fix: part 2 of NIO bugfixing --- .../java/app/passwordstore/data/password/PasswordItem.kt | 5 ++--- .../ui/adapters/PasswordItemRecyclerAdapter.kt | 11 ++++++++--- .../java/app/passwordstore/ui/crypto/BasePGPActivity.kt | 3 ++- .../java/app/passwordstore/ui/passwords/PasswordStore.kt | 13 +++++++------ .../main/kotlin/app/passwordstore/crypto/PGPKeyManager.kt | 9 +++++---- .../kotlin/app/passwordstore/crypto/PGPKeyManagerTest.kt | 8 +++++--- 6 files changed, 29 insertions(+), 20 deletions(-) diff --git a/app/src/main/java/app/passwordstore/data/password/PasswordItem.kt b/app/src/main/java/app/passwordstore/data/password/PasswordItem.kt index 52ea6cd4..df6540df 100644 --- a/app/src/main/java/app/passwordstore/data/password/PasswordItem.kt +++ b/app/src/main/java/app/passwordstore/data/password/PasswordItem.kt @@ -13,8 +13,6 @@ import java.nio.file.Path import kotlin.io.path.absolutePathString import kotlin.io.path.name import kotlin.io.path.nameWithoutExtension -import kotlin.io.path.pathString -import kotlin.io.path.relativeTo data class PasswordItem( val parent: PasswordItem? = null, @@ -25,7 +23,8 @@ data class PasswordItem( val name = file.nameWithoutExtension - val fullPathToParent = file.absolutePathString().replace(rootDir.absolutePathString(), "").replace(file.name, "") + val fullPathToParent = + file.absolutePathString().replace(rootDir.absolutePathString(), "").replace(file.name, "") val longName = BasePGPActivity.getLongName(fullPathToParent, rootDir.absolutePathString(), toString()) diff --git a/app/src/main/java/app/passwordstore/ui/adapters/PasswordItemRecyclerAdapter.kt b/app/src/main/java/app/passwordstore/ui/adapters/PasswordItemRecyclerAdapter.kt index 3e2993b4..9c729564 100644 --- a/app/src/main/java/app/passwordstore/ui/adapters/PasswordItemRecyclerAdapter.kt +++ b/app/src/main/java/app/passwordstore/ui/adapters/PasswordItemRecyclerAdapter.kt @@ -10,6 +10,7 @@ import android.view.MotionEvent import android.view.View import androidx.appcompat.widget.AppCompatImageView import androidx.appcompat.widget.AppCompatTextView +import androidx.core.view.isVisible import androidx.recyclerview.selection.ItemDetailsLookup import androidx.recyclerview.selection.Selection import androidx.recyclerview.widget.RecyclerView @@ -18,9 +19,11 @@ import app.passwordstore.data.password.PasswordItem import app.passwordstore.util.coroutines.DispatcherProvider import app.passwordstore.util.viewmodel.SearchableRepositoryAdapter import app.passwordstore.util.viewmodel.stableId +import kotlin.io.path.ExperimentalPathApi +import kotlin.io.path.PathWalkOption import kotlin.io.path.extension import kotlin.io.path.isDirectory -import kotlin.io.path.listDirectoryEntries +import kotlin.io.path.walk import kotlinx.coroutines.CoroutineScope import kotlinx.coroutines.withContext @@ -52,6 +55,7 @@ open class PasswordItemRecyclerAdapter( return super.onSelectionChanged(listener) as PasswordItemRecyclerAdapter } + @OptIn(ExperimentalPathApi::class) class PasswordItemViewHolder(view: View) : RecyclerView.ViewHolder(view) { private val name: AppCompatTextView = itemView.findViewById(R.id.label) @@ -75,11 +79,12 @@ open class PasswordItemRecyclerAdapter( val count = withContext(dispatcherProvider.io()) { item.file - .listDirectoryEntries() + .walk(PathWalkOption.INCLUDE_DIRECTORIES) .filter { it.isDirectory() || it.extension == "gpg" } + .toSet() .size } - childCount.visibility = if (count > 0) View.VISIBLE else View.GONE + childCount.isVisible = count > 0 childCount.text = "$count" } else { childCount.visibility = View.GONE diff --git a/app/src/main/java/app/passwordstore/ui/crypto/BasePGPActivity.kt b/app/src/main/java/app/passwordstore/ui/crypto/BasePGPActivity.kt index ffec09ad..40ec82d3 100644 --- a/app/src/main/java/app/passwordstore/ui/crypto/BasePGPActivity.kt +++ b/app/src/main/java/app/passwordstore/ui/crypto/BasePGPActivity.kt @@ -161,7 +161,8 @@ open class BasePGPActivity : AppCompatActivity() { */ fun getPGPIdentifiers(subDir: String): List? { val repoRoot = PasswordRepository.getRepositoryDirectory() - // This should ideally be `repoRoot.resolve(subDir)` but for some reason doing that returns `/subDir` as the path + // This should ideally be `repoRoot.resolve(subDir)` but for some reason doing that returns + // `/subDir` as the path // which doesn't work inside `findTillRoot`, so we're doing this manual dance. val gpgIdentifierFile = Paths.get(repoRoot.absolutePathString(), subDir).findTillRoot(".gpg-id", repoRoot) diff --git a/app/src/main/java/app/passwordstore/ui/passwords/PasswordStore.kt b/app/src/main/java/app/passwordstore/ui/passwords/PasswordStore.kt index 6625903d..2f4c2bbd 100644 --- a/app/src/main/java/app/passwordstore/ui/passwords/PasswordStore.kt +++ b/app/src/main/java/app/passwordstore/ui/passwords/PasswordStore.kt @@ -58,6 +58,7 @@ import java.nio.file.Path import java.nio.file.Paths import javax.inject.Inject import kotlin.io.path.ExperimentalPathApi +import kotlin.io.path.PathWalkOption import kotlin.io.path.absolute import kotlin.io.path.absolutePathString import kotlin.io.path.createDirectories @@ -65,12 +66,12 @@ import kotlin.io.path.deleteRecursively import kotlin.io.path.exists import kotlin.io.path.isDirectory import kotlin.io.path.isRegularFile -import kotlin.io.path.listDirectoryEntries import kotlin.io.path.moveTo import kotlin.io.path.name import kotlin.io.path.nameWithoutExtension import kotlin.io.path.pathString import kotlin.io.path.relativeTo +import kotlin.io.path.walk import kotlinx.coroutines.launch import kotlinx.coroutines.withContext import logcat.LogPriority.ERROR @@ -79,6 +80,7 @@ import logcat.logcat const val PASSWORD_FRAGMENT_TAG = "PasswordsList" +@OptIn(ExperimentalPathApi::class) @AndroidEntryPoint class PasswordStore : BaseGitActivity() { @@ -446,7 +448,8 @@ class PasswordStore : BaseGitActivity() { fun deletePasswords(selectedItems: List) { var size = 0 selectedItems.forEach { - if (it.file.isRegularFile()) size++ else size += it.file.listDirectoryEntries().size + if (it.file.isRegularFile()) size++ + else size += it.file.walk(PathWalkOption.INCLUDE_DIRECTORIES).toSet().size } if (size == 0) { selectedItems.map { item -> item.file.deleteRecursively() } @@ -458,7 +461,7 @@ class PasswordStore : BaseGitActivity() { .setPositiveButton(resources.getString(R.string.dialog_yes)) { _, _ -> val filesToDelete = arrayListOf() selectedItems.forEach { item -> - if (item.file.isDirectory()) filesToDelete.addAll(item.file.listDirectoryEntries()) + if (item.file.isDirectory()) filesToDelete.addAll(item.file.walk()) else filesToDelete.add(item.file) } selectedItems.map { item -> item.file.deleteRecursively() } @@ -599,9 +602,7 @@ class PasswordStore : BaseGitActivity() { // Recursively list all files (not directories) below `source`, then // obtain the corresponding target file by resolving the relative path // starting at the destination folder. - source.listDirectoryEntries().associateWith { - destinationFile.resolve(it.relativeTo(source)) - } + source.walk().associateWith { destinationFile.resolve(it.relativeTo(source)) } } else { mapOf(source to destinationFile) } diff --git a/crypto/pgpainless/src/main/kotlin/app/passwordstore/crypto/PGPKeyManager.kt b/crypto/pgpainless/src/main/kotlin/app/passwordstore/crypto/PGPKeyManager.kt index 8efa2a97..f405affc 100644 --- a/crypto/pgpainless/src/main/kotlin/app/passwordstore/crypto/PGPKeyManager.kt +++ b/crypto/pgpainless/src/main/kotlin/app/passwordstore/crypto/PGPKeyManager.kt @@ -23,12 +23,12 @@ import com.github.michaelbull.result.runCatching import com.github.michaelbull.result.unwrap import java.nio.file.Paths import javax.inject.Inject +import kotlin.io.path.ExperimentalPathApi import kotlin.io.path.createDirectories import kotlin.io.path.deleteIfExists import kotlin.io.path.exists -import kotlin.io.path.isRegularFile -import kotlin.io.path.listDirectoryEntries import kotlin.io.path.readBytes +import kotlin.io.path.walk import kotlin.io.path.writeBytes import kotlinx.coroutines.CoroutineDispatcher import kotlinx.coroutines.withContext @@ -37,6 +37,7 @@ import org.bouncycastle.openpgp.PGPSecretKeyRing import org.pgpainless.PGPainless import org.pgpainless.util.selection.userid.SelectUserId +@OptIn(ExperimentalPathApi::class) public class PGPKeyManager @Inject constructor(filesDir: String, private val dispatcher: CoroutineDispatcher) : @@ -98,7 +99,7 @@ constructor(filesDir: String, private val dispatcher: CoroutineDispatcher) : withContext(dispatcher) { runSuspendCatching { if (!keyDirExists()) throw KeyDirectoryUnavailableException - val keyFiles = keyDir.listDirectoryEntries().filter { it.isRegularFile() } + val keyFiles = keyDir.walk().toSet() if (keyFiles.isEmpty()) throw NoKeysAvailableException val keys = keyFiles.map { file -> PGPKey(file.readBytes()) } @@ -134,7 +135,7 @@ constructor(filesDir: String, private val dispatcher: CoroutineDispatcher) : withContext(dispatcher) { runSuspendCatching { if (!keyDirExists()) throw KeyDirectoryUnavailableException - val keyFiles = keyDir.listDirectoryEntries().filter { it.isRegularFile() } + val keyFiles = keyDir.walk().toSet() if (keyFiles.isEmpty()) return@runSuspendCatching emptyList() keyFiles.map { keyFile -> PGPKey(keyFile.readBytes()) }.toList() } diff --git a/crypto/pgpainless/src/test/kotlin/app/passwordstore/crypto/PGPKeyManagerTest.kt b/crypto/pgpainless/src/test/kotlin/app/passwordstore/crypto/PGPKeyManagerTest.kt index 8f4452c8..7f53c6f9 100644 --- a/crypto/pgpainless/src/test/kotlin/app/passwordstore/crypto/PGPKeyManagerTest.kt +++ b/crypto/pgpainless/src/test/kotlin/app/passwordstore/crypto/PGPKeyManagerTest.kt @@ -9,9 +9,10 @@ import app.passwordstore.crypto.errors.NoKeysAvailableException import app.passwordstore.crypto.errors.UnusableKeyException import com.github.michaelbull.result.unwrap import com.github.michaelbull.result.unwrapError +import kotlin.io.path.ExperimentalPathApi import kotlin.io.path.absolutePathString -import kotlin.io.path.listDirectoryEntries import kotlin.io.path.name +import kotlin.io.path.walk import kotlin.test.Test import kotlin.test.assertContentEquals import kotlin.test.assertEquals @@ -24,6 +25,7 @@ import kotlinx.coroutines.test.runTest import org.junit.Rule import org.junit.rules.TemporaryFolder +@OptIn(ExperimentalPathApi::class) class PGPKeyManagerTest { @get:Rule val temporaryFolder: TemporaryFolder = TemporaryFolder() @@ -44,9 +46,9 @@ class PGPKeyManagerTest { val keyId = keyManager.getKeyId(keyManager.addKey(secretKey).unwrap()) assertEquals(KeyId(CryptoConstants.KEY_ID), keyId) // Check if the keys directory have one file - assertEquals(1, filesDir.listDirectoryEntries().size) + assertEquals(1, filesDir.walk().toSet().size) // Check if the file name is correct - val keyFile = keysDir.listDirectoryEntries().first() + val keyFile = keysDir.walk().toSet().first() assertEquals(keyFile.name, "$keyId.${PGPKeyManager.KEY_EXTENSION}") } -- cgit v1.2.3