From 765999eb8a16f4c52e2eb41f8f5228ae875ff58d Mon Sep 17 00:00:00 2001 From: SrGooglo Date: Mon, 17 Jun 2024 03:46:28 +0200 Subject: [PATCH] improve install cancel --- packages/core/package.json | 2 +- packages/core/src/generic_steps/http.js | 21 +++++--- packages/core/src/generic_steps/index.js | 8 ++- packages/core/src/handlers/cancelInstall.js | 40 ++++++++++++++ packages/core/src/handlers/install.js | 53 ++++++++++++++++++- packages/core/src/handlers/reinstall.js | 35 ++++++++++++ packages/core/src/helpers/downloadHttpFile.js | 3 +- packages/core/src/index.js | 9 ++++ packages/core/src/manifest/libs/open/index.js | 3 +- packages/gui/package.json | 2 +- packages/gui/src/main/classes/CoreAdapter.js | 6 +++ .../src/components/PackageItem/index.jsx | 17 +++++- .../src/renderer/src/pages/pkg/[pkg_id].jsx | 2 +- 13 files changed, 183 insertions(+), 18 deletions(-) create mode 100644 packages/core/src/handlers/cancelInstall.js create mode 100644 packages/core/src/handlers/reinstall.js diff --git a/packages/core/package.json b/packages/core/package.json index d467043..8ed14e6 100644 --- a/packages/core/package.json +++ b/packages/core/package.json @@ -1,6 +1,6 @@ { "name": "@ragestudio/relic-core", - "version": "0.17.7", + "version": "0.18.0", "license": "MIT", "author": "RageStudio", "description": "RageStudio Relic, yet another package manager.", diff --git a/packages/core/src/generic_steps/http.js b/packages/core/src/generic_steps/http.js index 57f614c..f2c2ca0 100644 --- a/packages/core/src/generic_steps/http.js +++ b/packages/core/src/generic_steps/http.js @@ -6,7 +6,7 @@ import downloadHttpFile from "../helpers/downloadHttpFile" import parseStringVars from "../utils/parseStringVars" import extractFile from "../utils/extractFile" -export default async (pkg, step, logger) => { +export default async (pkg, step, logger, abortController) => { if (!step.path) { step.path = `./${path.basename(step.url)}` } @@ -28,13 +28,18 @@ export default async (pkg, step, logger) => { fs.mkdirSync(path.resolve(_path, ".."), { recursive: true }) - await downloadHttpFile(step.url, _path, (progress) => { - global._relic_eventBus.emit(`pkg:update:state`, { - id: pkg.id, - use_id_only: true, - status_text: `Downloaded ${progress.transferredString} / ${progress.totalString} | ${progress.speedString}/s`, - }) - }) + await downloadHttpFile( + step.url, + _path, + (progress) => { + global._relic_eventBus.emit(`pkg:update:state`, { + id: pkg.id, + use_id_only: true, + status_text: `Downloaded ${progress.transferredString} / ${progress.totalString} | ${progress.speedString}/s`, + }) + }, + abortController + ) logger.info(`Downloaded finished.`) diff --git a/packages/core/src/generic_steps/index.js b/packages/core/src/generic_steps/index.js index 96e2017..76a0c82 100644 --- a/packages/core/src/generic_steps/index.js +++ b/packages/core/src/generic_steps/index.js @@ -19,7 +19,7 @@ const StepsOrders = [ "http_file", ] -export default async function processGenericSteps(pkg, steps, logger = Logger) { +export default async function processGenericSteps(pkg, steps, logger = Logger, abortController) { logger.info(`Processing generic steps...`) if (!Array.isArray(steps)) { @@ -37,11 +37,15 @@ export default async function processGenericSteps(pkg, steps, logger = Logger) { for await (let step of steps) { step.type = step.type.toLowerCase() + if (abortController.signal.aborted) { + return false + } + if (!InstallationStepsMethods[step.type]) { throw new Error(`Unknown step: ${step.type}`) } - await InstallationStepsMethods[step.type](pkg, step, logger) + await InstallationStepsMethods[step.type](pkg, step, logger, abortController) } return pkg diff --git a/packages/core/src/handlers/cancelInstall.js b/packages/core/src/handlers/cancelInstall.js new file mode 100644 index 0000000..489b8eb --- /dev/null +++ b/packages/core/src/handlers/cancelInstall.js @@ -0,0 +1,40 @@ +import Logger from "../logger" + +import DB from "../db" + +import UninstallHandler from "./uninstall" + +const BaseLog = Logger.child({ service: "CANCEL_INSTALL" }) + +export default async function reinstall(pkg_id) { + try { + const pkg = await DB.getPackages(pkg_id) + + if (!pkg) { + BaseLog.info(`Package not found [${pkg_id}]`) + return null + } + + const task = globalThis.relic_core.tasks.find((task) => task.id === pkg_id) + + if (task) { + BaseLog.warn(`Task not found [${pkg_id}]`) + await task.abortController.abort() + } + + await UninstallHandler(pkg_id) + + return pkg + } catch (error) { + global._relic_eventBus.emit(`pkg:error`, { + event: "cancel_install", + id: pkg_id, + error + }) + + BaseLog.error(`Failed to cancel installation package [${pkg_id}]`, error) + BaseLog.error(error.stack) + + return null + } +} \ No newline at end of file diff --git a/packages/core/src/handlers/install.js b/packages/core/src/handlers/install.js index 0ff7489..84efba6 100644 --- a/packages/core/src/handlers/install.js +++ b/packages/core/src/handlers/install.js @@ -12,6 +12,7 @@ const BaseLog = Logger.child({ service: "INSTALLER" }) export default async function install(manifest) { let id = null + let abortController = new AbortController() try { BaseLog.info(`Invoking new installation...`) @@ -23,10 +24,20 @@ export default async function install(manifest) { id = manifest.constructor.id + globalThis.relic_core.tasks.push({ + type: "install", + id: id, + abortController: abortController, + }) + const Log = BaseLog.child({ service: `INSTALLER|${id}` }) Log.info(`Creating install path [${manifest.install_path}]`) + if (abortController.signal.aborted) { + return false + } + if (fs.existsSync(manifest.install_path)) { Log.info(`Package already exists, removing...`) await fs.rmSync(manifest.install_path, { recursive: true }) @@ -36,12 +47,20 @@ export default async function install(manifest) { Log.info(`Initializing manifest...`) + if (abortController.signal.aborted) { + return false + } + if (typeof manifest.initialize === "function") { await manifest.initialize() } Log.info(`Appending to db...`) + if (abortController.signal.aborted) { + return false + } + let pkg = DB.defaultPackageState({ ...manifest.constructor, id: id, @@ -60,6 +79,10 @@ export default async function install(manifest) { global._relic_eventBus.emit("pkg:new", pkg) + if (abortController.signal.aborted) { + return false + } + if (manifest.configuration) { Log.info(`Applying default config to package...`) @@ -70,6 +93,10 @@ export default async function install(manifest) { }, {}) } + if (abortController.signal.aborted) { + return false + } + if (typeof manifest.beforeInstall === "function") { Log.info(`Executing beforeInstall hook...`) @@ -81,6 +108,10 @@ export default async function install(manifest) { await manifest.beforeInstall(pkg) } + if (abortController.signal.aborted) { + return false + } + if (Array.isArray(manifest.installSteps)) { Log.info(`Executing generic install steps...`) @@ -89,7 +120,11 @@ export default async function install(manifest) { status_text: `Performing generic install steps...`, }) - await GenericSteps(pkg, manifest.installSteps, Log) + await GenericSteps(pkg, manifest.installSteps, Log, abortController) + } + + if (abortController.signal.aborted) { + return false } if (typeof manifest.afterInstall === "function") { @@ -112,6 +147,10 @@ export default async function install(manifest) { const finalPath = `${manifest.install_path}/.rmanifest` + if (abortController.signal.aborted) { + return false + } + if (fs.existsSync(finalPath)) { await fs.promises.unlink(finalPath) } @@ -129,6 +168,10 @@ export default async function install(manifest) { await DB.writePackage(pkg) + if (abortController.signal.aborted) { + return false + } + if (manifest.patches) { const defaultPatches = manifest.patches.filter((patch) => patch.default) @@ -148,8 +191,14 @@ export default async function install(manifest) { pkg.last_status = "installed" + if (abortController.signal.aborted) { + return false + } + await DB.writePackage(pkg) + globalThis.relic_core.tasks.filter((task) => task.id !== id) + global._relic_eventBus.emit(`pkg:update:state`, { ...pkg, id: pkg.id, @@ -175,6 +224,8 @@ export default async function install(manifest) { status_text: `Installation failed`, }) + globalThis.relic_core.tasks.filter((task) => task.id !== id) + BaseLog.error(`Error during installation of package [${id}] >`, error) BaseLog.error(error.stack) diff --git a/packages/core/src/handlers/reinstall.js b/packages/core/src/handlers/reinstall.js new file mode 100644 index 0000000..50428f3 --- /dev/null +++ b/packages/core/src/handlers/reinstall.js @@ -0,0 +1,35 @@ +import Logger from "../logger" + +import DB from "../db" + +import UninstallHandler from "./uninstall" +import InstallHandler from "./install" + +const BaseLog = Logger.child({ service: "REINSTALL" }) + +export default async function reinstall(pkg_id) { + try { + const pkg = await DB.getPackages(pkg_id) + + if (!pkg) { + BaseLog.info(`Package not found [${pkg_id}]`) + return null + } + + await UninstallHandler(pkg_id) + await InstallHandler(pkg.remote_manifest) + + return pkg + } catch (error) { + global._relic_eventBus.emit(`pkg:error`, { + event: "reinstall", + id: pkg_id, + error + }) + + BaseLog.error(`Failed to reinstall package [${pkg_id}]`, error) + BaseLog.error(error.stack) + + return null + } +} \ No newline at end of file diff --git a/packages/core/src/helpers/downloadHttpFile.js b/packages/core/src/helpers/downloadHttpFile.js index d347b81..db3242c 100644 --- a/packages/core/src/helpers/downloadHttpFile.js +++ b/packages/core/src/helpers/downloadHttpFile.js @@ -9,7 +9,7 @@ function convertSize(size) { })}B` } -export default async (url, destination, progressCallback) => { +export default async (url, destination, progressCallback, abortController) => { const progressBar = new cliProgress.SingleBar({ format: "[{bar}] {percentage}% | {total_formatted} | {speed}/s | {eta_formatted}", barCompleteChar: "\u2588", @@ -19,6 +19,7 @@ export default async (url, destination, progressCallback) => { const { data: remoteStream, headers } = await axios.get(url, { responseType: "stream", + signal: abortController?.signal, }) const localStream = fs.createWriteStream(destination) diff --git a/packages/core/src/index.js b/packages/core/src/index.js index 37d1306..f8bb2de 100644 --- a/packages/core/src/index.js +++ b/packages/core/src/index.js @@ -12,6 +12,8 @@ import DB from "./db" import PackageInstall from "./handlers/install" import PackageExecute from "./handlers/execute" import PackageUninstall from "./handlers/uninstall" +import PackageReinstall from "./handlers/reinstall" +import PackageCancelInstall from "./handlers/cancelInstall" import PackageUpdate from "./handlers/update" import PackageApply from "./handlers/apply" import PackageList from "./handlers/list" @@ -33,8 +35,13 @@ export default class RelicCore { db = DB async initialize() { + globalThis.relic_core = { + tasks: [], + } + await DB.initialize() + onExit(this.onExit) } @@ -52,6 +59,8 @@ export default class RelicCore { install: PackageInstall, execute: PackageExecute, uninstall: PackageUninstall, + reinstall: PackageReinstall, + cancelInstall: PackageCancelInstall, update: PackageUpdate, apply: PackageApply, list: PackageList, diff --git a/packages/core/src/manifest/libs/open/index.js b/packages/core/src/manifest/libs/open/index.js index d696826..733eb2e 100644 --- a/packages/core/src/manifest/libs/open/index.js +++ b/packages/core/src/manifest/libs/open/index.js @@ -6,8 +6,7 @@ const Log = Logger.child({ service: "OPEN-LIB" }) export default { spawn: async (...args) => { - Log.info("Open spawned with args >") - console.log(...args) + Log.info("Spawning with args >", args) return await open(...args) }, diff --git a/packages/gui/package.json b/packages/gui/package.json index 3d58068..244a38f 100644 --- a/packages/gui/package.json +++ b/packages/gui/package.json @@ -1,6 +1,6 @@ { "name": "@ragestudio/relic-gui", - "version": "0.17.6", + "version": "0.18.0", "description": "RageStudio Relic, yet another package manager.", "main": "./out/main/index.js", "author": "RageStudio", diff --git a/packages/gui/src/main/classes/CoreAdapter.js b/packages/gui/src/main/classes/CoreAdapter.js index a2313b4..29fb206 100644 --- a/packages/gui/src/main/classes/CoreAdapter.js +++ b/packages/gui/src/main/classes/CoreAdapter.js @@ -44,6 +44,12 @@ export default class CoreAdapter { "pkg:uninstall": async (event, pkg_id) => { return await this.core.package.uninstall(pkg_id) }, + "pkg:reinstall": async (event, pkg_id) => { + return await this.core.package.reinstall(pkg_id) + }, + "pkg:cancel_install": async (event, pkg_id) => { + return await this.core.package.cancelInstall(pkg_id) + }, "pkg:execute": async (event, pkg_id, { force = false } = {}) => { // check for updates first if (!force) { diff --git a/packages/gui/src/renderer/src/components/PackageItem/index.jsx b/packages/gui/src/renderer/src/components/PackageItem/index.jsx index 3986322..fb2d7e9 100644 --- a/packages/gui/src/renderer/src/components/PackageItem/index.jsx +++ b/packages/gui/src/renderer/src/components/PackageItem/index.jsx @@ -56,7 +56,13 @@ const PackageItem = (props) => { } const onClickCancelInstall = () => { - ipc.exec("pkg:cancel_install", manifest.id) + antd.Modal.confirm({ + title: "Uninstall", + content: `Are you sure you want to cancel the installation? The package will not be installed and all data will be lost.`, + onOk: () => { + ipc.exec("pkg:cancel_install", manifest.id) + }, + }) } const onClickRetryInstall = () => { @@ -162,6 +168,15 @@ const PackageItem = (props) => {
+ { + isInstalling && + Cancel + + } + { isFailed && <> { app.location.push("/") } - ipc.exec("pkg:install", manifest) + ipc.exec("pkg:reinstall", manifest.id) }, }) }