From 30c8c27770c3d901ac5f1930da55a85c321e5369 Mon Sep 17 00:00:00 2001 From: Harsh Shandilya Date: Mon, 19 Oct 2020 00:00:52 +0530 Subject: Convert PasswordRepository to an object Signed-off-by: Harsh Shandilya --- .../main/java/com/zeapo/pwdstore/PasswordStore.kt | 29 +- .../ui/dialogs/FolderCreationDialogFragment.kt | 3 +- .../java/com/zeapo/pwdstore/utils/Extensions.kt | 5 +- .../com/zeapo/pwdstore/utils/PasswordRepository.kt | 315 ++++++++++----------- 4 files changed, 172 insertions(+), 180 deletions(-) (limited to 'app/src/main') diff --git a/app/src/main/java/com/zeapo/pwdstore/PasswordStore.kt b/app/src/main/java/com/zeapo/pwdstore/PasswordStore.kt index 162918ba..66778e73 100644 --- a/app/src/main/java/com/zeapo/pwdstore/PasswordStore.kt +++ b/app/src/main/java/com/zeapo/pwdstore/PasswordStore.kt @@ -50,9 +50,6 @@ import com.zeapo.pwdstore.ui.dialogs.FolderCreationDialogFragment import com.zeapo.pwdstore.ui.onboarding.activity.OnboardingActivity import com.zeapo.pwdstore.utils.PasswordItem import com.zeapo.pwdstore.utils.PasswordRepository -import com.zeapo.pwdstore.utils.PasswordRepository.Companion.getRepository -import com.zeapo.pwdstore.utils.PasswordRepository.Companion.getRepositoryDirectory -import com.zeapo.pwdstore.utils.PasswordRepository.Companion.initialize import com.zeapo.pwdstore.utils.PreferenceKeys import com.zeapo.pwdstore.utils.base64 import com.zeapo.pwdstore.utils.commitChange @@ -101,7 +98,7 @@ class PasswordStore : BaseGitActivity() { val intentData = result.data ?: return@registerForActivityResult val filesToMove = requireNotNull(intentData.getStringArrayExtra("Files")) val target = File(requireNotNull(intentData.getStringExtra("SELECTED_FOLDER_PATH"))) - val repositoryPath = getRepositoryDirectory().absolutePath + val repositoryPath = PasswordRepository.getRepositoryDirectory().absolutePath if (!target.isDirectory) { e { "Tried moving passwords to a non-existing folder." } return@registerForActivityResult @@ -158,7 +155,7 @@ class PasswordStore : BaseGitActivity() { } } else -> { - val repoDir = getRepositoryDirectory().absolutePath + val repoDir = PasswordRepository.getRepositoryDirectory().absolutePath val relativePath = getRelativePath("${target.absolutePath}/", repoDir) withContext(Dispatchers.Main) { commitChange( @@ -204,7 +201,7 @@ class PasswordStore : BaseGitActivity() { setContentView(R.layout.activity_pwdstore) model.currentDir.observe(this) { dir -> - val basePath = getRepositoryDirectory().absoluteFile + val basePath = PasswordRepository.getRepositoryDirectory().absoluteFile supportActionBar!!.apply { if (dir != basePath) title = dir.name @@ -384,11 +381,11 @@ class PasswordStore : BaseGitActivity() { } private fun checkLocalRepository() { - val repo = initialize() + val repo = PasswordRepository.initialize() if (repo == null) { directorySelectAction.launch(UserPreference.createDirectorySelectionIntent(this)) } else { - checkLocalRepository(getRepositoryDirectory()) + checkLocalRepository(PasswordRepository.getRepositoryDirectory()) } } @@ -400,7 +397,7 @@ class PasswordStore : BaseGitActivity() { settings.getBoolean(PreferenceKeys.REPO_CHANGED, false)) { settings.edit { putBoolean(PreferenceKeys.REPO_CHANGED, false) } val args = Bundle() - args.putString(REQUEST_ARG_PATH, getRepositoryDirectory().absolutePath) + args.putString(REQUEST_ARG_PATH, PasswordRepository.getRepositoryDirectory().absolutePath) // if the activity was started from the autofill settings, the // intent is to match a clicked pwd with app. pass this to fragment @@ -426,8 +423,8 @@ class PasswordStore : BaseGitActivity() { } private fun getLastChangedTimestamp(fullPath: String): Long { - val repoPath = getRepositoryDirectory() - val repository = getRepository(repoPath) + val repoPath = PasswordRepository.getRepositoryDirectory() + val repository = PasswordRepository.getRepository(repoPath) if (repository == null) { d { "getLastChangedTimestamp: No git repository" } return File(fullPath).lastModified() @@ -450,7 +447,7 @@ class PasswordStore : BaseGitActivity() { for (intent in arrayOf(decryptIntent, authDecryptIntent)) { intent.putExtra("NAME", item.toString()) intent.putExtra("FILE_PATH", item.file.absolutePath) - intent.putExtra("REPO_PATH", getRepositoryDirectory().absolutePath) + intent.putExtra("REPO_PATH", PasswordRepository.getRepositoryDirectory().absolutePath) intent.putExtra("LAST_CHANGED_TIMESTAMP", getLastChangedTimestamp(item.file.absolutePath)) } // Needs an action to be a shortcut intent @@ -494,7 +491,7 @@ class PasswordStore : BaseGitActivity() { i { "Adding file to : ${currentDir.absolutePath}" } val intent = Intent(this, PasswordCreationActivity::class.java) intent.putExtra("FILE_PATH", currentDir.absolutePath) - intent.putExtra("REPO_PATH", getRepositoryDirectory().absolutePath) + intent.putExtra("REPO_PATH", PasswordRepository.getRepositoryDirectory().absolutePath) listRefreshAction.launch(intent) } @@ -530,7 +527,7 @@ class PasswordStore : BaseGitActivity() { refreshPasswordList() AutofillMatcher.updateMatches(applicationContext, delete = filesToDelete) val fmt = selectedItems.joinToString(separator = ", ") { item -> - item.file.toRelativeString(getRepositoryDirectory()) + item.file.toRelativeString(PasswordRepository.getRepositoryDirectory()) } lifecycleScope.launch { commitChange( @@ -644,7 +641,7 @@ class PasswordStore : BaseGitActivity() { } private val currentDir: File - get() = getPasswordFragment()?.currentDir ?: getRepositoryDirectory() + get() = getPasswordFragment()?.currentDir ?: PasswordRepository.getRepositoryDirectory() private suspend fun moveFile(source: File, destinationFile: File) { val sourceDestinationMap = if (source.isDirectory) { @@ -674,7 +671,7 @@ class PasswordStore : BaseGitActivity() { fun matchPasswordWithApp(item: PasswordItem) { val path = item.file .absolutePath - .replace(getRepositoryDirectory().toString() + "/", "") + .replace(PasswordRepository.getRepositoryDirectory().toString() + "/", "") .replace(".gpg", "") val data = Intent() data.putExtra("path", path) diff --git a/app/src/main/java/com/zeapo/pwdstore/ui/dialogs/FolderCreationDialogFragment.kt b/app/src/main/java/com/zeapo/pwdstore/ui/dialogs/FolderCreationDialogFragment.kt index c06a6d63..d5dd9b43 100644 --- a/app/src/main/java/com/zeapo/pwdstore/ui/dialogs/FolderCreationDialogFragment.kt +++ b/app/src/main/java/com/zeapo/pwdstore/ui/dialogs/FolderCreationDialogFragment.kt @@ -22,7 +22,6 @@ import com.zeapo.pwdstore.R import com.zeapo.pwdstore.crypto.BasePgpActivity import com.zeapo.pwdstore.crypto.GetKeyIdsActivity import com.zeapo.pwdstore.utils.PasswordRepository -import com.zeapo.pwdstore.utils.PasswordRepository.Companion.getRepositoryDirectory import com.zeapo.pwdstore.utils.commitChange import com.zeapo.pwdstore.utils.requestInputFocusOnView import java.io.File @@ -41,7 +40,7 @@ class FolderCreationDialogFragment : DialogFragment() { val repo = PasswordRepository.getRepository(null) if (repo != null) { lifecycleScope.launch { - val repoPath = getRepositoryDirectory().absolutePath + val repoPath = PasswordRepository.getRepositoryDirectory().absolutePath requireActivity().commitChange( getString( R.string.git_commit_gpg_id, diff --git a/app/src/main/java/com/zeapo/pwdstore/utils/Extensions.kt b/app/src/main/java/com/zeapo/pwdstore/utils/Extensions.kt index 10a29cf0..7a439e94 100644 --- a/app/src/main/java/com/zeapo/pwdstore/utils/Extensions.kt +++ b/app/src/main/java/com/zeapo/pwdstore/utils/Extensions.kt @@ -6,7 +6,6 @@ package com.zeapo.pwdstore.utils import com.github.michaelbull.result.getOrElse import com.github.michaelbull.result.runCatching -import com.zeapo.pwdstore.utils.PasswordRepository.Companion.getRepositoryDirectory import java.io.File import java.util.Date import org.eclipse.jgit.lib.ObjectId @@ -50,10 +49,10 @@ fun File.contains(other: File): Boolean { /** * Checks if this [File] is in the password repository directory as given - * by [getRepositoryDirectory] + * by [PasswordRepository.getRepositoryDirectory] */ fun File.isInsideRepository(): Boolean { - return canonicalPath.contains(getRepositoryDirectory().canonicalPath) + return canonicalPath.contains(PasswordRepository.getRepositoryDirectory().canonicalPath) } /** diff --git a/app/src/main/java/com/zeapo/pwdstore/utils/PasswordRepository.kt b/app/src/main/java/com/zeapo/pwdstore/utils/PasswordRepository.kt index beb1c7b4..8b403a56 100644 --- a/app/src/main/java/com/zeapo/pwdstore/utils/PasswordRepository.kt +++ b/app/src/main/java/com/zeapo/pwdstore/utils/PasswordRepository.kt @@ -7,9 +7,9 @@ package com.zeapo.pwdstore.utils import android.os.Build import androidx.annotation.RequiresApi import androidx.core.content.edit -import com.github.michaelbull.result.runCatching import com.github.michaelbull.result.getOrElse import com.github.michaelbull.result.onFailure +import com.github.michaelbull.result.runCatching import com.zeapo.pwdstore.Application import java.io.File import java.io.FileFilter @@ -24,7 +24,7 @@ import org.eclipse.jgit.transport.URIish import org.eclipse.jgit.util.FS import org.eclipse.jgit.util.FS_POSIX_Java6 -open class PasswordRepository protected constructor() { +object PasswordRepository { @RequiresApi(Build.VERSION_CODES.O) private class FS_POSIX_Java6_with_optional_symlinks : FS_POSIX_Java6() { @@ -51,191 +51,188 @@ open class PasswordRepository protected constructor() { } } - companion object { - - private var repository: Repository? = null - private val settings by lazy(LazyThreadSafetyMode.NONE) { Application.instance.sharedPrefs } - private val filesDir - get() = Application.instance.filesDir - - /** - * Returns the git repository - * - * @param localDir needed only on the creation - * @return the git repository - */ - @JvmStatic - fun getRepository(localDir: File?): Repository? { - if (repository == null && localDir != null) { - val builder = FileRepositoryBuilder() - repository = runCatching { - builder.run { - gitDir = localDir - if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) { - fs = Java7FSFactory().detect(null) - } - readEnvironment() - }.build() - }.getOrElse { e -> - e.printStackTrace() - null - } + private var repository: Repository? = null + private val settings by lazy(LazyThreadSafetyMode.NONE) { Application.instance.sharedPrefs } + private val filesDir + get() = Application.instance.filesDir + + /** + * Returns the git repository + * + * @param localDir needed only on the creation + * @return the git repository + */ + @JvmStatic + fun getRepository(localDir: File?): Repository? { + if (repository == null && localDir != null) { + val builder = FileRepositoryBuilder() + repository = runCatching { + builder.run { + gitDir = localDir + if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) { + fs = Java7FSFactory().detect(null) + } + readEnvironment() + }.build() + }.getOrElse { e -> + e.printStackTrace() + null } - return repository } + return repository + } - @JvmStatic - val isInitialized: Boolean - get() = repository != null + @JvmStatic + val isInitialized: Boolean + get() = repository != null - @JvmStatic - fun isGitRepo(): Boolean { - if (repository != null) { - return repository!!.objectDatabase.exists() - } - return false + @JvmStatic + fun isGitRepo(): Boolean { + if (repository != null) { + return repository!!.objectDatabase.exists() } + return false + } - @JvmStatic - @Throws(Exception::class) - fun createRepository(localDir: File) { - localDir.delete() + @JvmStatic + @Throws(Exception::class) + fun createRepository(localDir: File) { + localDir.delete() - Git.init().setDirectory(localDir).call() - getRepository(localDir) - } + Git.init().setDirectory(localDir).call() + getRepository(localDir) + } - // TODO add multiple remotes support for pull/push - @JvmStatic - fun addRemote(name: String, url: String, replace: Boolean = false) { - val storedConfig = repository!!.config - val remotes = storedConfig.getSubsections("remote") + // TODO add multiple remotes support for pull/push + @JvmStatic + fun addRemote(name: String, url: String, replace: Boolean = false) { + val storedConfig = repository!!.config + val remotes = storedConfig.getSubsections("remote") - if (!remotes.contains(name)) { - runCatching { - val uri = URIish(url) - val refSpec = RefSpec("+refs/head/*:refs/remotes/$name/*") + if (!remotes.contains(name)) { + runCatching { + val uri = URIish(url) + val refSpec = RefSpec("+refs/head/*:refs/remotes/$name/*") - val remoteConfig = RemoteConfig(storedConfig, name) - remoteConfig.addFetchRefSpec(refSpec) - remoteConfig.addPushRefSpec(refSpec) - remoteConfig.addURI(uri) - remoteConfig.addPushURI(uri) + val remoteConfig = RemoteConfig(storedConfig, name) + remoteConfig.addFetchRefSpec(refSpec) + remoteConfig.addPushRefSpec(refSpec) + remoteConfig.addURI(uri) + remoteConfig.addPushURI(uri) - remoteConfig.update(storedConfig) + remoteConfig.update(storedConfig) - storedConfig.save() - }.onFailure { e -> - e.printStackTrace() + storedConfig.save() + }.onFailure { e -> + e.printStackTrace() + } + } else if (replace) { + runCatching { + val uri = URIish(url) + + val remoteConfig = RemoteConfig(storedConfig, name) + // remove the first and eventually the only uri + if (remoteConfig.urIs.size > 0) { + remoteConfig.removeURI(remoteConfig.urIs[0]) + } + if (remoteConfig.pushURIs.size > 0) { + remoteConfig.removePushURI(remoteConfig.pushURIs[0]) } - } else if (replace) { - runCatching { - val uri = URIish(url) - - val remoteConfig = RemoteConfig(storedConfig, name) - // remove the first and eventually the only uri - if (remoteConfig.urIs.size > 0) { - remoteConfig.removeURI(remoteConfig.urIs[0]) - } - if (remoteConfig.pushURIs.size > 0) { - remoteConfig.removePushURI(remoteConfig.pushURIs[0]) - } - remoteConfig.addURI(uri) - remoteConfig.addPushURI(uri) + remoteConfig.addURI(uri) + remoteConfig.addPushURI(uri) - remoteConfig.update(storedConfig) + remoteConfig.update(storedConfig) - storedConfig.save() - }.onFailure { e -> - e.printStackTrace() - } + storedConfig.save() + }.onFailure { e -> + e.printStackTrace() } } + } - @JvmStatic - fun closeRepository() { - if (repository != null) repository!!.close() - repository = null + @JvmStatic + fun closeRepository() { + if (repository != null) repository!!.close() + repository = null + } + + @JvmStatic + fun getRepositoryDirectory(): File { + return if (settings.getBoolean(PreferenceKeys.GIT_EXTERNAL, false)) { + val externalRepo = settings.getString(PreferenceKeys.GIT_EXTERNAL_REPO) + if (externalRepo != null) + File(externalRepo) + else + File(filesDir.toString(), "/store") + } else { + File(filesDir.toString(), "/store") } + } - @JvmStatic - fun getRepositoryDirectory(): File { - return if (settings.getBoolean(PreferenceKeys.GIT_EXTERNAL, false)) { - val externalRepo = settings.getString(PreferenceKeys.GIT_EXTERNAL_REPO) - if (externalRepo != null) - File(externalRepo) - else - File(filesDir.toString(), "/store") + @JvmStatic + fun initialize(): Repository? { + val dir = getRepositoryDirectory() + // uninitialize the repo if the dir does not exist or is absolutely empty + settings.edit { + if (!dir.exists() || !dir.isDirectory || requireNotNull(dir.listFiles()).isEmpty()) { + putBoolean(PreferenceKeys.REPOSITORY_INITIALIZED, false) } else { - File(filesDir.toString(), "/store") + putBoolean(PreferenceKeys.REPOSITORY_INITIALIZED, true) } } - @JvmStatic - fun initialize(): Repository? { - val dir = getRepositoryDirectory() - // uninitialize the repo if the dir does not exist or is absolutely empty - settings.edit { - if (!dir.exists() || !dir.isDirectory || requireNotNull(dir.listFiles()).isEmpty()) { - putBoolean(PreferenceKeys.REPOSITORY_INITIALIZED, false) - } else { - putBoolean(PreferenceKeys.REPOSITORY_INITIALIZED, true) - } - } + // create the repository static variable in PasswordRepository + return getRepository(File(dir.absolutePath + "/.git")) + } - // create the repository static variable in PasswordRepository - return getRepository(File(dir.absolutePath + "/.git")) - } + /** + * Gets the .gpg files in a directory + * + * @param path the directory path + * @return the list of gpg files in that directory + */ + @JvmStatic + fun getFilesList(path: File?): ArrayList { + if (path == null || !path.exists()) return ArrayList() + + val directories = (path.listFiles(FileFilter { pathname -> pathname.isDirectory }) + ?: emptyArray()).toList() + val files = (path.listFiles(FileFilter { pathname -> pathname.extension == "gpg" }) + ?: emptyArray()).toList() + + val items = ArrayList() + items.addAll(directories) + items.addAll(files) + + return items + } - /** - * Gets the .gpg files in a directory - * - * @param path the directory path - * @return the list of gpg files in that directory - */ - @JvmStatic - fun getFilesList(path: File?): ArrayList { - if (path == null || !path.exists()) return ArrayList() - - val directories = (path.listFiles(FileFilter { pathname -> pathname.isDirectory }) - ?: emptyArray()).toList() - val files = (path.listFiles(FileFilter { pathname -> pathname.extension == "gpg" }) - ?: emptyArray()).toList() - - val items = ArrayList() - items.addAll(directories) - items.addAll(files) - - return items + /** + * Gets the passwords (PasswordItem) in a directory + * + * @param path the directory path + * @return a list of password items + */ + @JvmStatic + fun getPasswords(path: File, rootDir: File, sortOrder: PasswordSortOrder): ArrayList { + // We need to recover the passwords then parse the files + val passList = getFilesList(path).also { it.sortBy { f -> f.name } } + val passwordList = ArrayList() + val showHidden = settings.getBoolean(PreferenceKeys.SHOW_HIDDEN_CONTENTS, false) + + if (passList.size == 0) return passwordList + if (!showHidden) { + passList.filter { !it.isHidden }.toCollection(passList.apply { clear() }) } - - /** - * Gets the passwords (PasswordItem) in a directory - * - * @param path the directory path - * @return a list of password items - */ - @JvmStatic - fun getPasswords(path: File, rootDir: File, sortOrder: PasswordSortOrder): ArrayList { - // We need to recover the passwords then parse the files - val passList = getFilesList(path).also { it.sortBy { f -> f.name } } - val passwordList = ArrayList() - val showHidden = settings.getBoolean(PreferenceKeys.SHOW_HIDDEN_CONTENTS, false) - - if (passList.size == 0) return passwordList - if (!showHidden) { - passList.filter { !it.isHidden }.toCollection(passList.apply { clear() }) - } - passList.forEach { file -> - passwordList.add(if (file.isFile) { - PasswordItem.newPassword(file.name, file, rootDir) - } else { - PasswordItem.newCategory(file.name, file, rootDir) - }) - } - passwordList.sortWith(sortOrder.comparator) - return passwordList + passList.forEach { file -> + passwordList.add(if (file.isFile) { + PasswordItem.newPassword(file.name, file, rootDir) + } else { + PasswordItem.newCategory(file.name, file, rootDir) + }) } + passwordList.sortWith(sortOrder.comparator) + return passwordList } } -- cgit v1.2.3