mirror of
https://github.com/ragestudio/relic.git
synced 2025-06-09 02:24:18 +00:00
improve install cancel
This commit is contained in:
parent
881d018bfc
commit
765999eb8a
@ -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.",
|
||||
|
@ -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.`)
|
||||
|
||||
|
@ -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
|
||||
|
40
packages/core/src/handlers/cancelInstall.js
Normal file
40
packages/core/src/handlers/cancelInstall.js
Normal file
@ -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
|
||||
}
|
||||
}
|
@ -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)
|
||||
|
||||
|
35
packages/core/src/handlers/reinstall.js
Normal file
35
packages/core/src/handlers/reinstall.js
Normal file
@ -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
|
||||
}
|
||||
}
|
@ -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)
|
||||
|
@ -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,
|
||||
|
@ -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)
|
||||
},
|
||||
|
@ -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",
|
||||
|
@ -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) {
|
||||
|
@ -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) => {
|
||||
</div>
|
||||
|
||||
<div className="installation_item_actions">
|
||||
{
|
||||
isInstalling && <antd.Button
|
||||
type="primary"
|
||||
onClick={onClickCancelInstall}
|
||||
>
|
||||
Cancel
|
||||
</antd.Button>
|
||||
}
|
||||
|
||||
{
|
||||
isFailed && <>
|
||||
<antd.Button
|
||||
|
@ -106,7 +106,7 @@ const PackageOptions = (props) => {
|
||||
app.location.push("/")
|
||||
}
|
||||
|
||||
ipc.exec("pkg:install", manifest)
|
||||
ipc.exec("pkg:reinstall", manifest.id)
|
||||
},
|
||||
})
|
||||
}
|
||||
|
Loading…
x
Reference in New Issue
Block a user