mirror of
https://github.com/pnpm/pnpm.git
synced 2026-05-11 09:28:24 -04:00
171 lines
5.2 KiB
TypeScript
171 lines
5.2 KiB
TypeScript
import fs from 'fs'
|
|
import path from 'path'
|
|
import assertStore from '@pnpm/assert-store'
|
|
import { Lockfile } from '@pnpm/lockfile-file'
|
|
import { store } from '@pnpm/plugin-commands-store'
|
|
import prepare from '@pnpm/prepare'
|
|
import { REGISTRY_MOCK_PORT } from '@pnpm/registry-mock'
|
|
import rimraf from '@zkochan/rimraf'
|
|
import execa from 'execa'
|
|
import isEmpty from 'ramda/src/isEmpty'
|
|
import sinon from 'sinon'
|
|
import ssri from 'ssri'
|
|
|
|
const STORE_VERSION = 'v3'
|
|
const REGISTRY = `http://localhost:${REGISTRY_MOCK_PORT}/`
|
|
const pnpmBin = path.join(__dirname, '../../pnpm/bin/pnpm.cjs')
|
|
|
|
test('remove unreferenced packages', async () => {
|
|
const project = prepare()
|
|
const cacheDir = path.resolve('cache')
|
|
const storeDir = path.resolve('store')
|
|
|
|
await execa('node', [pnpmBin, 'add', 'is-negative@2.1.0', '--store-dir', storeDir, '--registry', REGISTRY])
|
|
await execa('node', [pnpmBin, 'remove', 'is-negative', '--store-dir', storeDir, '--config.modules-cache-max-age=0'], { env: { npm_config_registry: REGISTRY } })
|
|
|
|
await project.storeHas('is-negative', '2.1.0')
|
|
|
|
const reporter = sinon.spy()
|
|
await store.handler({
|
|
cacheDir,
|
|
dir: process.cwd(),
|
|
rawConfig: {
|
|
registry: REGISTRY,
|
|
},
|
|
registries: { default: REGISTRY },
|
|
reporter,
|
|
storeDir,
|
|
}, ['prune'])
|
|
|
|
expect(reporter.calledWithMatch({
|
|
level: 'info',
|
|
message: 'Removed 1 package',
|
|
})).toBeTruthy()
|
|
|
|
await project.storeHasNot('is-negative', '2.1.0')
|
|
|
|
reporter.resetHistory()
|
|
await store.handler({
|
|
cacheDir,
|
|
dir: process.cwd(),
|
|
rawConfig: {
|
|
registry: REGISTRY,
|
|
},
|
|
registries: { default: REGISTRY },
|
|
reporter,
|
|
storeDir,
|
|
}, ['prune'])
|
|
|
|
expect(reporter.calledWithMatch({
|
|
level: 'info',
|
|
message: 'Removed 1 package',
|
|
})).toBeFalsy()
|
|
})
|
|
|
|
test.skip('remove packages that are used by project that no longer exist', async () => {
|
|
prepare()
|
|
const cacheDir = path.resolve('cache')
|
|
const storeDir = path.resolve('store', STORE_VERSION)
|
|
const { cafsHas, cafsHasNot } = assertStore(storeDir)
|
|
|
|
await execa('node', [pnpmBin, 'add', 'is-negative@2.1.0', '--store-dir', storeDir, '--registry', REGISTRY])
|
|
|
|
await rimraf('node_modules')
|
|
|
|
await cafsHas(ssri.fromHex('f0d86377aa15a64c34961f38ac2a9be2b40a1187', 'sha1').toString())
|
|
|
|
const reporter = sinon.spy()
|
|
await store.handler({
|
|
cacheDir,
|
|
dir: process.cwd(),
|
|
rawConfig: {
|
|
registry: REGISTRY,
|
|
},
|
|
registries: { default: REGISTRY },
|
|
reporter,
|
|
storeDir,
|
|
}, ['prune'])
|
|
|
|
expect(reporter.calledWithMatch({
|
|
level: 'info',
|
|
message: `- localhost+${REGISTRY_MOCK_PORT}/is-negative/2.1.0`,
|
|
})).toBeTruthy()
|
|
|
|
await cafsHasNot(ssri.fromHex('f0d86377aa15a64c34961f38ac2a9be2b40a1187', 'sha1').toString())
|
|
})
|
|
|
|
test('keep dependencies used by others', async () => {
|
|
const project = prepare()
|
|
const cacheDir = path.resolve('cache')
|
|
const storeDir = path.resolve('store')
|
|
await execa('node', [pnpmBin, 'add', 'camelcase-keys@3.0.0', '--store-dir', storeDir, '--registry', REGISTRY])
|
|
await execa('node', [pnpmBin, 'add', 'hastscript@3.0.0', '--save-dev', '--store-dir', storeDir, '--registry', REGISTRY])
|
|
await execa('node', [pnpmBin, 'remove', 'camelcase-keys', '--store-dir', storeDir], { env: { npm_config_registry: REGISTRY } })
|
|
|
|
await project.storeHas('camelcase-keys', '3.0.0')
|
|
await project.hasNot('camelcase-keys')
|
|
|
|
await project.storeHas('camelcase', '3.0.0')
|
|
|
|
await project.storeHas('map-obj', '1.0.1')
|
|
await project.hasNot('map-obj')
|
|
|
|
// all dependencies are marked as dev
|
|
const lockfile = await project.readLockfile() as Lockfile
|
|
expect(isEmpty(lockfile.packages)).toBeFalsy()
|
|
|
|
Object.entries(lockfile.packages ?? {}).forEach(([depPath, dep]) => expect(dep.dev).toBeTruthy())
|
|
|
|
await store.handler({
|
|
cacheDir,
|
|
dir: process.cwd(),
|
|
rawConfig: {
|
|
registry: REGISTRY,
|
|
},
|
|
registries: { default: REGISTRY },
|
|
storeDir,
|
|
}, ['prune'])
|
|
|
|
await project.storeHasNot('camelcase-keys', '3.0.0')
|
|
await project.storeHasNot('map-obj', '1.0.1')
|
|
await project.storeHas('camelcase', '3.0.0')
|
|
})
|
|
|
|
test('keep dependency used by package', async () => {
|
|
const project = prepare()
|
|
const cacheDir = path.resolve('cache')
|
|
const storeDir = path.resolve('store')
|
|
await execa('node', [pnpmBin, 'add', 'is-not-positive@1.0.0', 'is-positive@3.1.0', '--store-dir', storeDir, '--registry', REGISTRY])
|
|
await execa('node', [pnpmBin, 'remove', 'is-not-positive', '--store-dir', storeDir], { env: { npm_config_registry: REGISTRY } })
|
|
|
|
await store.handler({
|
|
cacheDir,
|
|
dir: process.cwd(),
|
|
rawConfig: {
|
|
registry: REGISTRY,
|
|
},
|
|
registries: { default: REGISTRY },
|
|
storeDir,
|
|
}, ['prune'])
|
|
|
|
await project.storeHas('is-positive', '3.1.0')
|
|
})
|
|
|
|
test('prune will skip scanning non-directory in storeDir', async () => {
|
|
prepare()
|
|
const cacheDir = path.resolve('cache')
|
|
const storeDir = path.resolve('store')
|
|
await execa('node', [pnpmBin, 'add', 'is-not-positive@1.0.0', 'is-positive@3.1.0', '--store-dir', storeDir, '--registry', REGISTRY])
|
|
fs.writeFileSync(path.join(storeDir, STORE_VERSION, 'files/.DS_store'), 'foobar')
|
|
|
|
await store.handler({
|
|
cacheDir,
|
|
dir: process.cwd(),
|
|
rawConfig: {
|
|
registry: REGISTRY,
|
|
},
|
|
registries: { default: REGISTRY },
|
|
storeDir,
|
|
}, ['prune'])
|
|
})
|