diff --git a/bin/wrap.js b/bin/wrap.js index b7d995ffc..e2c0a8deb 100644 --- a/bin/wrap.js +++ b/bin/wrap.js @@ -8,6 +8,7 @@ config.isChildProcess = true config._processInfo = { pid: process.pid, ppid: process.ppid, + parent: process.env.NYC_PROCESS_ID, root: process.env.NYC_ROOT_ID } if (process.env.NYC_PROCESSINFO_EXTERNAL_ID) { diff --git a/index.js b/index.js index 006ff268a..84e370a6c 100755 --- a/index.js +++ b/index.js @@ -312,6 +312,7 @@ NYC.prototype._wrapExit = function () { } NYC.prototype.wrap = function (bin) { + process.env.NYC_PROCESS_ID = this.processInfo.uuid this._addRequireHooks() this._wrapExit() this._loadAdditionalModules() @@ -341,7 +342,7 @@ NYC.prototype.writeCoverageFile = function () { coverage = this.sourceMaps.remapCoverage(coverage) } - var id = this.generateUniqueID() + var id = this.processInfo.uuid var coverageFilename = path.resolve(this.tempDirectory(), id + '.json') fs.writeFileSync( @@ -355,6 +356,7 @@ NYC.prototype.writeCoverageFile = function () { } this.processInfo.coverageFilename = coverageFilename + this.processInfo.files = Object.keys(coverage) fs.writeFileSync( path.resolve(this.processInfoDirectory(), id + '.json'), @@ -421,8 +423,7 @@ NYC.prototype.writeProcessIndex = function () { 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')) - // on thiis first read pass, also map the pids to uuids - info.uuid = path.basename(f, '.json') + info.children = [] pidToUid.set(info.uuid, info.pid) pidToUid.set(info.pid, info.uuid) infoByUid.set(info.uuid, info) @@ -436,34 +437,17 @@ NYC.prototype.writeProcessIndex = function () { }).filter(Boolean) // create all the parent-child links and write back the updated info - const needsUpdate = new Set() infos.forEach(info => { - if (info.ppid && info.ppid !== '0' && !info.parent) { - info.parent = pidToUid.get(info.ppid) - needsUpdate.add(info) - } if (info.parent) { const parentInfo = infoByUid.get(info.parent) if (parentInfo.children.indexOf(info.uuid) === -1) { parentInfo.children.push(info.uuid) - needsUpdate.add(parentInfo) } } }) // figure out which files were touched by each process. const files = infos.reduce((files, info) => { - if (!info.files) { - try { - info.files = Object.keys(JSON.parse(fs.readFileSync( - path.resolve(this.tempDirectory(), info.coverageFilename), - 'utf-8' - ))) - } catch (er) { - return files - } - needsUpdate.add(info) - } info.files.forEach(f => { files[f] = files[f] || [] files[f].push(info.uuid) @@ -478,15 +462,16 @@ NYC.prototype.writeProcessIndex = function () { 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 } } - if (info.children && info.children.length) { - index.processes[info.uuid].children = Array.from(info.children) - } + index.processes[info.uuid].children = Array.from(info.children || []) return index }, { processes: {}, files: files, externalIds: {} }) @@ -502,12 +487,6 @@ NYC.prototype.writeProcessIndex = function () { } }) - needsUpdate.forEach(info => { - fs.writeFileSync( - path.resolve(dir, info.uuid + '.json'), JSON.stringify(info) - ) - }) - fs.writeFileSync(path.resolve(dir, 'index.json'), JSON.stringify(index)) } diff --git a/lib/process.js b/lib/process.js index fb62ab6a9..608b5ec29 100644 --- a/lib/process.js +++ b/lib/process.js @@ -1,9 +1,12 @@ 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 @@ -12,14 +15,14 @@ function ProcessInfo (defaults) { this.ppid = null this.root = null this.coverageFilename = null - this.nodes = [] // list of children, filled by buildProcessTree() - this.children = [] // just uuids, not full nodes - - this._coverageMap = null for (var key in defaults) { this[key] = defaults[key] } + + if (!this.uuid) { + this.uuid = uuid() + } } Object.defineProperty(ProcessInfo.prototype, 'label', { @@ -37,7 +40,7 @@ Object.defineProperty(ProcessInfo.prototype, 'label', { }) ProcessInfo.buildProcessTree = function (infos) { - var treeRoot = new ProcessInfo({ _label: 'nyc' }) + var treeRoot = new ProcessInfo({ _label: 'nyc', nodes: [] }) var nodes = { } infos = infos.sort(function (a, b) { @@ -45,6 +48,7 @@ ProcessInfo.buildProcessTree = function (infos) { }) infos.forEach(function (p) { + p.nodes = [] nodes[p.root + ':' + p.pid] = p }) diff --git a/test/processinfo.js b/test/processinfo.js index 814f050d3..f3a7b151f 100644 --- a/test/processinfo.js +++ b/test/processinfo.js @@ -52,8 +52,8 @@ t.test('validate the created processinfo data', t => { throw er const procInfoData = JSON.parse(procInfoJson) t.match(procInfoData, { - pid: /^[0-9]+$/, - ppid: /^[0-9]+$/, + pid: Number, + ppid: Number, uuid: f.replace(/\.json$/, ''), argv: [ node, @@ -65,10 +65,7 @@ t.test('validate the created processinfo data', t => { time: Number, root: /^[0-9a-f]{8}-(?:[0-9a-f]{4}-){3}[0-9a-f]{12}$/, coverageFilename: resolve(fixturesCLI, tmp, f), - nodes: [], - _coverageMap: null, files: [ resolvedJS ], - children: Array, }) }) })