# 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, std/strutils, std/tempfiles import constants 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") 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 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 removeDir( $dataDir ) extractAll( path, $dataDir ) removeFile( path ) let source = dataDir / Path( "config.ini" ) if not fileExists( confFile ): copyFile( $source, $confFile ) let embeddedFs* = newEmbeddedFS()