Commit desktop bundles can bake environment defaults/clears (--bundle-unset HERMES_DESKTOP_USER_DATA_DIR, HERMES_HOME=null) that stomp the smoke driver's --home/--user-data pin, so every native smoke threw "Desktop did not honor the isolated home and userData directories". Instead of pinning, the driver replays the bundle env over its launch env through the same resolver the app runs, seeds the predicted home (bailing rather than wiping when it is not empty), and verifies the app landed there via a new hermesHome report on the version bridge. The --user-data equality check now applies only when the artifact bakes no env. - Extract the pure path resolver into electron/data-paths.mjs (data-paths.ts is now a typed re-export) so Node's type-stripped driver can import it. - Add applyBundleEnvironment/validateBundleEnvironment as the pure twin of the bundle banner, pinned by a lockstep test. - Record bundleEnv in the install stamp and add readBundledBundleEnv. - Report hermesHome from hermes:version and assert it equals the predicted home.
67 lines
2.8 KiB
JavaScript
67 lines
2.8 KiB
JavaScript
// data-paths.mjs — the pure path-resolution core, shared by the desktop app
|
|
// (via data-paths.ts, a typed re-export) and the CI smoke driver (which runs
|
|
// under Node's type-stripping and therefore cannot import the app's
|
|
// extensionless TypeScript directly). No Electron imports here; only node:path.
|
|
//
|
|
// data-paths.ts re-exports these names and adds the TypeScript-facing
|
|
// `HermesHomeOptions` interface. Keep the two in lockstep: every behavior in
|
|
// this file is exercised by data-paths.test.ts through the re-export.
|
|
|
|
import path from 'node:path'
|
|
|
|
/** A HERMES_HOME rooted inside a `profiles/` directory names the profile's
|
|
* parent (the home), not the profile directory itself. */
|
|
function normalizeHermesHomeRoot(hermesHome, pathModule) {
|
|
if (!hermesHome) {
|
|
return hermesHome
|
|
}
|
|
const resolved = pathModule.resolve(String(hermesHome))
|
|
const parent = pathModule.dirname(resolved)
|
|
if (pathModule.basename(parent).toLowerCase() === 'profiles') {
|
|
return pathModule.dirname(parent)
|
|
}
|
|
return resolved
|
|
}
|
|
|
|
export function platformDefaultHermesHome(home, env = process.env, platform = process.platform) {
|
|
const suffix = env.HERMES_DATA_DIR_SUFFIX || ''
|
|
if (platform === 'win32') {
|
|
const base = (env.LOCALAPPDATA || '').trim() || path.win32.join(home, 'AppData', 'Local')
|
|
return path.win32.join(base, 'hermes') + suffix
|
|
}
|
|
return path.posix.join(home, '.hermes') + suffix
|
|
}
|
|
|
|
export function resolveDesktopUserData(defaultPath, env = process.env) {
|
|
return env.HERMES_DESKTOP_USER_DATA_DIR
|
|
? path.resolve(env.HERMES_DESKTOP_USER_DATA_DIR)
|
|
: defaultPath + (env.HERMES_DATA_DIR_SUFFIX || '')
|
|
}
|
|
|
|
export function resolveDesktopHermesHome({ home, env = process.env, platform = process.platform, directoryExists = () => false, readWindowsHome = () => null }) {
|
|
const paths = platform === 'win32' ? path.win32 : path.posix
|
|
if (env.HERMES_HOME) {
|
|
return normalizeHermesHomeRoot(env.HERMES_HOME, paths)
|
|
}
|
|
// Fresh-install rehearsals must not touch the real Hermes home.
|
|
if (env.HERMES_DESKTOP_USER_DATA_DIR) {
|
|
return paths.join(paths.resolve(env.HERMES_DESKTOP_USER_DATA_DIR), 'hermes-home')
|
|
}
|
|
if (platform === 'win32' && env.HERMES_HOME === undefined) {
|
|
// Explorer can miss setx changes. An explicit empty value opts out of that fallback.
|
|
const registryHome = readWindowsHome()
|
|
if (registryHome) {
|
|
return normalizeHermesHomeRoot(registryHome, paths)
|
|
}
|
|
}
|
|
const defaultHome = platformDefaultHermesHome(home, env, platform)
|
|
// Keep the legacy migration for ordinary installs, not isolated suffix runs.
|
|
if (platform === 'win32' && !env.HERMES_DATA_DIR_SUFFIX) {
|
|
const legacy = paths.join(home, '.hermes')
|
|
if (!directoryExists(defaultHome) && directoryExists(legacy)) {
|
|
return legacy
|
|
}
|
|
}
|
|
return defaultHome
|
|
}
|