Permalink
Browse files

Make the bundle folder configurable

  • Loading branch information...
1 parent 2adbbae commit 609ed5643a678ade30872cfb57474a5f9ca95811 @isaacs isaacs committed Jan 9, 2011
Showing with 107 additions and 77 deletions.
  1. +3 −0 doc/bundle.md
  2. +5 −0 doc/json.md
  3. +45 −33 lib/build.js
  4. +12 −9 lib/bundle.js
  5. +3 −1 lib/link.js
  6. +3 −3 lib/utils/lifecycle.js
  7. +28 −31 lib/utils/write-shim.js
  8. +4 −0 man1/bundle.1
  9. +4 −0 man1/json.1
View
@@ -37,6 +37,9 @@ In this way, a command like
to have a dependency that is not published on the npm registry. (It still
must contain a package.json, though, of course.)
+If there is a `directories.bundle` folder specified in the package.json,
+then it will use that folder rather than `node_modules`.
+
## CAVEATS
Man pages are not installed by bundle.
View
@@ -245,6 +245,11 @@ Put markdown files in here. Eventually, these will be displayed nicely, maybe,
Put example scripts in here. Someday, it might be exposed in some clever way.
+### directories.bundle
+
+The location where bundled dependencies live. This defaults to
+"node_modules", but can be set to anything you like.
+
## repository
Specify the place where your code lives. This is helpful for people who want to
View
@@ -67,13 +67,14 @@ function build (args, cb) {
function rebuildBundle (pkg, cb) {
if (!npm.config.get("rebuild-bundle")) return cb()
+ if (!pkg.directories.bundle) return cb()
var bundle = path.join( npm.dir, pkg.name, pkg.version
- , "package", "node_modules")
+ , "package", pkg.directories.bundle)
fs.stat(bundle, function (er, s) {
if (er || !s.isDirectory()) return cb()
log(pkg._id, "rebuilding bundled dependencies")
conf.unshift({ root : bundle
- , binroot : null
+ , binroot : path.join(bundle, ".bin")
, manroot : null
})
npm.commands.rebuild([], function (er, data) {
@@ -165,38 +166,44 @@ function resolveDependencies (pkg, cb) {
// link foo-1.0.3 to ROOT/.npm/{pkg}/{version}/node_modules/foo
// see if it's bundled already
- var bundleDir = path.join( npm.dir, pkg.name, pkg.version
- , "package", "node_modules" )
- , deps = pkg.dependencies && Object.keys(pkg.dependencies) || []
- log.verbose([pkg, deps], "deps being resolved")
+ var bundleDir = pkg.directories.bundle &&
+ path.join( npm.dir, pkg.name, pkg.version, "package"
+ , pkg.directories.bundle )
+ , deps = pkg.dependencies && Object.keys(pkg.dependencies) || []
+ log.verbose([pkg._id, deps], "deps being resolved")
+ if (!bundleDir) return verifyDeps(pkg, deps, cb)
fs.readdir(bundleDir, function (er, bundledDeps) {
if (er) bundledDeps = []
bundledDeps.forEach(function (bd) {
+ log.verbose([pkg._id, bd], "already bundled")
var i = deps.indexOf(bd)
if (i !== -1) deps.splice(i, 1)
})
+ verifyDeps(pkg, deps, cb)
+ })
+}
- asyncMap(deps, function (i, cb) {
- var req = { name:i, version:pkg.dependencies[i] }
- log.verbose(req.name+"@"+req.version, "required")
+function verifyDeps (pkg, deps, cb) {
+ asyncMap(deps, function (i, cb) {
+ var req = { name:i, version:pkg.dependencies[i] }
+ log.verbose(req.name+"@"+req.version, "required")
- // see if we have this thing installed.
- fs.readdir(path.join(npm.dir, req.name), function (er, versions) {
- if (er) return cb(new Error(
- "Required package: "+req.name+"("+req.version+") not found."))
- // TODO: Get the "stable" version if there is one.
- // Look that up from the registry.
- var satis = semver.maxSatisfying(versions, req.version)
- if (satis) return cb(null, {name:req.name, version:satis})
- return cb(new Error(
- "Required package: "+req.name+"("+req.version+") not found. "+
- "(Found: "+JSON.stringify(versions)+")"))
- })
- }, function (er, found) {
- // save the resolved dependencies on the pkg data for later
- pkg._resolvedDeps = found
- cb(er, found)
+ // see if we have this thing installed.
+ fs.readdir(path.join(npm.dir, req.name), function (er, versions) {
+ if (er) return cb(new Error(
+ "Required package: "+req.name+"("+req.version+") not found."))
+ // TODO: Get the "stable" version if there is one.
+ // Look that up from the registry.
+ var satis = semver.maxSatisfying(versions, req.version)
+ if (satis) return cb(null, {name:req.name, version:satis})
+ return cb(new Error(
+ "Required package: "+req.name+"("+req.version+") not found. "+
+ "(Found: "+JSON.stringify(versions)+")"))
})
+ }, function (er, found) {
+ // save the resolved dependencies on the pkg data for later
+ pkg._resolvedDeps = found
+ cb(er, found)
})
}
@@ -300,9 +307,9 @@ function linkModules (pkg, target, cb) {
log.silly(pkg.modules, "linkModules")
log.verbose(target, "linkModules")
if (target === npm.root
- && !target.match(/node_modules$/)
&& -1 === require.paths.indexOf(target)) {
- log.warn("modules installing to "+target+", outside NODE_PATH")
+ log.warn("modules installing to "+target+", outside NODE_PATH"
+ ,pkg._id)
}
if (!pkg.modules) pkg.modules = {}
var mod = pkg.modules
@@ -321,7 +328,9 @@ function linkModules (pkg, target, cb) {
writeShim
( path.join(pkgDir, mod[key])
, path.join(target, key.replace(/\.js$/, '')+".js")
- , path.join(versionDir, "node_modules")
+ , [ path.join(versionDir, "node_modules")
+ , pkg.directories.bundle
+ && path.join(versionDir, "package", pkg.directories.bundle) ]
, cb
)
}, function (er) {
@@ -362,18 +371,21 @@ function linkBins (pkg, binroot, versioned, cb) {
}
}
if (!binroot) return cb()
- var dep = path.join(npm.dir, pkg.name, pkg.version, "node_modules")
+ var versionDir = path.join(npm.dir, pkg.name, pkg.version)
+ , deps = [ path.join(versionDir, "node_modules")
+ , pkg.directories.bundle &&
+ path.join(versionDir, "package", pkg.directories.bundle) ]
asyncMap(Object.keys(pkg.bin).filter(function (i) {
return i.charAt(0) !== "_"
}), function (i, cb) {
log.verbose(i+" "+pkg.bin[i], "linkBin")
var to = path.join(binroot, i+(versioned ? "@"+pkg.version : ""))
, from = path.join(npm.dir, pkg.name, pkg.version, "package", pkg.bin[i])
- shimTest(from, to, dep, cb)
+ shimTest(from, to, deps, cb)
}, log.er(cb, "failed to link bins"))
}
-function shimTest (from, to, dep, cb) {
+function shimTest (from, to, deps, cb) {
// if it needs a shim, then call writeShim
// otherwise, just link it in.
fs.stat(from, function S (er, s) {
@@ -382,14 +394,14 @@ function shimTest (from, to, dep, cb) {
return fs.stat(from, S)
}
if (er) return cb(er)
- if (from.match(/\.(node|js)$/)) return writeShim(from, to, dep, cb)
+ if (from.match(/\.(node|js)$/)) return writeShim(from, to, deps, cb)
fs.readFile(from, function (er, data) {
if (er) return cb(er)
data = data.toString("ascii")
var envNode = data.match(/#!(\/usr\/bin\/)?env node/)
, node = data.match(/#!(\/usr(\/local)?\/bin\/)?node/)
if (envNode && envNode.index === 0 || node && node.index === 0) {
- return writeShim(from, to, dep, cb)
+ return writeShim(from, to, deps, cb)
}
return link(from, to, cb)
})
View
@@ -34,16 +34,24 @@ bundle.completion = function(args, index, cb) {
function bundle (args, dir, cb_) {
if (typeof dir === "function") cb_ = dir, dir = process.cwd()
- var location = path.join(dir, "node_modules")
- , binRoot = path.join(dir, "node_modules", ".bin")
+
+ readJson(path.join(dir, "package.json"), function (er, data) {
+ if (er) return log.er(cb_, "Not a package: "+dir)(er)
+ bundle_(data, args, dir, cb_)
+ })
+}
+function bundle_ (data, args, dir, cb_) {
+ var bundleDir = data.directories.bundle || "node_modules"
+ , location = path.join(dir, bundleDir)
+ , binRoot = path.join(dir, bundleDir, ".bin")
, pkg = dir
, cmd = args.shift()
function cb (er, data) {
conf.shift()
cb_(er, data)
}
mkdir(location, function (er) {
- if (er) return cb(new Error(bundle.usage))
+ if (er) return cb_(new Error(bundle.usage))
var c = { root : location
, binroot : binRoot
, manroot : null
@@ -78,12 +86,7 @@ function bundle (args, dir, cb_) {
}
// no command given, just install the local deps.
- // just read the package.json from the directory to
- // avoid adding the whole package to the cache
- readJson(path.join(pkg, "package.json"), function (er, data) {
- if (er) return log.er(cb, "Error reading "+pkg+"/package.json")(er)
- install(data, location, cb)
- })
+ install(data, location, cb)
})
})
}
View
@@ -82,7 +82,9 @@ function getDeps (data, folder, cb) {
function postBundle (er) {
if (er) return cb(er)
// filter out any bundled deps. those don't need to be installed
- fs.readdir(path.join(folder, "node_modules"), function (er, bundled) {
+ if (!data.directories.bundle) return cb(null, deps)
+ fs.readdir(path.join(folder, data.directories.bundle),
+ function (er, bundled) {
if (er && !bundled) bundled = []
bundled.forEach(function (b) { delete deps[b] })
cb(null, deps)
View
@@ -21,7 +21,7 @@ function lifecycle (pkg, stage, wd, cb) {
var env = makeEnv(pkg)
env.npm_lifecycle_event = stage
var pkgDir = path.join(npm.dir, pkg.name, pkg.version)
- env.PATH = path.join(pkgDir, "node_modules", ".bin")
+ env.PATH = path.join(pkgDir, pkg.directories.bundle, ".bin")
+ ":" + path.join(pkgDir, "dep-bin")
+ (env.PATH ? ":" + env.PATH : "")
@@ -51,7 +51,7 @@ function addDepsToEnv (pkg, env, cb_) {
if (er) return cb_(er)
pkg._bundledDeps = bundled
var bundledir = path.join(npm.dir, pkg.name, pkg.version
- ,"package", "node_modules", ".npm")
+ ,"package", pkg.directories.bundle, ".npm")
deps.forEach(add(npm.dir, "npm_dependency_"))
bundled.forEach(add(bundledir, "npm_dependency_"))
bundled.forEach(add(bundledir, "npm_bundle_"))
@@ -67,7 +67,7 @@ function addDepsToEnv (pkg, env, cb_) {
function readDeps (pkg, cb) {
var pkgdir = path.join(npm.dir, pkg.name, pkg.version)
, depdir = path.join(pkgdir, "dependson")
- , bundledir = path.join(pkgdir, "package", "node_modules", ".npm")
+ , bundledir = path.join(pkgdir, "package", pkg.directories.bundle, ".npm")
fs.readdir(depdir, function (er, dn) {
done(er ? [] : dn.map(function (dn) {
dn = dn.split("@")
View
@@ -8,46 +8,43 @@ var fs = require("./graceful-fs")
, mkdir = require("./mkdir-p")
, log = require("./log")
-function shimIfExists (from, to, dep, cb) {
- if (!cb) cb = dep, dep = false
+function shimIfExists (from, to, deps, cb) {
+ if (!cb) cb = deps, deps = false
fs.stat(from, function (er) {
if (er) return cb()
- writeShim(from, to, dep, cb)
+ writeShim(from, to, deps, cb)
})
}
-function writeShim (from, to, dep, cb) {
- if (!cb) cb = dep, dep = false
+function writeShim (from, to, deps, cb) {
+ if (!cb) cb = deps, deps = false
log.silly([from,to], "writeShim")
- if (dep) dep = relativize(dep, to)
+ if (deps) {
+ deps = deps.filter(function (d) { return d }).map(function (dep) {
+ return relativize(dep, to)
+ })
+ }
from = relativize(from, to).replace(/\.(js|node)$/, '')
- // todo: remove this dep juggling when 0.2.x is deprecated,
- // and node_modules is picked up automatically.2
+ // todo: remove this deps juggling somehow.
var code = "#!/usr/bin/env node\n"
+ "// generated by npm, please don't touch!\n"
- + (dep ? "var dep = require('path').join(__dirname, "
- + JSON.stringify(dep) + ")\n"
- + "var depMet = require.paths.indexOf(dep) !== -1\n"
- + "var bundle = dep.replace(/node_modules$/, "
- + "'package/node_modules')\n"
- + "var bundleMet = require.paths.indexOf(bundle) !== -1\n"
- : "")
- + "var from = "+JSON.stringify(from)+"\n"
- + "\n"
- + (dep ? "if (!depMet) require.paths.unshift(dep)\n"
- + "if (!bundleMet) require.paths.unshift(bundle)\n"
- : "")
- + "module.exports = require(from)\n"
- + "\n"
- + (dep ? "if (!depMet) {\n"
- + " var i = require.paths.indexOf(dep)\n"
- + " if (i !== -1) require.paths.splice(i, 1)\n"
- + "}\n"
- + "if (!bundleMet) {\n"
- + " var i = require.paths.indexOf(bundle)\n"
- + " if (i !== -1) require.paths.slice(i, 1)\n"
- + "}\n"
- : "")
+ + ( deps ? "var deps = " + JSON.stringify(deps || []) + "\n"
+ + " , path = require('path')\n"
+ + "deps = deps.map(function (dep, i, deps) {\n"
+ + " return require('path').join(__dirname, dep)\n"
+ + "}).filter(function (dep, i, deps) {\n"
+ + " return -1 !== require.paths.indexOf(dep)\n"
+ + "})\n"
+ : "" )
+ + "require.paths.unshift.apply(require.paths, deps)\n"
+ + "module.exports = require("+JSON.stringify(from)+")\n"
+ + ( deps ? "deps.forEach(function (dep, i, deps) {\n"
+ + " var met = require.paths.indexOf(dep)\n"
+ + " if (met !== -1) {\n"
+ + " require.paths.splice(met, 1)\n"
+ + " }\n"
+ + "})\n"
+ : "" )
mkdir(path.dirname(to), function (er) {
if (er) return cb(er)
View
@@ -51,6 +51,10 @@ In this way, a command like \fBnpm bundle install http://github\.com/user/projec
to have a dependency that is not published on the npm registry\. (It still
must contain a package\.json, though, of course\.)
.
+.P
+If there is a \fBdirectories\.bundle\fR folder specified in the package\.json,
+then it will use that folder rather than \fBnode_modules\fR\|\.
+.
.SH "CAVEATS"
Man pages are not installed by bundle\.
.
View
@@ -336,6 +336,10 @@ Put markdown files in here\. Eventually, these will be displayed nicely, maybe,
.SS "directories\.example"
Put example scripts in here\. Someday, it might be exposed in some clever way\.
.
+.SS "directories\.bundle"
+The location where bundled dependencies live\. This defaults to
+"node_modules", but can be set to anything you like\.
+.
.SH "repository"
Specify the place where your code lives\. This is helpful for people who want to
contribute, as well as perhaps maybe being the underpinning of some magical "track

0 comments on commit 609ed56

Please sign in to comment.