feat: add a --no-lock option

Ref #594
This commit is contained in:
zkochan
2017-05-07 13:38:03 +03:00
parent 21ec1d5819
commit 3a2683ca94
7 changed files with 67 additions and 31 deletions

View File

@@ -113,6 +113,19 @@ Controls the maximum number of HTTP requests that can be done simultaneously.
Controls the number of child processes run parallely to build node modules.
#### lock
* Default: **true**
* Type: **Boolean**
Dangerous! If false, the store is not locked. It means that several installations using the same
store can run simultaneously.
Can be passed in via a CLI option. `--no-lock` to set it to false. E.g.: `pnpm install --no-lock`.
> If you experience issues similar to the ones described in [#594](https://github.com/pnpm/pnpm/issues/594), use this option to disable locking.
> In the meanwhile, we'll try to find a solution that will make locking work for everyone.
## Benchmark
pnpm is usually 10 times faster than npm and 30% faster than yarn. See [this](https://github.com/zkochan/node-package-manager-benchmark)

View File

@@ -29,6 +29,7 @@ const defaults = (opts: PnpmOptions) => {
networkConcurrency: 16,
fetchingConcurrency: 16,
lockStaleDuration: 60 * 1000, // 1 minute
lock: true,
childConcurrency: 5,
offline: false,
registry: 'https://registry.npmjs.org/',
@@ -52,6 +53,9 @@ export default (opts?: PnpmOptions): StrictPnpmOptions => {
if (extendedOpts.force) {
logger.warn('using --force I sure hope you know what you are doing')
}
if (extendedOpts.lock === false) {
logger.warn('using --no-lock I sure hope you know what you are doing')
}
if (extendedOpts.localRegistry !== DEFAULT_LOCAL_REGISTRY) {
extendedOpts.localRegistry = expandTilde(extendedOpts.localRegistry, extendedOpts.prefix)
}

View File

@@ -61,25 +61,27 @@ export async function install (maybeOpts?: PnpmOptions) {
const optionalDeps = R.keys(ctx.pkg.optionalDependencies)
return lock(
ctx.storePath,
async () => {
const scripts = !opts.ignoreScripts && ctx.pkg && ctx.pkg.scripts || {}
if (scripts['preinstall']) {
npmRun('preinstall', ctx.root, opts.userAgent)
}
if (opts.lock === false) {
return run()
}
await installInContext(installType, specs, optionalDeps, [], ctx, installCtx, opts)
return lock(ctx.storePath, run, {stale: opts.lockStaleDuration})
if (scripts['postinstall']) {
npmRun('postinstall', ctx.root, opts.userAgent)
}
if (scripts['prepublish']) {
npmRun('prepublish', ctx.root, opts.userAgent)
}
},
{stale: opts.lockStaleDuration}
)
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, optionalDeps, [], ctx, installCtx, opts)
if (scripts['postinstall']) {
npmRun('postinstall', ctx.root, opts.userAgent)
}
if (scripts['prepublish']) {
npmRun('prepublish', ctx.root, opts.userAgent)
}
}
}
function specsToInstallFromPackage(
@@ -131,18 +133,22 @@ export async function installPkgs (fuzzyDeps: string[] | Dependencies, maybeOpts
? packagesToInstall.map(spec => spec.name)
: []
return lock(
ctx.storePath,
() => installInContext(
if (opts.lock === false) {
return run()
}
return lock(ctx.storePath, run, {stale: opts.lockStaleDuration})
function run () {
return installInContext(
installType,
packagesToInstall,
optionalDependencies,
packagesToInstall.map(spec => spec.name),
ctx,
installCtx,
opts),
{stale: opts.lockStaleDuration}
)
opts)
}
}
function argsToSpecs (args: string[], defaultTag: string, where: string): PackageSpec[] {

View File

@@ -19,7 +19,13 @@ export async function prune(maybeOpts?: PnpmOptions): Promise<void> {
const ctx = await getContext(opts)
return lock(ctx.storePath, async function () {
if (opts.lock === false) {
return run()
}
return lock(ctx.storePath, run, {stale: opts.lockStaleDuration})
async function run () {
if (!ctx.pkg) {
throw new Error('No package.json found - cannot prune')
}
@@ -37,8 +43,7 @@ export async function prune(maybeOpts?: PnpmOptions): Promise<void> {
const prunedShr = pruneShrinkwrap(newShr)
await removeOrphanPkgs(ctx.privateShrinkwrap, prunedShr, ctx.root, ctx.storePath)
},
{stale: opts.lockStaleDuration})
}
}
async function getExtraneousPkgs (pkg: Package, root: string, production: boolean) {

View File

@@ -32,11 +32,16 @@ export default async function uninstallCmd (pkgsToUninstall: string[], maybeOpts
}
const pkg = ctx.pkg
return lock(
ctx.storePath,
() => uninstallInContext(pkgsToUninstall, pkg, ctx, opts),
{stale: opts.lockStaleDuration}
)
if (opts.lock === false) {
return run()
}
return lock(ctx.storePath, run, {stale: opts.lockStaleDuration})
function run () {
return uninstallInContext(pkgsToUninstall, pkg, ctx, opts)
}
}
export async function uninstallInContext (pkgsToUninstall: string[], pkg: Package, ctx: PnpmContext, opts: StrictPnpmOptions) {

View File

@@ -59,6 +59,7 @@ async function run (argv: string[]) {
'network-concurrency': Number,
'fetching-concurrency': Number,
'lock-stale-duration': Number,
'lock': Boolean,
'child-concurrency': Number,
'offline': Boolean,
'reporter': String,

View File

@@ -46,6 +46,7 @@ export type PnpmOptions = {
networkConcurrency?: number,
fetchingConcurrency?: number,
lockStaleDuration?: number,
lock?: boolean,
childConcurrency?: number,
repeatInstallDepth?: number,
@@ -98,6 +99,7 @@ export type StrictPnpmOptions = {
networkConcurrency: number,
fetchingConcurrency: number,
lockStaleDuration: number,
lock: boolean,
childConcurrency: number,
repeatInstallDepth: number,