2025-08-21 16:57:23 -07:00
|
|
|
# vim: set et sta sw=4 ts=4 :
|
|
|
|
|
#
|
|
|
|
|
# This module exposes an "embeddedFs" object, that can
|
|
|
|
|
# return file handles for either native use (extracted on first run)
|
|
|
|
|
# or wasm (via preload-files).
|
|
|
|
|
|
|
|
|
|
import
|
|
|
|
|
std/os,
|
|
|
|
|
std/files,
|
|
|
|
|
std/paths,
|
|
|
|
|
std/strformat,
|
2025-08-22 11:47:04 -07:00
|
|
|
std/strutils,
|
2025-08-21 16:57:23 -07:00
|
|
|
std/tempfiles
|
|
|
|
|
|
2025-08-22 11:47:04 -07:00
|
|
|
import
|
|
|
|
|
constants
|
|
|
|
|
|
2025-08-21 16:57:23 -07:00
|
|
|
type
|
|
|
|
|
EmbeddedFS* = object
|
|
|
|
|
EmbeddedFSError* = object of CatchableError
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
when not defined( emscripten ):
|
|
|
|
|
import zippy/tarballs
|
|
|
|
|
const ROOT = Path( currentSourcePath() ).parentDir.parentDir.parentDir
|
|
|
|
|
const RESOURCES = staticRead( $(ROOT / Path("resources.tgz")) )
|
|
|
|
|
|
|
|
|
|
let appname = extractFilename( getAppFileName() )
|
|
|
|
|
let dataDir = Path(getDataDir()) / Path( appname )
|
|
|
|
|
let confDir = Path(getConfigDir()) / Path( appname )
|
|
|
|
|
let confFile* = confDir / Path("config.ini")
|
|
|
|
|
|
|
|
|
|
else:
|
|
|
|
|
let dataDir = Path( "resources" )
|
|
|
|
|
let confDir = Path( "resources" )
|
|
|
|
|
let confFile* = confDir / Path("config.ini")
|
|
|
|
|
|
|
|
|
|
|
2025-08-22 11:47:04 -07:00
|
|
|
|
2025-08-21 16:57:23 -07:00
|
|
|
proc path*( data: EmbeddedFS, path: string ): Path =
|
|
|
|
|
## Returns the path of an embedded file.
|
|
|
|
|
return dataDir / Path( path )
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
proc `[]`*( data: EmbeddedFS, path: string ): string =
|
|
|
|
|
## Returns the contents of an embedded file.
|
|
|
|
|
if not fileExists( data.path(path) ):
|
|
|
|
|
raise newException( EmbeddedFSError, "No such file: {path}".fmt )
|
|
|
|
|
|
|
|
|
|
let f = open( $data.path(path) )
|
|
|
|
|
defer: f.close
|
|
|
|
|
return f.readAll
|
|
|
|
|
|
|
|
|
|
|
2025-08-22 11:47:04 -07:00
|
|
|
proc newEmbeddedFS(): EmbeddedFS =
|
|
|
|
|
## Initialize the embedded filesystem.
|
|
|
|
|
##
|
|
|
|
|
## If the current runtime version is different than the binary version,
|
|
|
|
|
## re-extract the embedded filesystem to disk.
|
|
|
|
|
|
|
|
|
|
result = EmbeddedFS()
|
|
|
|
|
when defined( emscripten ): return
|
|
|
|
|
|
|
|
|
|
try:
|
|
|
|
|
var fsVersion = readFile( $result.path(".version") )
|
|
|
|
|
fsVersion.removeSuffix
|
|
|
|
|
if fsVersion == VERSION: return
|
|
|
|
|
except:
|
|
|
|
|
discard
|
|
|
|
|
|
|
|
|
|
echo "Extracting embedded resources for v{VERSION}".fmt
|
|
|
|
|
|
|
|
|
|
createDir( getDataDir() )
|
|
|
|
|
createDir( $confDir )
|
|
|
|
|
|
|
|
|
|
let ( tarball, path ) = createTempFile( "{appname}_resources_".fmt, ".tgz" )
|
|
|
|
|
tarball.write( RESOURCES )
|
|
|
|
|
tarball.close
|
2025-08-21 16:57:23 -07:00
|
|
|
|
2025-08-22 11:47:04 -07:00
|
|
|
removeDir( $dataDir )
|
|
|
|
|
extractAll( path, $dataDir )
|
|
|
|
|
removeFile( path )
|
2025-08-21 16:57:23 -07:00
|
|
|
|
2025-08-22 11:47:04 -07:00
|
|
|
let source = dataDir / Path( "config.ini" )
|
|
|
|
|
if not fileExists( confFile ): copyFile( $source, $confFile )
|
2025-08-21 16:57:23 -07:00
|
|
|
|
|
|
|
|
|
2025-08-22 11:47:04 -07:00
|
|
|
let embeddedFs* = newEmbeddedFS()
|
2025-08-21 16:57:23 -07:00
|
|
|
|