mirror of
https://git.bits.team/Bits/mod-manager.git
synced 2024-11-21 13:38:21 -05:00
Require confirmation when uninstalling mods that are depended on
This commit is contained in:
parent
76f6c2c475
commit
f7be866698
13
package-lock.json
generated
13
package-lock.json
generated
@ -19,7 +19,8 @@
|
|||||||
"ora": "^6.1.2",
|
"ora": "^6.1.2",
|
||||||
"pino": "^8.3.1",
|
"pino": "^8.3.1",
|
||||||
"string-format": "^2.0.0",
|
"string-format": "^2.0.0",
|
||||||
"string-similarity-js": "^2.1.4"
|
"string-similarity-js": "^2.1.4",
|
||||||
|
"typescript-string-operations": "^1.4.1"
|
||||||
},
|
},
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
"@types/node": "^18.6.3",
|
"@types/node": "^18.6.3",
|
||||||
@ -835,6 +836,11 @@
|
|||||||
"node": ">=4.2.0"
|
"node": ">=4.2.0"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"node_modules/typescript-string-operations": {
|
||||||
|
"version": "1.4.1",
|
||||||
|
"resolved": "https://registry.npmjs.org/typescript-string-operations/-/typescript-string-operations-1.4.1.tgz",
|
||||||
|
"integrity": "sha512-c+q+Tb0hxeebohdT9KpGUAm5zwxhU8pHeNOeuLCGFMXKN0OrldoAxtufrGLR3xSPCXDA4A3IBCEdRNNscVqLQg=="
|
||||||
|
},
|
||||||
"node_modules/util-deprecate": {
|
"node_modules/util-deprecate": {
|
||||||
"version": "1.0.2",
|
"version": "1.0.2",
|
||||||
"resolved": "https://registry.npmjs.org/util-deprecate/-/util-deprecate-1.0.2.tgz",
|
"resolved": "https://registry.npmjs.org/util-deprecate/-/util-deprecate-1.0.2.tgz",
|
||||||
@ -1416,6 +1422,11 @@
|
|||||||
"integrity": "sha512-C0WQT0gezHuw6AdY1M2jxUO83Rjf0HP7Sk1DtXj6j1EwkQNZrHAg2XPWlq62oqEhYvONq5pkC2Y9oPljWToLmQ==",
|
"integrity": "sha512-C0WQT0gezHuw6AdY1M2jxUO83Rjf0HP7Sk1DtXj6j1EwkQNZrHAg2XPWlq62oqEhYvONq5pkC2Y9oPljWToLmQ==",
|
||||||
"dev": true
|
"dev": true
|
||||||
},
|
},
|
||||||
|
"typescript-string-operations": {
|
||||||
|
"version": "1.4.1",
|
||||||
|
"resolved": "https://registry.npmjs.org/typescript-string-operations/-/typescript-string-operations-1.4.1.tgz",
|
||||||
|
"integrity": "sha512-c+q+Tb0hxeebohdT9KpGUAm5zwxhU8pHeNOeuLCGFMXKN0OrldoAxtufrGLR3xSPCXDA4A3IBCEdRNNscVqLQg=="
|
||||||
|
},
|
||||||
"util-deprecate": {
|
"util-deprecate": {
|
||||||
"version": "1.0.2",
|
"version": "1.0.2",
|
||||||
"resolved": "https://registry.npmjs.org/util-deprecate/-/util-deprecate-1.0.2.tgz",
|
"resolved": "https://registry.npmjs.org/util-deprecate/-/util-deprecate-1.0.2.tgz",
|
||||||
|
@ -21,7 +21,8 @@
|
|||||||
"ora": "^6.1.2",
|
"ora": "^6.1.2",
|
||||||
"pino": "^8.3.1",
|
"pino": "^8.3.1",
|
||||||
"string-format": "^2.0.0",
|
"string-format": "^2.0.0",
|
||||||
"string-similarity-js": "^2.1.4"
|
"string-similarity-js": "^2.1.4",
|
||||||
|
"typescript-string-operations": "^1.4.1"
|
||||||
},
|
},
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
"@types/node": "^18.6.3",
|
"@types/node": "^18.6.3",
|
||||||
|
@ -9,9 +9,9 @@ export default class UninstallCommand implements Subcommand {
|
|||||||
.description("Uninstalls the provided mods")
|
.description("Uninstalls the provided mods")
|
||||||
.argument("<mods...>", "The mods to uninstall (as names or ids)")
|
.argument("<mods...>", "The mods to uninstall (as names or ids)")
|
||||||
.action((mods) => {
|
.action((mods) => {
|
||||||
ModManager.execute(() => {
|
ModManager.execute(async () => {
|
||||||
for (let mod of mods) {
|
for (let mod of mods) {
|
||||||
Mods.uninstall(mod);
|
await Mods.uninstall(mod);
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
|
@ -7,6 +7,9 @@ import Util from "../util/util.js";
|
|||||||
import ModManager from "../mod-manager.js";
|
import ModManager from "../mod-manager.js";
|
||||||
import MinecraftUtils from "../util/minecraft_utils.js";
|
import MinecraftUtils from "../util/minecraft_utils.js";
|
||||||
import MigrateError from "../errors/migrate_error.js";
|
import MigrateError from "../errors/migrate_error.js";
|
||||||
|
import inquirer from "inquirer";
|
||||||
|
import { StringBuilder } from 'typescript-string-operations';
|
||||||
|
import chalk from "chalk";
|
||||||
|
|
||||||
export default class Mods {
|
export default class Mods {
|
||||||
private static readonly MOD_SOURCES: Array<ModSource> = [];
|
private static readonly MOD_SOURCES: Array<ModSource> = [];
|
||||||
@ -97,26 +100,60 @@ export default class Mods {
|
|||||||
return !Util.isArrayEmpty(modsWithId)
|
return !Util.isArrayEmpty(modsWithId)
|
||||||
}
|
}
|
||||||
|
|
||||||
static uninstall(mod: string) {
|
private static getDependantMods(dependency: string) {
|
||||||
|
return this.getTrackedMods().filter(mod => mod.dependencies.includes(dependency))
|
||||||
|
}
|
||||||
|
|
||||||
|
static async uninstall(mod: string) {
|
||||||
// Find mod to uninstall
|
// Find mod to uninstall
|
||||||
|
const modToUninstall = this.findMod(mod);
|
||||||
|
|
||||||
const spinner = new PrintUtils.Spinner(`Uninstalling ${mod}...`)
|
const spinner = new PrintUtils.Spinner(`Uninstalling ${mod}...`)
|
||||||
spinner.start();
|
spinner.start();
|
||||||
|
|
||||||
const modToUninstall = this.findMod(mod);
|
// If a matching mod is found, remove it
|
||||||
// IF a matching mod is found, remove it
|
|
||||||
if (modToUninstall != undefined) {
|
if (modToUninstall != undefined) {
|
||||||
this.silentUninstall(modToUninstall);
|
|
||||||
|
|
||||||
for (let dependency of modToUninstall.dependencies) {
|
// Ensure the user wants to delete this mod
|
||||||
if (!this.isDependedOn(dependency)) {
|
let del = true;
|
||||||
const dependencyMod = this.findMod(dependency);
|
if (Mods.isDependedOn(modToUninstall.id)) {
|
||||||
if (dependencyMod != undefined) {
|
spinner.pause();
|
||||||
this.silentUninstall(dependencyMod)
|
|
||||||
}
|
const dependantMods = Mods.getDependantMods(modToUninstall.id);
|
||||||
}
|
const answer = await inquirer.prompt([{
|
||||||
|
type: "input",
|
||||||
|
name: "delete",
|
||||||
|
message: chalk.yellowBright(`${modToUninstall.name} is depended on by ${Mods.modListToSting(dependantMods)}. Are you sure you would like to uninstall? (y/n)`),
|
||||||
|
async validate(input: any): Promise<string | boolean> {
|
||||||
|
const lowerInput = input.toLowerCase();
|
||||||
|
const valid = lowerInput === "y" || lowerInput === "n" ;
|
||||||
|
if (!valid) {
|
||||||
|
return "Please answer either y or n"
|
||||||
|
}
|
||||||
|
return valid
|
||||||
|
},
|
||||||
|
}])
|
||||||
|
del = Util.getBoolFromYesNo(answer.delete);
|
||||||
|
}
|
||||||
|
|
||||||
|
// If we are deleting this mod, uninstall it
|
||||||
|
if (del) {
|
||||||
|
spinner.start()
|
||||||
|
this.silentUninstall(modToUninstall);
|
||||||
|
|
||||||
|
// Remove any left over dependencies that are not depended on by any other mod
|
||||||
|
for (let dependency of modToUninstall.dependencies) {
|
||||||
|
if (!this.isDependedOn(dependency)) {
|
||||||
|
const dependencyMod = this.findMod(dependency);
|
||||||
|
if (dependencyMod != undefined) {
|
||||||
|
this.silentUninstall(dependencyMod)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
spinner.succeed(`${modToUninstall.name} successfully uninstalled!`)
|
||||||
}
|
}
|
||||||
|
|
||||||
spinner.succeed(`${modToUninstall.name} successfully uninstalled!`)
|
|
||||||
} else {
|
} else {
|
||||||
spinner.error(`${mod} was not found.`)
|
spinner.error(`${mod} was not found.`)
|
||||||
}
|
}
|
||||||
@ -366,13 +403,14 @@ export default class Mods {
|
|||||||
}
|
}
|
||||||
|
|
||||||
private static isDependedOn(dependency: string) {
|
private static isDependedOn(dependency: string) {
|
||||||
const trackedMods = this.getTrackedMods();
|
return Mods.getDependantMods(dependency).length != 0
|
||||||
|
}
|
||||||
|
|
||||||
for (let trackedMod of trackedMods) {
|
private static modListToSting(dependantMods: TrackedMod[]) {
|
||||||
if (trackedMod.dependencies.includes(dependency)) {
|
const builder = new StringBuilder();
|
||||||
return true;
|
for (let dependantMod of dependantMods) {
|
||||||
}
|
builder.Append(dependantMod.name)
|
||||||
}
|
}
|
||||||
return false;
|
return builder.ToString();
|
||||||
}
|
}
|
||||||
}
|
}
|
@ -24,6 +24,10 @@ export default class PrintUtils {
|
|||||||
this.spinner.stopAndPersist();
|
this.spinner.stopAndPersist();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public pause() {
|
||||||
|
this.spinner.stop();
|
||||||
|
}
|
||||||
|
|
||||||
public error(print: string | Error) {
|
public error(print: string | Error) {
|
||||||
if (print instanceof Error) {
|
if (print instanceof Error) {
|
||||||
this.spinner.fail(print.message)
|
this.spinner.fail(print.message)
|
||||||
|
@ -21,4 +21,14 @@ export default class Util {
|
|||||||
compare = compare.toLowerCase();
|
compare = compare.toLowerCase();
|
||||||
return stringSimilarity(master, compare) >= this.SIMILARITY_THRESHOLD;
|
return stringSimilarity(master, compare) >= this.SIMILARITY_THRESHOLD;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static getBoolFromYesNo(answer: string) {
|
||||||
|
if (answer.toLowerCase() === "y") {
|
||||||
|
return true;
|
||||||
|
} else if (answer.toLowerCase() === "n") {
|
||||||
|
return false
|
||||||
|
} else {
|
||||||
|
throw new Error("Invalid answer to get a boolean value from")
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user