diff --git a/index.js b/index.js index 2310f57e5..ffe1b50ee 100755 --- a/index.js +++ b/index.js @@ -10,6 +10,7 @@ const glob = require('glob') const Hash = require('./lib/hash') const libCoverage = require('istanbul-lib-coverage') const libHook = require('istanbul-lib-hook') +const { ProcessInfo, ProcessDB } = require('istanbul-lib-processinfo') const libReport = require('istanbul-lib-report') const mkdirp = require('make-dir') const Module = require('module') @@ -24,8 +25,6 @@ const util = require('util') const debugLog = util.debuglog('nyc') -const ProcessInfo = require('./lib/process.js') - /* istanbul ignore next */ if (/self-coverage/.test(__dirname)) { require('../self-coverage-helper') @@ -87,7 +86,9 @@ class NYC { this.hookRunInThisContext = config.hookRunInThisContext this.fakeRequire = null - this.processInfo = new ProcessInfo(config && config._processInfo) + this.processInfo = new ProcessInfo(Object.assign({}, config._processInfo, { + directory: path.resolve(this.tempDirectory(), 'processinfo') + })) this.hashCache = {} } @@ -308,7 +309,7 @@ class NYC { mkdirp.sync(this.tempDirectory()) if (this.cache) mkdirp.sync(this.cacheDirectory) - mkdirp.sync(this.processInfoDirectory()) + mkdirp.sync(this.processInfo.directory) } reset () { @@ -364,12 +365,7 @@ class NYC { this.processInfo.coverageFilename = coverageFilename this.processInfo.files = Object.keys(coverage) - - fs.writeFileSync( - path.resolve(this.processInfoDirectory(), id + '.json'), - JSON.stringify(this.processInfo), - 'utf-8' - ) + this.processInfo.save() } getCoverageMapFromAllCoverageFiles (baseDirectory) { @@ -412,84 +408,14 @@ class NYC { } } - // XXX(@isaacs) Index generation should move to istanbul-lib-processinfo writeProcessIndex () { - const dir = this.processInfoDirectory() - const pidToUid = new Map() - const infoByUid = new Map() - const eidToUid = new Map() - const infos = fs.readdirSync(dir).filter(f => f !== 'index.json').map(f => { - try { - const info = JSON.parse(fs.readFileSync(path.resolve(dir, f), 'utf-8')) - info.children = [] - pidToUid.set(info.uuid, info.pid) - pidToUid.set(info.pid, info.uuid) - infoByUid.set(info.uuid, info) - if (info.externalId) { - eidToUid.set(info.externalId, info.uuid) - } - return info - } catch (er) { - return null - } - }).filter(Boolean) - - // create all the parent-child links and write back the updated info - infos.forEach(info => { - if (info.parent) { - const parentInfo = infoByUid.get(info.parent) - if (parentInfo && !parentInfo.children.includes(info.uuid)) { - parentInfo.children.push(info.uuid) - } - } - }) - - // figure out which files were touched by each process. - const files = infos.reduce((files, info) => { - info.files.forEach(f => { - files[f] = files[f] || [] - files[f].push(info.uuid) - }) - return files - }, {}) - - // build the actual index! - const index = infos.reduce((index, info) => { - index.processes[info.uuid] = {} - index.processes[info.uuid].parent = info.parent - if (info.externalId) { - if (index.externalIds[info.externalId]) { - throw new Error(`External ID ${info.externalId} used by multiple processes`) - } - index.processes[info.uuid].externalId = info.externalId - index.externalIds[info.externalId] = { - root: info.uuid, - children: info.children - } - } - index.processes[info.uuid].children = Array.from(info.children) - return index - }, { processes: {}, files: files, externalIds: {} }) - - // flatten the descendant sets of all the externalId procs - Object.keys(index.externalIds).forEach(eid => { - const { children } = index.externalIds[eid] - // push the next generation onto the list so we accumulate them all - for (let i = 0; i < children.length; i++) { - const nextGen = index.processes[children[i]].children - if (nextGen && nextGen.length) { - children.push(...nextGen.filter(uuid => children.indexOf(uuid) === -1)) - } - } - }) - - fs.writeFileSync(path.resolve(dir, 'index.json'), JSON.stringify(index)) + const db = new ProcessDB(this.processInfo.directory) + db.writeIndex() } showProcessTree () { - var processTree = ProcessInfo.buildProcessTree(this._loadProcessInfos()) - - console.log(processTree.render(this)) + const db = new ProcessDB(this.processInfo.directory) + console.log(db.renderTree(this)) } checkCoverage (thresholds, perFile) { @@ -521,28 +447,6 @@ class NYC { }) } - _loadProcessInfos () { - return fs.readdirSync(this.processInfoDirectory()).map(f => { - let data - try { - data = JSON.parse(fs.readFileSync( - path.resolve(this.processInfoDirectory(), f), - 'utf-8' - )) - } catch (e) { // handle corrupt JSON output. - return null - } - if (f !== 'index.json') { - data.nodes = [] - data = new ProcessInfo(data) - } - return { file: path.basename(f, '.json'), data: data } - }).filter(Boolean).reduce((infos, info) => { - infos[info.file] = info.data - return infos - }, {}) - } - eachReport (filenames, iterator, baseDirectory) { baseDirectory = baseDirectory || this.tempDirectory() @@ -588,10 +492,6 @@ class NYC { reportDirectory () { return path.resolve(this.cwd, this._reportDir) } - - processInfoDirectory () { - return path.resolve(this.tempDirectory(), 'processinfo') - } } module.exports = NYC diff --git a/lib/process.js b/lib/process.js deleted file mode 100644 index 37b1e91dc..000000000 --- a/lib/process.js +++ /dev/null @@ -1,91 +0,0 @@ -const archy = require('archy') -const libCoverage = require('istanbul-lib-coverage') -const uuid = require('uuid/v4') - -function ProcessInfo (defaults) { - defaults = defaults || {} - - this.uuid = null - this.parent = null - this.pid = String(process.pid) - this.argv = process.argv - this.execArgv = process.execArgv - this.cwd = process.cwd() - this.time = Date.now() - this.ppid = null - this.coverageFilename = null - - for (var key in defaults) { - this[key] = defaults[key] - } - - if (!this.uuid) { - this.uuid = uuid() - } -} - -Object.defineProperty(ProcessInfo.prototype, 'label', { - get: function () { - if (this._label) { - return this._label - } - - var covInfo = '' - if (this._coverageMap) { - covInfo = '\n ' + this._coverageMap.getCoverageSummary().lines.pct + ' % Lines' - } - return this.argv.join(' ') + covInfo - } -}) - -ProcessInfo.buildProcessTree = function (infos) { - const treeRoot = new ProcessInfo({ _label: 'nyc', nodes: [] }) - const index = infos.index - for (const id in index.processes) { - const node = infos[id] - if (!node) { - throw new Error(`Invalid entry in processinfo index: ${id}`) - } - const idx = index.processes[id] - node.nodes = idx.children.map(id => infos[id]).sort((a, b) => a.time - b.time) - if (!node.parent) { - treeRoot.nodes.push(node) - } - } - - return treeRoot -} - -ProcessInfo.prototype.getCoverageMap = function (merger) { - if (this._coverageMap) { - return this._coverageMap - } - - var childMaps = this.nodes.map(function (child) { - return child.getCoverageMap(merger) - }) - - this._coverageMap = merger([this.coverageFilename], childMaps) - - return this._coverageMap -} - -ProcessInfo.prototype.render = function (nyc) { - this.getCoverageMap(function (filenames, maps) { - var map = libCoverage.createCoverageMap({}) - - nyc.eachReport(filenames, function (report) { - map.merge(report) - }) - - maps.forEach(function (otherMap) { - map.merge(otherMap) - }) - - return map - }) - - return archy(this) -} - -module.exports = ProcessInfo diff --git a/package-lock.json b/package-lock.json index eb10c4aab..bcc8fb94c 100644 --- a/package-lock.json +++ b/package-lock.json @@ -2649,14 +2649,13 @@ } }, "istanbul-lib-processinfo": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/istanbul-lib-processinfo/-/istanbul-lib-processinfo-1.0.0.tgz", - "integrity": "sha512-FY0cPmWa4WoQNlvB8VOcafiRoB5nB+l2Pz2xGuXHRSy1KM8QFOYfz/rN+bGMCAeejrY3mrpF5oJHcN0s/garCg==", - "dev": true, + "version": "github:istanbuljs/istanbul-lib-processinfo#c6cfcf6bfee8249223fb72d8b7465de1ce944c91", + "from": "github:istanbuljs/istanbul-lib-processinfo#master", "requires": { "archy": "^1.0.0", "cross-spawn": "^6.0.5", - "istanbul-lib-coverage": "^2.0.3", + "istanbul-lib-coverage": "^3.0.0-alpha.0", + "make-dir": "^3.0.0", "rimraf": "^2.6.3", "uuid": "^3.3.2" }, @@ -2665,7 +2664,6 @@ "version": "6.0.5", "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-6.0.5.tgz", "integrity": "sha512-eTVLrBSt7fjbDygz805pMnstIs2VTBNkRm0qxZd+M7A5XDdxVRWO5MxGBXZhjY4cqLYLdtrGqRf8mBPmzwSpWQ==", - "dev": true, "requires": { "nice-try": "^1.0.4", "path-key": "^2.0.1", @@ -2674,17 +2672,10 @@ "which": "^1.2.9" } }, - "istanbul-lib-coverage": { - "version": "2.0.5", - "resolved": "https://registry.npmjs.org/istanbul-lib-coverage/-/istanbul-lib-coverage-2.0.5.tgz", - "integrity": "sha512-8aXznuEPCJvGnMSRft4udDRDtb1V3pkQkMMI5LI+6HuQz5oQ4J2UFn1H82raA3qJtyOLkkwVqICBQkjnGtn5mA==", - "dev": true - }, "semver": { "version": "5.7.0", "resolved": "https://registry.npmjs.org/semver/-/semver-5.7.0.tgz", - "integrity": "sha512-Ya52jSX2u7QKghxeoFGpLwCtGlt7j0oY9DYb5apt9nPlJ42ID+ulTXESnt/qAQcoSERyZ5sl3LDIOw0nAn/5DA==", - "dev": true + "integrity": "sha512-Ya52jSX2u7QKghxeoFGpLwCtGlt7j0oY9DYb5apt9nPlJ42ID+ulTXESnt/qAQcoSERyZ5sl3LDIOw0nAn/5DA==" } } }, @@ -3344,8 +3335,7 @@ "nice-try": { "version": "1.0.5", "resolved": "https://registry.npmjs.org/nice-try/-/nice-try-1.0.5.tgz", - "integrity": "sha512-1nh45deeb5olNY7eX82BkPO7SSxR5SSYJiPTrTdFUVYwAl8CKMA5N9PjTYkHiRjisVcxcQ1HXdLhx2qxxJzLNQ==", - "dev": true + "integrity": "sha512-1nh45deeb5olNY7eX82BkPO7SSxR5SSYJiPTrTdFUVYwAl8CKMA5N9PjTYkHiRjisVcxcQ1HXdLhx2qxxJzLNQ==" }, "node-modules-regexp": { "version": "1.0.0", @@ -3948,8 +3938,7 @@ "path-key": { "version": "2.0.1", "resolved": "https://registry.npmjs.org/path-key/-/path-key-2.0.1.tgz", - "integrity": "sha1-QRyttXTFoUDTpLGRDUDYDMn0C0A=", - "dev": true + "integrity": "sha1-QRyttXTFoUDTpLGRDUDYDMn0C0A=" }, "path-parse": { "version": "1.0.6", @@ -4482,7 +4471,6 @@ "version": "1.2.0", "resolved": "https://registry.npmjs.org/shebang-command/-/shebang-command-1.2.0.tgz", "integrity": "sha1-RKrGW2lbAzmJaMOfNj/uXer98eo=", - "dev": true, "requires": { "shebang-regex": "^1.0.0" } @@ -4490,8 +4478,7 @@ "shebang-regex": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/shebang-regex/-/shebang-regex-1.0.0.tgz", - "integrity": "sha1-2kL0l0DAtC2yypcoVxyxkMmO/qM=", - "dev": true + "integrity": "sha1-2kL0l0DAtC2yypcoVxyxkMmO/qM=" }, "signal-exit": { "version": "3.0.2", @@ -5420,6 +5407,19 @@ "bundled": true, "dev": true }, + "cross-spawn": { + "version": "6.0.5", + "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-6.0.5.tgz", + "integrity": "sha512-eTVLrBSt7fjbDygz805pMnstIs2VTBNkRm0qxZd+M7A5XDdxVRWO5MxGBXZhjY4cqLYLdtrGqRf8mBPmzwSpWQ==", + "dev": true, + "requires": { + "nice-try": "^1.0.4", + "path-key": "^2.0.1", + "semver": "^5.5.0", + "shebang-command": "^1.2.0", + "which": "^1.2.9" + } + }, "csstype": { "version": "2.6.4", "bundled": true, @@ -5621,6 +5621,25 @@ "bundled": true, "dev": true }, + "istanbul-lib-coverage": { + "version": "2.0.5", + "resolved": "https://registry.npmjs.org/istanbul-lib-coverage/-/istanbul-lib-coverage-2.0.5.tgz", + "integrity": "sha512-8aXznuEPCJvGnMSRft4udDRDtb1V3pkQkMMI5LI+6HuQz5oQ4J2UFn1H82raA3qJtyOLkkwVqICBQkjnGtn5mA==", + "dev": true + }, + "istanbul-lib-processinfo": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/istanbul-lib-processinfo/-/istanbul-lib-processinfo-1.0.0.tgz", + "integrity": "sha512-FY0cPmWa4WoQNlvB8VOcafiRoB5nB+l2Pz2xGuXHRSy1KM8QFOYfz/rN+bGMCAeejrY3mrpF5oJHcN0s/garCg==", + "dev": true, + "requires": { + "archy": "^1.0.0", + "cross-spawn": "^6.0.5", + "istanbul-lib-coverage": "^2.0.3", + "rimraf": "^2.6.3", + "uuid": "^3.3.2" + } + }, "js-tokens": { "version": "3.0.2", "bundled": true, @@ -5887,6 +5906,12 @@ "object-assign": "^4.1.1" } }, + "semver": { + "version": "5.7.0", + "resolved": "https://registry.npmjs.org/semver/-/semver-5.7.0.tgz", + "integrity": "sha512-Ya52jSX2u7QKghxeoFGpLwCtGlt7j0oY9DYb5apt9nPlJ42ID+ulTXESnt/qAQcoSERyZ5sl3LDIOw0nAn/5DA==", + "dev": true + }, "signal-exit": { "version": "3.0.2", "bundled": true, diff --git a/package.json b/package.json index 694c2a4c5..322c382a3 100644 --- a/package.json +++ b/package.json @@ -68,7 +68,6 @@ "author": "Ben Coe ", "license": "ISC", "dependencies": { - "archy": "^1.0.0", "caching-transform": "^4.0.0", "convert-source-map": "^1.6.0", "cp-file": "^7.0.0", @@ -79,6 +78,7 @@ "istanbul-lib-coverage": "^3.0.0-alpha.0", "istanbul-lib-hook": "^3.0.0-alpha.0", "istanbul-lib-instrument": "^4.0.0-alpha.0", + "istanbul-lib-processinfo": "istanbuljs/istanbul-lib-processinfo#master", "istanbul-lib-report": "^3.0.0-alpha.0", "istanbul-lib-source-maps": "^4.0.0-alpha.0", "istanbul-reports": "^3.0.0-alpha.1", diff --git a/tap-snapshots/test-nyc-integration.js-TAP.test.js b/tap-snapshots/test-nyc-integration.js-TAP.test.js index ffe6bfc8b..46353911f 100644 --- a/tap-snapshots/test-nyc-integration.js-TAP.test.js +++ b/tap-snapshots/test-nyc-integration.js-TAP.test.js @@ -185,6 +185,7 @@ All files | 90.91 | 70 | 100 | 100 | selfspawn-fibonacci.js | 90.91 | 70 | 100 | 100 | 4,25,27 ------------------------|---------|----------|---------|---------|------------------- nyc +│ 100 % Lines └─┬ node ./selfspawn-fibonacci.js 5 │ 100 % Lines ├─┬ node ./selfspawn-fibonacci.js 4