Skip to content

Commit

Permalink
feat: lock project during install/uninstall
Browse files Browse the repository at this point in the history
  • Loading branch information
zkochan committed May 25, 2017
1 parent 90806ec commit d44a333
Show file tree
Hide file tree
Showing 3 changed files with 84 additions and 76 deletions.
128 changes: 66 additions & 62 deletions src/api/install.ts
Expand Up @@ -55,43 +55,45 @@ export type InstallContext = {

export async function install (maybeOpts?: PnpmOptions) {
const opts = extendOptions(maybeOpts)
const installType = 'general'
const ctx = await getContext(opts, installType)
const installCtx = await createInstallCmd(opts, ctx.shrinkwrap, ctx.skipped)
return lock(opts.prefix, async () => {
const installType = 'general'
const ctx = await getContext(opts, installType)
const installCtx = await createInstallCmd(opts, ctx.shrinkwrap, ctx.skipped)

if (!ctx.pkg) throw new Error('No package.json found')
if (!ctx.pkg) throw new Error('No package.json found')

const specs = specsToInstallFromPackage(ctx.pkg, {
prefix: opts.prefix,
})
const specs = specsToInstallFromPackage(ctx.pkg, {
prefix: opts.prefix,
})

specs.forEach(spec => {
if (ctx.shrinkwrap.specifiers && ctx.shrinkwrap.specifiers[spec.name] !== spec.rawSpec) {
delete ctx.shrinkwrap.dependencies[spec.name]
}
})
specs.forEach(spec => {
if (ctx.shrinkwrap.specifiers && ctx.shrinkwrap.specifiers[spec.name] !== spec.rawSpec) {
delete ctx.shrinkwrap.dependencies[spec.name]
}
})

if (opts.lock === false) {
return run()
}
if (opts.lock === false) {
return run()
}

return lock(ctx.storePath, run, {stale: opts.lockStaleDuration})
return lock(ctx.storePath, run, {stale: opts.lockStaleDuration})

async function run () {
const scripts = !opts.ignoreScripts && ctx.pkg && ctx.pkg.scripts || {}
if (scripts['preinstall']) {
npmRun('preinstall', ctx.root, opts.userAgent)
}
async function run () {
const scripts = !opts.ignoreScripts && ctx.pkg && ctx.pkg.scripts || {}
if (scripts['preinstall']) {
npmRun('preinstall', ctx.root, opts.userAgent)
}

await installInContext(installType, specs, [], ctx, installCtx, opts)
await installInContext(installType, specs, [], ctx, installCtx, opts)

if (scripts['postinstall']) {
npmRun('postinstall', ctx.root, opts.userAgent)
}
if (scripts['prepublish']) {
npmRun('prepublish', ctx.root, opts.userAgent)
if (scripts['postinstall']) {
npmRun('postinstall', ctx.root, opts.userAgent)
}
if (scripts['prepublish']) {
npmRun('prepublish', ctx.root, opts.userAgent)
}
}
}
}, {stale: opts.lockStaleDuration})
}

function specsToInstallFromPackage(
Expand Down Expand Up @@ -125,45 +127,47 @@ function depsFromPackage (pkg: Package): Dependencies {
*/
export async function installPkgs (fuzzyDeps: string[] | Dependencies, maybeOpts?: PnpmOptions) {
const opts = extendOptions(maybeOpts)
let packagesToInstall = Array.isArray(fuzzyDeps)
? argsToSpecs(fuzzyDeps, {
defaultTag: opts.tag,
where: opts.prefix,
dev: opts.saveDev,
optional: opts.saveOptional,
})
: similarDepsToSpecs(fuzzyDeps, {
where: opts.prefix,
dev: opts.saveDev,
optional: opts.saveOptional,
})
return lock(opts.prefix, async () => {
let packagesToInstall = Array.isArray(fuzzyDeps)
? argsToSpecs(fuzzyDeps, {
defaultTag: opts.tag,
where: opts.prefix,
dev: opts.saveDev,
optional: opts.saveOptional,
})
: similarDepsToSpecs(fuzzyDeps, {
where: opts.prefix,
dev: opts.saveDev,
optional: opts.saveOptional,
})

if (!Object.keys(packagesToInstall).length) {
throw new Error('At least one package has to be installed')
}
const installType = 'named'
const ctx = await getContext(opts, installType)
const installCtx = await createInstallCmd(opts, ctx.shrinkwrap, ctx.skipped)
if (!Object.keys(packagesToInstall).length) {
throw new Error('At least one package has to be installed')
}
const installType = 'named'
const ctx = await getContext(opts, installType)
const installCtx = await createInstallCmd(opts, ctx.shrinkwrap, ctx.skipped)

packagesToInstall.forEach(spec => {
delete ctx.shrinkwrap.dependencies[spec.name]
})
packagesToInstall.forEach(spec => {
delete ctx.shrinkwrap.dependencies[spec.name]
})

if (opts.lock === false) {
return run()
}
if (opts.lock === false) {
return run()
}

return lock(ctx.storePath, run, {stale: opts.lockStaleDuration})
return lock(ctx.storePath, run, {stale: opts.lockStaleDuration})

function run () {
return installInContext(
installType,
packagesToInstall,
packagesToInstall.map(spec => spec.name),
ctx,
installCtx,
opts)
}
function run () {
return installInContext(
installType,
packagesToInstall,
packagesToInstall.map(spec => spec.name),
ctx,
installCtx,
opts)
}
}, {stale: opts.lockStaleDuration})
}

function argsToSpecs (
Expand Down
5 changes: 4 additions & 1 deletion src/api/lock.ts
@@ -1,6 +1,7 @@
import logger from 'pnpm-logger'
import path = require('path')
import lockfile = require('proper-lockfile')
import mkdirp = require('mkdirp-promise')

async function delay(ms: number) {
return new Promise(resolve => setTimeout(resolve, ms))
Expand Down Expand Up @@ -46,7 +47,9 @@ export default async function withLock<T> (
fn: () => Promise<T>,
opts: {stale: number}
): Promise<T> {
const lockFilename: string = path.resolve(storePath, 'lock')
storePath = path.resolve(storePath)
await mkdirp(storePath)
const lockFilename = path.join(storePath, 'lock')
await lock(lockFilename, {firstTime: true, stale: opts.stale})
try {
const result = await fn()
Expand Down
27 changes: 14 additions & 13 deletions src/api/uninstall.ts
Expand Up @@ -22,24 +22,25 @@ import removeTopDependency from '../removeTopDependency'

export default async function uninstallCmd (pkgsToUninstall: string[], maybeOpts?: PnpmOptions) {
const opts = extendOptions(maybeOpts)
return lock(opts.prefix, async () => {
const ctx = await getContext(opts)

const ctx = await getContext(opts)

if (!ctx.pkg) {
throw new Error('No package.json found - cannot uninstall')
}
if (!ctx.pkg) {
throw new Error('No package.json found - cannot uninstall')
}

const pkg = ctx.pkg
const pkg = ctx.pkg

if (opts.lock === false) {
return run()
}
if (opts.lock === false) {
return run()
}

return lock(ctx.storePath, run, {stale: opts.lockStaleDuration})
return lock(ctx.storePath, run, {stale: opts.lockStaleDuration})

function run () {
return uninstallInContext(pkgsToUninstall, pkg, ctx, opts)
}
function run () {
return uninstallInContext(pkgsToUninstall, pkg, ctx, opts)
}
}, {stale: opts.lockStaleDuration})
}

export async function uninstallInContext (pkgsToUninstall: string[], pkg: Package, ctx: PnpmContext, opts: StrictPnpmOptions) {
Expand Down

0 comments on commit d44a333

Please sign in to comment.