Support installing from files

close #21
This commit is contained in:
Zoltan Kochan committed 2016-07-17 13:53:44 +03:00
1 parent b77eefbdfe
commit 32ef49b76b
9 files changed
+92 -15

No files matched your search

+2 -2
View File
@@ -10,8 +10,8 @@
- [x] compiled packages (`npm i node-sass`)
- [x] bundled dependencies (`npm i fsevents@1.0.6`)
- [ ] git-hosted packages (`npm i rstacruz/scourjs`)
- [ ] optional dependencies (`npm i escodegen@1.8.0` wants `source-map@~0.2.0`)
- [ ] file packages (`npm i file:../path`)
- [x] optional dependencies (`npm i escodegen@1.8.0` wants `source-map@~0.2.0`)
- [x] file packages (`npm i file:../path`)
- [x] windows support
- [x] bin executables
- [ ] `--global` installs
+22 -10
View File
@@ -3,14 +3,18 @@ var got = require('./got')
var crypto = require('crypto')
var gunzip = require('gunzip-maybe')
var tar = require('tar-fs')
var fs = require('fs')
/*
* Fetches a tarball `tarball` and extracts it into `dir`
*/
module.exports = function fetch (dir, tarball, shasum, log) {
return got.getStream(tarball)
.then(stream => fetchStream(dir, tarball, shasum, log, stream))
module.exports = function fetch (dir, dist, log) {
if (!dist.local) {
return got.getStream(dist.tarball)
.then(stream => fetchStream(dir, dist.tarball, dist.shasum, log, stream))
}
return unpackStream(fs.createReadStream(dist.tarball), dir)
}
function fetchStream (dir, tarball, shasum, log, stream) {
@@ -19,13 +23,12 @@ function fetchStream (dir, tarball, shasum, log, stream) {
var size
var downloaded = 0
stream
.on('response', start)
.on('data', _ => { actualShasum.update(_) })
.on('error', reject)
.pipe(gunzip()).on('error', reject)
.pipe(tar.extract(dir, { strip: 1 })).on('error', reject)
.on('finish', finish)
unpackStream(
stream
.on('response', start)
.on('data', _ => { actualShasum.update(_) })
.on('error', reject), dir
).then(finish)
function start (res) {
if (res.statusCode !== 200) {
@@ -53,3 +56,12 @@ function fetchStream (dir, tarball, shasum, log, stream) {
}
})
}
function unpackStream (stream, dir) {
return new Promise((resolve, reject) => {
stream
.pipe(gunzip()).on('error', reject)
.pipe(tar.extract(dir, { strip: 1 })).on('error', reject)
.on('finish', resolve)
})
}
+3 -2
View File
@@ -95,7 +95,7 @@ module.exports = function install (ctx, pkgSpec, modules, options) {
.then(_ => _
? saveCachedResolution()
.then(data => log('package.json', data))
: resolve(pkg.spec, log)
: resolve(Object.assign({}, pkg.spec, {root: ctx.root}), log)
.then(saveResolution)
.then(_ => log('resolved', pkg))
.then(_ => buildToStoreCached(ctx, paths, pkg, log))
@@ -186,7 +186,8 @@ function fetchToStore (ctx, paths, pkg, log) {
.then(_ => mkdirp(ctx.store))
.then(_ => mkdirp(join(paths.tmp, '_')))
.then(_ => fs.writeFile(join(paths.tmp, '.pnpm_inprogress'), '', 'utf-8'))
.then(_ => fetch(join(paths.tmp, '_'), pkg.dist.tarball, pkg.dist.shasum, log))
.then(_ => fetch(join(paths.tmp, '_'), pkg.dist, log))
.then(_ => pkg.dist.local ? fs.unlink(pkg.dist.tarball) : Promise.resolve())
// TODO: this is the point it becomes partially useable.
// ie, it can now be symlinked into .store/foo@1.0.0.
+3
View File
@@ -1,6 +1,7 @@
var resolveNpm = require('./resolve/npm')
var resolveTarball = require('./resolve/tarball')
var resolveGithub = require('./resolve/github')
var resolveLocal = require('./resolve/local')
/**
* Resolves a package in the NPM registry. Done as part of `install()`.
@@ -23,6 +24,8 @@ module.exports = function resolve (pkg, log) {
return resolveTarball(pkg, log)
} else if (pkg.type === 'hosted' && pkg.hosted.type === 'github') {
return resolveGithub(pkg, log)
} else if (pkg.type === 'local') {
return resolveLocal(pkg, log)
} else {
throw new Error('' + pkg.rawSpec + ': ' + pkg.type + ' packages not supported')
}
+1 -1
View File
@@ -11,7 +11,7 @@ module.exports = function resolveGithub (pkg) {
return resolveRef(spec).then(function (ref) {
spec.ref = ref
return resolvePackageName(spec).then(function (name) {
var fullname = name + ['@github', spec.owner, spec.repo, spec.ref].join('!')
var fullname = name.replace('/', '!') + ['@github', spec.owner, spec.repo, spec.ref].join('!')
return {
name: name,
fullname: fullname,
+42
View File
@@ -0,0 +1,42 @@
var resolve = require('path').resolve
var spawn = require('child_process').spawn
/**
* Resolves a package hosted on the local filesystem
*/
module.exports = function resolveLocal (pkg) {
var dependencyPath = resolve(pkg.root, pkg.spec)
return new Promise((resolve, reject) => {
var proc = spawn('sh', ['-c', 'npm pack'], {
cwd: dependencyPath
})
proc.on('error', reject)
proc.on('close', code => {
if (code > 0) return reject(new Error('Exit code ' + code))
return resolve()
})
})
.then(_ => {
var localPkg = require(resolve(dependencyPath, 'package.json'))
var tgzFilename = localPkg.name + '-' + localPkg.version + '.tgz'
return {
name: localPkg.name,
fullname: localPkg.name.replace('/', '!') + [
'@file',
escapePkgPath(dependencyPath)
].join('!'),
dist: {
local: true,
tarball: resolve(dependencyPath, tgzFilename)
}
}
})
}
function escapePkgPath (pkgPath) {
return pkgPath.replace(/[/\\]/g, '!').replace(/^!/, '')
}
+14
View File
@@ -184,6 +184,20 @@ test('tarballs (is-array-1.0.1.tgz)', function (t) {
}, t.end)
})
test('local file', function (t) {
prepare()
var localPkgPath = join(__dirname, 'local-pkg')
install(['file:' + localPkgPath], { quiet: true })
.then(function () {
var localPkg = require(
join(process.cwd(), 'node_modules', 'local-pkg'))
t.ok(localPkg, 'localPkg() is available')
t.end()
}, t.end)
})
test('shrinkwrap compatibility', function (t) {
prepare()
fs.writeFileSync('package.json',
+1
View File
@@ -0,0 +1 @@
module.exports = function () {}
+4
View File
@@ -0,0 +1,4 @@
{
"name": "local-pkg",
"version": "1.0.0"
}