41 lines
2.1 KiB
JavaScript
41 lines
2.1 KiB
JavaScript
// One-time copy of the user-authored folders into a custom data directory.
|
|||
|
|
//
|
||
|
|
// `OPENCHAMBER_DATA_DIR` is documented as "the OpenChamber data directory",
|
||
|
|
// but for a long time only the flat files (settings, auth, push tokens)
|
||
|
|
// followed it while `projects/`, `themes/`, and `speech-models/` stayed under
|
||
|
|
// `~/.config/openchamber`. Now every folder hangs off the data directory, so an
|
||
|
|
// instance that already ran with a custom directory finds those folders in
|
||
|
|
// the old place. This copies each one over once: only when the new location
|
||
|
|
// does not exist yet and the old one does. It copies rather than moves
|
||
|
|
// because a second instance on the same machine (a custom directory next to
|
||
|
|
// the default one) must not strip the default instance of its projects.
|
||
|
|
|
||
|
|
const USER_DIR_ENTRIES = Object.freeze(['projects', 'themes', 'speech-models']);
|
||
|
|
|
||
|
|
const exists = async (fsPromises, target) => fsPromises.access(target).then(() => true, () => false);
|
||
|
|
|
||
|
|
/**
|
||
|
|
* Copy the user folders from `legacyRoot` into `dataDir`. Returns the entries
|
||
|
|
* copied. A no-op when the two roots are the same directory. A folder whose
|
||
|
|
* copy fails is reported through `warn` and its partial copy removed; the
|
||
|
|
* server keeps starting, reading the (empty) new location.
|
||
|
|
*/
|
||
|
|
export const migrateLegacyUserDirs = async ({ fsPromises, path, dataDir, legacyRoot, warn = () => {}, entries = USER_DIR_ENTRIES }) => {
|
||
|
|
if (path.resolve(dataDir) === path.resolve(legacyRoot)) return [];
|
||
|
|
const moved = [];
|
||
|
|
for (const entry of entries) {
|
||
|
|
const from = path.join(legacyRoot, entry);
|
||
|
|
const to = path.join(dataDir, entry);
|
||
|
|
if (await exists(fsPromises, to) || !(await exists(fsPromises, from))) continue;
|
||
|
|
try {
|
||
|
|
await fsPromises.mkdir(dataDir, { recursive: true });
|
||
|
|
await fsPromises.cp(from, to, { recursive: true, errorOnExist: true, force: false });
|
||
|
|
moved.push(entry);
|
||
|
|
} catch (error) {
|
||
|
|
await fsPromises.rm(to, { recursive: true, force: true }).catch(() => {});
|
||
|
|
warn(`Failed to copy ${from} to ${to}: ${error instanceof Error ? error.message : String(error)}`);
|
||
|
|
}
|
||
|
|
}
|
||
|
|
return moved;
|
||
|
|
};
|