Coverage Summary for Class: AppDataDir_jvmKt (com.georgeci.moneysurfer.domain.storage)

Class Class, % Method, % Branch, % Line, % Instruction, %
AppDataDir_jvmKt 0% (0/1) 0% (0/3) 0% (0/28) 0% (0/20) 0% (0/178)


 package com.georgeci.moneysurfer.domain.storage
 
 import java.io.File
 import java.io.IOException
 import java.nio.file.Files
 import java.nio.file.Path
 import java.nio.file.attribute.PosixFilePermissions
 import java.util.Locale
 
 private const val APP_DIR_NAME = "MoneySurfer"
 private const val OWNER_ONLY = "rwx------"
 
 /**
  * Per-user application-data directory for MoneySurfer on JVM desktop targets.
  *
  * Resolves to the platform convention:
  * - macOS:   ~/Library/Application Support/MoneySurfer
  * - Windows: %APPDATA%\MoneySurfer (falling back to ~/AppData/Roaming)
  * - Linux:   $XDG_DATA_HOME/MoneySurfer (falling back to ~/.local/share)
  *
  * `APPDATA` / `XDG_DATA_HOME` are honoured only when set to an absolute path, so
  * a stray relative value cannot redirect storage into the working directory. The
  * directory is created with owner-only permissions (0700) where the file system
  * supports POSIX permissions, so local databases and preferences are not left
  * world-readable under a shared /tmp. Creation or permission-tightening failures
  * are surfaced rather than swallowed.
  */
 fun appDataDir(): File {
     val home = File(System.getProperty("user.home").orEmpty())
     val os = System.getProperty("os.name").orEmpty().lowercase(Locale.ROOT)
     val base = when {
         os.contains("mac") || os.contains("darwin") ->
             File(home, "Library/Application Support")
         os.contains("win") ->
             absoluteEnvDir("APPDATA") ?: File(home, "AppData/Roaming")
         else ->
             absoluteEnvDir("XDG_DATA_HOME") ?: File(home, ".local/share")
     }
     return File(base, APP_DIR_NAME).also { it.createOwnerOnly() }
 }
 
 /** The environment variable as a directory, but only when it is an absolute path. */
 private fun absoluteEnvDir(name: String): File? =
     System.getenv(name)
         ?.takeIf { it.isNotBlank() }
         ?.let(::File)
         ?.takeIf { it.isAbsolute }
 
 private fun File.createOwnerOnly() {
     val path: Path = toPath()
     if (path.fileSystem.supportedFileAttributeViews().contains("posix")) {
         val perms = PosixFilePermissions.fromString(OWNER_ONLY)
         Files.createDirectories(path, PosixFilePermissions.asFileAttribute(perms))
         // Enforce owner-only even if the directory already existed with looser perms.
         Files.setPosixFilePermissions(path, perms)
     } else if (!mkdirs() && !isDirectory) {
         throw IOException("Unable to create app-data directory: $path")
     }
 }