This repository has been archived by the owner on May 10, 2021. It is now read-only.
-
Notifications
You must be signed in to change notification settings - Fork 12
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
Showing
11 changed files
with
4,267 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,3 @@ | ||
/node_modules | ||
/.nyc_output | ||
/test/cache |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,6 @@ | ||
language: node_js | ||
sudo: false | ||
node_js: | ||
- "7" | ||
- "6" | ||
- "4" |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,7 @@ | ||
<!-- | ||
⚠️🚨 BEFORE FILING AN ISSUE: 🚨⚠️ | ||
|
||
👉🏼 CONTRIBUTING.md 👈🏼 (the "contribution guidelines" up there ☝🏼) | ||
|
||
I PROMISE IT'S A VERY VERY SHORT READ.🙇🏼 | ||
--> |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,3 @@ | ||
To the extent possible under law, maintainers for this project have waived all copyright and related or neighboring rights to this project. | ||
|
||
For more information on this waiver, see: https://creativecommons.org/publicdomain/zero/1.0/ |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,7 @@ | ||
<!-- | ||
⚠️🚨 BEFORE FILING A PR: 🚨⚠️ | ||
|
||
👉🏼 CONTRIBUTING.md 👈🏼 (the "contribution guidelines" up there ☝🏼) | ||
|
||
I PROMISE IT'S A VERY VERY SHORT READ.🙇🏼 | ||
--> |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,43 @@ | ||
[](https://npm.im/cipm) [](https://npm.im/cipm) [](https://travis-ci.org/zkat/cipm) [](https://ci.appveyor.com/project/zkat/cipm) [](https://coveralls.io/github/zkat/cipm?branch=latest) | ||
|
||
## NOTE: this project is under active development. Please don't use it yet. | ||
|
||
# cipm(1) -- install npm dependencies from a package lock | ||
|
||
## SYNOPSIS | ||
|
||
`cipm [--userconfig <path>] [--ignore-scripts] [--offline] [--loglevel <level>]` | ||
|
||
## INSTALL | ||
|
||
`npm install [-g|-D] cipm` | ||
|
||
## DESCRIPTION | ||
|
||
When invoked inside an npm project with a `package.json` and `package-lock.json` (or an `npm-shrinwkrap.json`), it will install the specified dependencies and run their install scripts. | ||
|
||
The main difference between this and `npm install` is that `cipm` is both a small, standalone program, and that it can bypass a lot of the heavier machinery in npm oriented towards interacting with invalid states: `cipm` completely removes `node_modules` before beginning the install, if it exists. | ||
|
||
`cipm` also requires that the current project have an existing lockfile, which must first be generated using `npm install` in `npm@5` or later versions (or any other package manager supporting `lockfileVersion@>=1`). | ||
|
||
This tool is ideal for using in CI environments that require regular, full installs of an application, but that are usually able to cache package data in a central cache. | ||
|
||
## EXAMPLES | ||
|
||
## AUTHOR | ||
|
||
Written by [Kat Marchan](https://github.com/zkat). | ||
|
||
## REPORTING BUGS | ||
|
||
Please file any relevant issues [on Github.](https://github.com/zkat/cipm) | ||
|
||
## LICENSE | ||
|
||
This work is released by its authors into the public domain under CC0-1.0. See `LICENSE.md` for details. | ||
|
||
## SEE ALSO | ||
|
||
* `npm-install(1)` | ||
* `npm-package-locks(5)` | ||
* `package-lock.json(5)` |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,22 @@ | ||
environment: | ||
matrix: | ||
- nodejs_version: "7" | ||
- nodejs_version: "6" | ||
- nodejs_version: "4" | ||
|
||
platform: | ||
- x64 | ||
|
||
install: | ||
- ps: Install-Product node $env:nodejs_version $env:platform | ||
- npm config set spin false | ||
- npm i -g npm@latest | ||
- npm install | ||
|
||
test_script: | ||
- npm test | ||
|
||
matrix: | ||
fast_finish: true | ||
|
||
build: off |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,155 @@ | ||
'use strict' | ||
|
||
const BB = require('bluebird') | ||
|
||
const extractionWorker = require('./worker.js') | ||
const fs = BB.promisifyAll(require('graceful-fs')) | ||
const npa = require('npm-package-arg') | ||
const path = require('path') | ||
const rimraf = BB.promisify(require('rimraf')) | ||
const workerFarm = require('worker-farm') | ||
const yargs = require('yargs') | ||
|
||
const WORKER_PATH = require.resolve('./worker.js') | ||
let workers | ||
|
||
main(parseArgs()) | ||
|
||
let pkgCount = 0 | ||
|
||
function parseArgs () { | ||
return yargs | ||
.option('loglevel', { | ||
type: 'string', | ||
describe: 'log level for npmlog', | ||
default: 'notice' | ||
}) | ||
.option('offline', { | ||
type: 'boolean', | ||
describe: 'force cipm to run offline, or error' | ||
}) | ||
.option('ignore-scripts', { | ||
type: 'boolean', | ||
describe: 'skip running lifecycle scripts' | ||
}) | ||
.option('userconfig', { | ||
type: 'string', | ||
describe: 'path to npmrc' | ||
}) | ||
.argv | ||
} | ||
|
||
function main () { | ||
const startTime = Date.now() | ||
workers = workerFarm({ | ||
maxConcurrentCallsPerWorker: 20, | ||
maxRetries: 1 | ||
}, WORKER_PATH) | ||
return BB.join( | ||
readJson('.', 'package.json'), | ||
readJson('.', 'package-lock.json', true), | ||
readJson('.', 'npm-shrinkwrap.json', true), | ||
(pkg, lock, shrink) => { | ||
pkg._shrinkwrap = lock || shrink | ||
return pkg | ||
} | ||
).tap(pkg => { | ||
if (!pkg._shrinkwrap) { | ||
throw new Error(`cipm can only install packages with an existing package-lock.json or npm-shrinkwrap.json. Run an install with npm@5 or later to generate it, then try again.`) | ||
} | ||
|
||
return rimraf('./node_modules') | ||
}).tap(pkg => { | ||
return runScript('preinstall', pkg, '.') | ||
}).tap(pkg => { | ||
return extractDeps( | ||
`./node_modules`, | ||
pkg._shrinkwrap.dependencies | ||
) | ||
}).tap(pkg => { | ||
return runScript('install', pkg, '.') | ||
}).tap(pkg => { | ||
return runScript('postinstall', pkg, '.') | ||
}).then(pkg => { | ||
workerFarm.end(workers) | ||
console.log(`added ${pkgCount} packages in ${ | ||
(Date.now() - startTime) / 1000 | ||
}s.`) | ||
}) | ||
} | ||
|
||
function runScript (script, pkg, pkgPath) { | ||
if (pkg.scripts && pkg.scripts[script]) { | ||
console.log('executing', script, 'on', pkgPath) | ||
} | ||
return BB.resolve() | ||
} | ||
|
||
function extractDeps (modPath, deps) { | ||
return BB.map(Object.keys(deps || {}), (name) => { | ||
const child = deps[name] | ||
const childPath = path.join(modPath, name) | ||
return ( | ||
child.bundled | ||
? BB.resolve() | ||
: extractChild(name, child, childPath) | ||
).then(() => { | ||
return readJson(childPath, 'package.json') | ||
}).tap(pkg => { | ||
return runScript('preinstall', pkg, childPath) | ||
}).then(pkg => { | ||
return extractDeps(path.join(childPath, 'node_modules')) | ||
.then(dependencies => { | ||
return { | ||
name, | ||
package: pkg, | ||
child, | ||
childPath, | ||
dependencies: dependencies.reduce((acc, dep) => { | ||
acc[dep.name] = dep | ||
return acc | ||
}, {}) | ||
} | ||
}) | ||
}).tap(full => { | ||
pkgCount++ | ||
return runScript('install', full.package, childPath) | ||
}).tap(full => { | ||
return runScript('postinstall', full.package, childPath) | ||
}) | ||
}) | ||
} | ||
|
||
function extractChild (name, child, childPath) { | ||
const spec = npa.resolve(name, child.resolved || child.version) | ||
const opts = { | ||
cache: path.resolve(process.env.HOME, '.npm/_cacache'), | ||
integrity: child.integrity | ||
} | ||
const args = [spec, childPath, opts] | ||
return BB.fromNode((cb) => { | ||
let launcher = extractionWorker | ||
let msg = args | ||
const spec = typeof args[0] === 'string' ? npa(args[0]) : args[0] | ||
if (spec.registry || spec.type === 'remote') { | ||
// workers will run things in parallel! | ||
launcher = workers | ||
try { | ||
msg = JSON.stringify(msg) | ||
} catch (e) { | ||
return cb(e) | ||
} | ||
} | ||
launcher(msg, cb) | ||
}) | ||
} | ||
|
||
function readJson (jsonPath, name, ignoreMissing) { | ||
return fs.readFileAsync(path.join(jsonPath, name), 'utf8') | ||
.then(str => JSON.parse(str)) | ||
.catch({code: 'ENOENT'}, err => { | ||
if (!ignoreMissing) { | ||
throw err | ||
} | ||
}) | ||
} |
Oops, something went wrong.