Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: reset --reinstall --hard #777

Merged
merged 4 commits into from
Jan 31, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
77 changes: 73 additions & 4 deletions src/commands/plugins/reset.ts
Original file line number Diff line number Diff line change
@@ -1,20 +1,89 @@
import {Command} from '@oclif/core'
/* eslint-disable no-await-in-loop */
import {Command, Flags} from '@oclif/core'
import chalk from 'chalk'
import {rm} from 'node:fs/promises'
import {join} from 'node:path'

import Plugins from '../../plugins.js'

export default class Reset extends Command {
static flags = {
hard: Flags.boolean({
summary: 'Delete node_modules and package manager related files in addition to uninstalling plugins.',
}),
reinstall: Flags.boolean({
summary: 'Reinstall all plugins after uninstalling.',
}),
}

static summary = 'Remove all user-installed and linked plugins.'

async run(): Promise<void> {
const {flags} = await this.parse(Reset)
const plugins = new Plugins(this.config)
const userPlugins = await plugins.list()

this.log(`Uninstalling ${userPlugins.length} plugin${userPlugins.length === 0 ? '' : 's'}`)
this.log(`Found ${userPlugins.length} plugin${userPlugins.length === 0 ? '' : 's'}:`)
for (const plugin of userPlugins) {
this.log(`• ${plugin.name} ${chalk.dim(`(${plugin.type})`)}`)
this.log(
`- ${plugin.name} ${chalk.dim(this.config.plugins.get(plugin.name)?.version)} ${chalk.dim(`(${plugin.type})`)}`,
)
}

await Promise.all(userPlugins.map(async (plugin) => plugins.uninstall(plugin.name)))
if (flags.hard) {
const filesToDelete = [
join(this.config.dataDir, 'node_modules'),
join(this.config.dataDir, 'package.json'),
join(this.config.dataDir, 'yarn.lock'),
join(this.config.dataDir, 'package-lock.json'),
]

this.log('✅ Removed the following files:')
for (const file of filesToDelete) {
this.log(`- ${file}`)
}

await Promise.all(filesToDelete.map((file) => rm(file, {force: true, recursive: true})))

for (const plugin of userPlugins) {
this.log(`✅ ${plugin.type === 'link' ? 'Unlinked' : 'Uninstalled'} ${plugin.name}`)
}
} else {
// These need to run sequentially so as to avoid write conflicts to the package.json
for (const plugin of userPlugins) {
try {
await plugins.uninstall(plugin.name)
this.log(`✅ ${plugin.type === 'link' ? 'Unlinked' : 'Uninstalled'} ${plugin.name}`)
} catch {
this.warn(`Failed to uninstall ${plugin.name}`)
}
}
}

if (flags.reinstall) {
this.log('Reinstall flag passed:')
// These need to run sequentially so as to avoid write conflicts to the package.json
for (const plugin of userPlugins) {
if (plugin.type === 'link') {
try {
const newPlugin = await plugins.link(plugin.root, {install: false})
const newVersion = chalk.dim(`-> ${newPlugin.version}`)
this.log(`✅ Relinked ${plugin.name} ${newVersion}`)
} catch {
this.warn(`Failed to relink ${plugin.name}`)
}
}

if (plugin.type === 'user') {
try {
const newPlugin = await plugins.install(plugin.name, {tag: plugin.tag})
const newVersion = chalk.dim(`-> ${newPlugin.version}`)
this.log(`✅ Reinstalled ${plugin.name}@${plugin.tag} ${newVersion}`)
} catch {
this.warn(`Failed to reinstall ${plugin.name}`)
}
}
}
}
}
}
6 changes: 4 additions & 2 deletions src/plugins.ts
Original file line number Diff line number Diff line change
Expand Up @@ -158,14 +158,16 @@ export default class Plugins {
}
}

async link(p: string, {install}: {install: boolean}): Promise<void> {
async link(p: string, {install}: {install: boolean}): Promise<Interfaces.Config> {
const c = await Config.load(resolve(p))
ux.action.start(`${this.config.name}: linking plugin ${c.name}`)

this.isValidPlugin(c)

// refresh will cause yarn.lock to install dependencies, including devDeps
if (install) await this.refresh({all: false, prod: false}, c.root)
await this.add({name: c.name, root: c.root, type: 'link'})

return c
}

async list(): Promise<(Interfaces.PJSON.PluginTypes.Link | Interfaces.PJSON.PluginTypes.User)[]> {
Expand Down
Loading