@@ -77,83 +77,48 @@ internal class DbStudioCommand : AbstractSubcommand<ToolState, CommandContext>()
7777 private val SQLITE_EXTENSIONS = setOf (" .db" , " .sqlite" , " .sqlite3" , " .db3" )
7878 }
7979
80- private fun discoverDatabases (): List <DiscoveredDatabase > {
81- val databases = mutableListOf<DiscoveredDatabase >()
82-
83- val cwd = Path .of(System .getProperty(" user.dir" ))
84-
85- searchDirectory(cwd, databases, depth = 0 , maxDepth = 0 , isLocal = true )
86-
87- try {
88- cwd.listDirectoryEntries()
89- .filter { it.isDirectory() }
90- .forEach { subDir ->
91- searchDirectory(subDir, databases, depth = 1 , maxDepth = 1 , isLocal = true )
92- }
93- } catch (e: Exception ) {
94-
95- }
96-
97- val userHome = Path .of(System .getProperty(" user.home" ))
98- val osName = System .getProperty(" os.name" ).lowercase()
99-
100- val userDataDirs = when {
101- osName.contains(" mac" ) -> listOf (
102- userHome.resolve(" Library/Application Support" )
103- )
104- osName.contains(" win" ) -> listOf (
105- Path .of(System .getenv(" APPDATA" ) ? : userHome.resolve(" AppData/Roaming" ).toString())
106- )
107- else -> listOf ( // Linux/Unix
108- userHome.resolve(" .local/share" )
109- )
110- }
111-
112- userDataDirs.forEach { dir ->
113- if (dir.exists() && dir.isDirectory()) {
114- searchDirectory(dir, databases, depth = 0 , maxDepth = 1 , isLocal = false )
115- }
116- }
117-
118- return databases.sortedWith(
119- compareByDescending<DiscoveredDatabase > { it.isLocal }
120- .thenByDescending { it.lastModified }
80+ // Extension function for SQLite detection
81+ private fun Path.isSqliteDatabase (): Boolean =
82+ isRegularFile() && SQLITE_EXTENSIONS .any { name.endsWith(it, ignoreCase = true ) }
83+
84+ // Extension function to safely convert Path to DiscoveredDatabase
85+ private fun Path.toDiscoveredDatabase (): DiscoveredDatabase ? = runCatching {
86+ DiscoveredDatabase (
87+ path = toAbsolutePath().toString(),
88+ name = name,
89+ size = fileSize(),
90+ lastModified = getLastModifiedTime().toMillis(),
91+ isLocal = true ,
12192 )
122- }
93+ }.getOrNull()
12394
95+ // Functional version that returns a list
12496 private fun searchDirectory (
12597 dir : Path ,
126- databases : MutableList <DiscoveredDatabase >,
12798 depth : Int ,
128- maxDepth : Int ,
129- isLocal : Boolean
130- ) {
131- try {
132- dir.listDirectoryEntries().forEach { file ->
133- when {
134- file.isRegularFile() && SQLITE_EXTENSIONS .any { file.name.endsWith(it, ignoreCase = true ) } -> {
135- try {
136- databases.add(
137- DiscoveredDatabase (
138- path = file.toAbsolutePath().toString(),
139- name = file.name,
140- size = file.fileSize(),
141- lastModified = file.getLastModifiedTime().toMillis(),
142- isLocal = isLocal,
143- )
144- )
145- } catch (e: Exception ) {
146- // Silently ignore files we can't read
147- }
148- }
149- file.isDirectory() && depth < maxDepth -> {
150- searchDirectory(file, databases, depth + 1 , maxDepth, isLocal)
151- }
152- }
99+ maxDepth : Int
100+ ): List <DiscoveredDatabase > = runCatching {
101+ dir.listDirectoryEntries().flatMap { file ->
102+ when {
103+ file.isSqliteDatabase() -> listOfNotNull(file.toDiscoveredDatabase())
104+ file.isDirectory() && depth < maxDepth -> searchDirectory(file, depth + 1 , maxDepth)
105+ else -> emptyList()
153106 }
154- } catch (e: Exception ) {
155- // Silently ignore permission errors
156107 }
108+ }.getOrElse { emptyList() }
109+
110+ private fun discoverDatabases (): List <DiscoveredDatabase > {
111+ val cwd = Path .of(System .getProperty(" user.dir" ))
112+
113+ // Search current directory and immediate subdirectories
114+ val currentDir = searchDirectory(cwd, depth = 0 , maxDepth = 0 )
115+ val subDirs = runCatching {
116+ cwd.listDirectoryEntries()
117+ .filter { it.isDirectory() }
118+ .flatMap { searchDirectory(it, depth = 1 , maxDepth = 1 ) }
119+ }.getOrElse { emptyList() }
120+
121+ return (currentDir + subDirs).sortedByDescending { it.lastModified }
157122 }
158123
159124 private fun copyDirectory (sourcePath : Path , targetDir : Path ) {
@@ -233,7 +198,7 @@ internal class DbStudioCommand : AbstractSubcommand<ToolState, CommandContext>()
233198 val discovered = discoverDatabases()
234199
235200 if (discovered.isEmpty()) {
236- return CommandResult .err(message = " No SQLite databases found in current directory or user data directories" )
201+ return CommandResult .err(message = " No SQLite databases found in current directory or user data directories. If you're targeting a database file outside of this directory, provide the path as an argument (e.g. \" elide db studio /my/database/path.db \" ) " )
237202 }
238203
239204 discovered
0 commit comments