diff options
Diffstat (limited to 'deps/npm/lib/utils/tar.js')
-rw-r--r-- | deps/npm/lib/utils/tar.js | 114 |
1 files changed, 101 insertions, 13 deletions
diff --git a/deps/npm/lib/utils/tar.js b/deps/npm/lib/utils/tar.js index 98f6e4ff64e..1e00040dbb1 100644 --- a/deps/npm/lib/utils/tar.js +++ b/deps/npm/lib/utils/tar.js @@ -20,9 +20,9 @@ var myUid = process.getuid && process.getuid() var myGid = process.getgid && process.getgid() var readPackageTree = require('read-package-tree') var union = require('lodash.union') -var flattenTree = require('../install/flatten-tree.js') var moduleName = require('./module-name.js') var packageId = require('./package-id.js') +var pulseTillDone = require('../utils/pulse-till-done.js') if (process.env.SUDO_UID && myUid === 0) { if (!isNaN(process.env.SUDO_UID)) myUid = +process.env.SUDO_UID @@ -40,18 +40,20 @@ function pack (tarball, folder, pkg, cb) { readJson(path.join(folder, 'package.json'), function (er, pkg) { if (er || !pkg.bundleDependencies) { - pack_(tarball, folder, null, null, pkg, cb) + pack_(tarball, folder, null, pkg, cb) } else { // we require this at runtime due to load-order issues, because recursive // requires fail if you replace the exports object, and we do, not in deps, but // in a dep of it. var recalculateMetadata = require('../install/deps.js').recalculateMetadata - readPackageTree(folder, iferr(cb, function (tree) { - recalculateMetadata(tree, log.newGroup('pack:' + packageId(pkg)), iferr(cb, function () { - pack_(tarball, folder, tree, flattenTree(tree), pkg, cb) + readPackageTree(folder, pulseTillDone('pack:readTree:' + packageId(pkg), iferr(cb, function (tree) { + var recalcGroup = log.newGroup('pack:recalc:' + packageId(pkg)) + recalculateMetadata(tree, recalcGroup, iferr(cb, function () { + recalcGroup.finish() + pack_(tarball, folder, tree, pkg, pulseTillDone('pack:' + packageId(pkg), cb)) })) - })) + }))) } }) } @@ -61,9 +63,96 @@ function BundledPacker (props) { } inherits(BundledPacker, Packer) +BundledPacker.prototype.applyIgnores = function (entry, partial, entryObj) { + if (!entryObj || entryObj.type !== 'Directory') { + // package.json files can never be ignored. + if (entry === 'package.json') return true + + // readme files should never be ignored. + if (entry.match(/^readme(\.[^\.]*)$/i)) return true + + // license files should never be ignored. + if (entry.match(/^(license|licence)(\.[^\.]*)?$/i)) return true + + // copyright notice files should never be ignored. + if (entry.match(/^(notice)(\.[^\.]*)?$/i)) return true + + // changelogs should never be ignored. + if (entry.match(/^(changes|changelog|history)(\.[^\.]*)?$/i)) return true + } + + // special rules. see below. + if (entry === 'node_modules' && this.packageRoot) return true + + // package.json main file should never be ignored. + var mainFile = this.package && this.package.main + if (mainFile && path.resolve(this.path, entry) === path.resolve(this.path, mainFile)) return true + + // some files are *never* allowed under any circumstances + // (VCS folders, native build cruft, npm cruft, regular cruft) + if (entry === '.git' || + entry === 'CVS' || + entry === '.svn' || + entry === '.hg' || + entry === '.lock-wscript' || + entry.match(/^\.wafpickle-[0-9]+$/) || + (this.parent && this.parent.packageRoot && this.basename === 'build' && + entry === 'config.gypi') || + entry === 'npm-debug.log' || + entry === '.npmrc' || + entry.match(/^\..*\.swp$/) || + entry === '.DS_Store' || + entry.match(/^\._/) + ) { + return false + } + + // in a node_modules folder, we only include bundled dependencies + // also, prevent packages in node_modules from being affected + // by rules set in the containing package, so that + // bundles don't get busted. + // Also, once in a bundle, everything is installed as-is + // To prevent infinite cycles in the case of cyclic deps that are + // linked with npm link, even in a bundle, deps are only bundled + // if they're not already present at a higher level. + if (this.bundleMagic) { + // bubbling up. stop here and allow anything the bundled pkg allows + if (entry.indexOf('/') !== -1) return true + + // never include the .bin. It's typically full of platform-specific + // stuff like symlinks and .cmd files anyway. + if (entry === '.bin') return false + + // the package root. + var p = this.parent + // the package before this one. + var pp = p && p.parent + + // if this entry has already been bundled, and is a symlink, + // and it is the *same* symlink as this one, then exclude it. + if (pp && pp.bundleLinks && this.bundleLinks && + pp.bundleLinks[entry] && + pp.bundleLinks[entry] === this.bundleLinks[entry]) { + return false + } + + // since it's *not* a symbolic link, if we're *already* in a bundle, + // then we should include everything. + if (pp && pp.package && pp.basename === 'node_modules') { + return true + } + + // only include it at this point if it's a bundleDependency + return this.isBundled(entry) + } + // if (this.bundled) return true + + return Packer.prototype.applyIgnores.call(this, entry, partial, entryObj) +} + function nameMatch (name) { return function (other) { return name === moduleName(other) } } -function pack_ (tarball, folder, tree, flatTree, pkg, cb) { +function pack_ (tarball, folder, tree, pkg, cb) { function InstancePacker (props) { BundledPacker.call(this, props) } @@ -81,18 +170,17 @@ function pack_ (tarball, folder, tree, flatTree, pkg, cb) { if (bd.indexOf(name) !== -1) return true var pkg = tree.children.filter(nameMatch(name))[0] if (!pkg) return false - var requiredBy = union([], pkg.package._requiredBy) + var requiredBy = [].concat(pkg.requiredBy) var seen = {} while (requiredBy.length) { - var req = requiredBy.shift() - if (seen[req]) continue - seen[req] = true - var reqPkg = flatTree[req] + var reqPkg = requiredBy.shift() + if (seen[reqPkg.path]) continue + seen[reqPkg.path] = true if (!reqPkg) continue if (reqPkg.parent === tree && bd.indexOf(moduleName(reqPkg)) !== -1) { return true } - requiredBy = union(requiredBy, reqPkg.package._requiredBy) + requiredBy = union(requiredBy, reqPkg.requiredBy) } return false } |