Welcome to mirror list, hosted at ThFree Co, Russian Federation.

github.com/npm/cli.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
path: root/lib
diff options
context:
space:
mode:
authorisaacs <i@izs.me>2010-05-10 06:35:30 +0400
committerisaacs <i@izs.me>2010-05-10 06:35:30 +0400
commit44d1b65f993d7dcdfc6259ae1b59a2684ea5779d (patch)
treeb063c7c0a606facd619971a5fe0130f7558f841a /lib
parenta5c897ac8a19cc73389fd8a83403bf68775d2fd4 (diff)
Leverage the cache for installs.
Diffstat (limited to 'lib')
-rw-r--r--lib/install.js207
1 files changed, 64 insertions, 143 deletions
diff --git a/lib/install.js b/lib/install.js
index 728d113c9..53b0b1f11 100644
--- a/lib/install.js
+++ b/lib/install.js
@@ -28,6 +28,7 @@ var registry = require("./utils/registry")
, path = require("path")
, chain = require("./utils/chain")
, fs = require("fs")
+ , cache = require("./cache")
function registryInstall (pkglist, cb) {
// it's helpful to know what we have already
@@ -57,17 +58,7 @@ function registryInstall (pkglist, cb) {
, installReg = {}
;(function F (pkg) {
if (!pkg) {
- installList = installList.map(function (i) {
- return path.join(npm.dir, i, "package")
- })
- log(installList, "install")
- if (installList.length === 0) {
- return log("nothing to install", "install", cb)
- }
- return npm.commands.build
- ( installList
- , cb
- )
+ return buildAll(installList, cb)
}
log(pkg, "install pkg")
if (seen[pkg]) {
@@ -76,29 +67,30 @@ function registryInstall (pkglist, cb) {
}
seen[pkg] = true
- function tarballHandler (er, data) {
- if (er) return cb(er)
- npm.set(data)
- installedPackages[data.name] = installedPackages[data.name] || {}
- installedPackages[data.name][data.version] = data
- installReg[data.name] = installReg[data.name] || {}
- installReg[data.name][data.version] = data
- installList.push(path.join(data.name, data.version))
- // also make sure to get any dependencies.
+ // Call this with the parsed package data when we know
+ // that it's sitting in the cache
+ function Continue (er, data) {
+ if (er) return log.er(cb, "Error installing "+pkg)(er)
+ seen[data.name+"@"+data.version] = true
+ var p = path.join(data.name, data.version)
+ , ir = installReg
+ if (!installReg[data.name] || !installReg[data.name][data.version]) {
+ installList.push(p)
+ ;(ir[data.name] = ir[data.name] || {})[data.version] = true
+ }
+ // also add the dependencies.
if (data.dependencies) for (var dep in data.dependencies) {
dep = dep.trim()+"@"+data.dependencies[dep]
if (!seen[dep]) pkglist.push(dep)
}
F(pkglist.shift())
}
- if (pkg.match(/^(file:|\.|\/)/)) {
- pkg = pkg.replace(/^file:(\/\/)?/, '')
- if (pkg.charAt(0) !== "/") pkg = path.join(process.cwd(), pkg)
- return installLocalTarball(pkg, tarballHandler)
- }
- if (pkg.match(/^https?:\/\//)) return fetchTarball(pkg, tarballHandler)
- // now we know it's not a URL, so handle it like a tag, version, or range.
+ // it's a local thing or a url if it has a / in it.
+ if (pkg.indexOf("/") !== -1) return cache.add(pkg, Continue)
+
+ // now we know it's not a URL or file,
+ // so handle it like a tag, version, or range.
pkg = pkg.split("@")
var name = pkg[0]
, ver = pkg.slice(1).join("@").trim()
@@ -106,59 +98,41 @@ function registryInstall (pkglist, cb) {
, exact = semver.valid(ver)
, tag = (!exact && !range)
pkg = pkg.join("@")
- // must fetch data to know how to solve this.
+
+ // if it's an exact name/version, and not already installed, then pull
+ // the data out of the cache to ensure it's there, and then add deps.
+ if (exact) {
+ if ( (name in installedPackages) && (ver in installedPackages[name])
+ || (name in installReg) && (ver in installReg[name])
+ ) {
+ // already installed. Continue.
+ return F(pkglist.shift())
+ }
+ return cache.read(name, ver, Continue)
+ }
+
+ // if not exact, then fetch the root data so that we have the
+ // tags and all the versions, and can know what's available.
var data = npm.get(name)
if (!data) {
log(name, "fetch data")
return registry.get(name, function (er, data) {
if (!er && !data) er = new Error("not found in registry: "+name)
if (er) return cb(er)
- npm.set(name, data)
+ npm.set(data)
seen[pkg] = false
return F(pkg)
})
}
- // now we know that we have the data.
+ // now we know that we have the data.
if (tag) {
tag = ver || defTag
if (!data["dist-tags"] || !(tag in data["dist-tags"])) {
- return cb(new Error(
- "Tag "+tag+" not found for package "+name))
+ return cb(new Error("Tag "+tag+" not found for package "+name))
}
data = data.versions[data["dist-tags"][tag]]
- npm.set(data)
- // add that version to the list, and its dependencies
if (!seen[name+"@"+data.version]) pkglist.push(name+"@"+data.version)
- if (data.dependencies) for (var dep in data.dependencies) {
- dep = dep.trim()+"@"+data.dependencies[dep]
- if (!seen[dep]) pkglist.push(dep)
- }
- return F(pkglist.shift())
- }
- // now we know it's not a tag. Either a real version, or a range,
- // and possibly already installed.
- if (exact) {
- if ((name in installedPackages) && (ver in installedPackages[name])) {
- // already installed. Continue.
- return F(pkglist.shift())
- }
- var data = npm.get(name)
- // make sure this version exists.
- if (!(ver in data.versions)) {
- return cb(new Error(
- "Required version "+name+"@"+ver+" not found in registry"))
- }
- data = data.versions[ver]
- // get the tarball, and add the deps.
- var tarball = data.dist.tarball
- if (!tarball) return cb(new Error(
- "No tarball URL found for "+name+"@"+ver))
- if (!seen[tarball]) pkglist.push(tarball)
- if (data.dependencies) for (var dep in data.dependencies) {
- dep = dep.trim()+"@"+data.dependencies[dep]
- if (!seen[dep]) pkglist.push(dep)
- }
return F(pkglist.shift())
}
// now we know it's a range. get the data for this package, and then
@@ -170,12 +144,11 @@ function registryInstall (pkglist, cb) {
var satis = semver.maxSatisfying
( Object.keys(installedPackages[name] || {})
.concat(Object.keys(installReg[name] || {}))
- , range)
- if (satis) {
- satis = name+"@"+satis
- if (!seen[satis]) pkglist.push(satis)
- return F(pkglist.shift())
- }
+ , range
+ )
+ // if there is a satisfying version already, then simply move on.
+ if (satis) return F(pkglist.shift())
+
// new thing. fetch from registry. favor defTag version.
var data = npm.get(name)
, stable = data["dist-tags"] && data["dist-tags"][defTag]
@@ -187,90 +160,38 @@ function registryInstall (pkglist, cb) {
var satis = semver.maxSatisfying(Object.keys(data.versions), range)
if (!satis) return cb(new Error(
"No satisfying version found for "+name+"@"+range))
- data = data[satis]
+ // now just install as an explicit version.
satis = name+"@"+satis
if (!seen[satis]) pkglist.push(satis)
- if (data.dependencies) for (var dep in data.dependencies) {
- dep = dep.trim()+"@"+data.dependencies[dep]
- if (!seen[dep]) pkglist.push(dep)
- }
return F(pkglist.shift())
})(pkglist.shift())
}
-// download the tarball, and move the contents into
-// the appropriate name/version folder.
-function fetchTarball (tarball, cb) {
- var target = path.join(npm.tmp, tarball.replace(/[^a-zA-Z0-9]/g, "-")+"-"+
- Date.now()+"-"+Math.random()) + ".tgz"
- chain
- ( [mkdir, npm.tmp]
- , [fetch, tarball, target]
- , function (er, ok) {
- if (er) return cb(er)
- installLocalTarball(target, function (er, data) {
- if (er) return cb(er)
- rm(target, function (er) {
- if (er) return cb(er)
- cb(null, data)
- })
- })
- }
- )
-}
-function installLocalTarball (tarball, cb) {
- var folder = path.join(npm.tmp, tarball.replace(/[^a-zA-Z0-9]/g, "-")+"-"+
- Date.now()+"-"+Math.random())
+function buildAll (list, cb) {
+ if (list.length === 0) {
+ return log("Nothing to install", "install", cb)
+ }
+ log("About to unpack", "buildAll")
chain
- ( [mkdir, folder]
- , [unpackTar, tarball, folder]
- , function (er) {
- if (er) return cb(er)
- readJson(path.join(folder, "package.json"), function (er, data) {
- if (er) return cb(er)
- chain
- ( [moveIntoPlace, folder, data]
- , [log, data._id, "moved into place"]
- , [rm, folder]
- , [log, folder, "removed"]
- , function (er) { return cb(er, data) }
- )
- })
- }
+ ( [unpackAll, list]
+ , [build, list]
+ , cb
)
-
}
-
-function unpackTar (tarball, unpackTarget, cb) {
- exec("tar", ["xzvf", tarball, "--strip", "1", "-C", unpackTarget], cb)
+function unpackAll (list, cb) {
+ list = list.map(function (i) { return i.split('/') })
+ ;(function U (i) {
+ if (!i) return cb()
+ var target = path.join(npm.dir, i[0], i[1], "package")
+ cache.unpack(i[0], i[1], target, function (er) {
+ if (er) return cb(er)
+ return U(list.shift())
+ })
+ })(list.shift())
}
-
-// move to ROOT/.npm/{name}/{version}/package
-function moveIntoPlace (dir, data, cb) {
- if (!data.name || !data.version) {
- return cb(new Error("Name or version not found in package info."))
- }
- var target = path.join(npm.dir, data.name, data.version)
-
- chain
- ( function (cb) {
- fs.lstat(target, function (e) {
- log((e?"remove":"creating") + " " +target, "moveIntoPlace")
- if (e) rm(target, function (er, ok) {
- if (er) {
- log("could not remove " + target, "moveIntoPlace")
- cb(new Error(target+" exists, and can't be removed"))
- } else {
- log("unlinked "+target,"moveIntoPlace")
- cb()
- }
- })
- else cb()
- })
- }
- , [mkdir, target]
- , [fs, "rename", dir, path.join(target, "package")]
- , [log, "done", "moveIntoPlace"]
+function build (list, cb) {
+ npm.commands.build
+ ( list.map(function (i) { return path.join(npm.dir, i, "package") })
, cb
)
}