diff --git a/lib/cache.js b/lib/cache.js index 6c9dc649ae1..25054b2e744 100644 --- a/lib/cache.js +++ b/lib/cache.js @@ -408,20 +408,55 @@ function addNameRange (name, range, data, cb) { function next () { engineFilter(data) + + if (!npm.config.get("registry")) { + cachedFilter(data, function (er) { + if (er) return cb(er) + next_() + }) + } else { + next_() + } + } + + function next_ () { + log.silly([data.name, Object.keys(data.versions)], "versions") // if the tagged version satisfies, then use that. var tagged = data["dist-tags"][npm.config.get("tag")] if (tagged && data.versions[tagged] && semver.satisfies(tagged, range)) { return addNameVersion(name, tagged, data.versions[tagged], cb) } + // find the max satisfying version. var ms = semver.maxSatisfying(Object.keys(data.versions || {}), range) if (!ms) { return cb(installTargetsError(range, data)) } + + // if we don't have a registry connection, try to see if + // there's a cached copy that will be ok. addNameVersion(name, ms, data.versions[ms], cb) } } +// filter the versions down based on what's already in cache. +function cachedFilter (data, cb) { + ls_(data.name, 1, function (er, files) { + if (er) return log.er(cb, "Not in cache, can't fetch: "+data.name)(er) + files = files.map(function (f) { + return path.basename(f.replace(/(\\|\/)$/, "")) + }).filter(function (f) { + return semver.valid(f) + }) + log.silly([data.name, files], "cached") + Object.keys(data.versions).forEach(function (v) { + if (files.indexOf(v) === -1) delete data.versions[v] + }) + + cb(null, data) + }) +} + function installTargetsError (requested, data) { var targets = Object.keys(data["dist-tags"]).filter(function (f) { return (data.versions || {}).hasOwnProperty(f) @@ -491,6 +526,10 @@ function addNameVersion (name, ver, data, cb) { }) function fetchit () { + if (!npm.config.get("registry")) { + return cb(new Error("Cannot fetch: "+dist.tarball)) + } + // use the same protocol as the registry. // https registry --> https tarballs. var tb = url.parse(dist.tarball)