Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

fix: respect cache flag in parent process #556

Merged
merged 10 commits into from
Apr 20, 2017
1 change: 0 additions & 1 deletion bin/nyc.js
Original file line number Diff line number Diff line change
Expand Up @@ -43,7 +43,6 @@ if (argv._[0] === 'report') {
if (config.all) nyc.addAllFiles()

var env = {
NYC_CACHE: argv.cache ? 'enable' : 'disable',
NYC_CONFIG: JSON.stringify(config),
NYC_CWD: process.cwd(),
NYC_ROOT_ID: nyc.rootId,
Expand Down
3 changes: 2 additions & 1 deletion bin/wrap.js
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,8 @@ process.env.NYC_PARENT_PID = process.pid

var config = {}
if (process.env.NYC_CONFIG) config = JSON.parse(process.env.NYC_CONFIG)
config.enableCache = process.env.NYC_CACHE === 'enable'
config.isChildProcess = true

config._processInfo = {
ppid: parentPid,
root: process.env.NYC_ROOT_ID
Expand Down
110 changes: 35 additions & 75 deletions index.js
Original file line number Diff line number Diff line change
@@ -1,25 +1,25 @@
/* global __coverage__ */
var arrify = require('arrify')
var debugLog = require('debug-log')('nyc')
var fs = require('fs')
var glob = require('glob')
var libCoverage = require('istanbul-lib-coverage')
var libHook = require('istanbul-lib-hook')
var libReport = require('istanbul-lib-report')
var libSourceMaps = require('istanbul-lib-source-maps')
var reports = require('istanbul-reports')
var mkdirp = require('mkdirp')
var Module = require('module')
var cachingTransform = require('caching-transform')
var path = require('path')
var rimraf = require('rimraf')
var onExit = require('signal-exit')
var resolveFrom = require('resolve-from')
var convertSourceMap = require('convert-source-map')
var md5hex = require('md5-hex')
var findCacheDir = require('find-cache-dir')
var js = require('default-require-extensions/js')
var testExclude = require('test-exclude')

const arrify = require('arrify')
const cachingTransform = require('caching-transform')
const debugLog = require('debug-log')('nyc')
const findCacheDir = require('find-cache-dir')
const fs = require('fs')
const glob = require('glob')
const js = require('default-require-extensions/js')
const libCoverage = require('istanbul-lib-coverage')
const libHook = require('istanbul-lib-hook')
const libReport = require('istanbul-lib-report')
const md5hex = require('md5-hex')
const mkdirp = require('mkdirp')
const Module = require('module')
const onExit = require('signal-exit')
const path = require('path')
const reports = require('istanbul-reports')
const resolveFrom = require('resolve-from')
const rimraf = require('rimraf')
const SourceMaps = require('./lib/source-maps')
const testExclude = require('test-exclude')

var ProcessInfo
try {
Expand Down Expand Up @@ -50,19 +50,21 @@ function NYC (config) {
this._showProcessTree = config.showProcessTree || false
this._eagerInstantiation = config.eager || false
this.cwd = config.cwd || process.cwd()

this.reporter = arrify(config.reporter || 'text')

this.cacheDirectory = config.cacheDir || findCacheDir({name: 'nyc', cwd: this.cwd})

this.enableCache = Boolean(this.cacheDirectory && (config.enableCache === true || process.env.NYC_CACHE === 'enable'))
this.cache = Boolean(this.cacheDirectory && config.cache)

this.exclude = testExclude({
cwd: this.cwd,
include: config.include,
exclude: config.exclude
})

this.sourceMaps = new SourceMaps({
cacheDirectory: this.cacheDirectory
})

// require extensions can be provided as config in package.json.
this.require = arrify(config.require)

Expand All @@ -78,11 +80,8 @@ function NYC (config) {
return transforms
}.bind(this), {})

this.sourceMapCache = libSourceMaps.createSourceMapStore()

this.hookRunInContext = config.hookRunInContext
this.hashCache = {}
this.loadedMaps = null
this.fakeRequire = null

this.processInfo = new ProcessInfo(config && config._processInfo)
Expand All @@ -103,7 +102,9 @@ NYC.prototype._createTransform = function (ext) {
return hash
},
cacheDir: this.cacheDirectory,
disableCache: !this.enableCache,
// when running --all (in the parent process) we should
// not load source from cache.
disableCache: !(this.cache && this.config.isChildProcess),
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We should probably add a test for this statement

ext: ext
}
if (this._eagerInstantiation) {
Expand Down Expand Up @@ -271,7 +272,7 @@ NYC.prototype._transformFactory = function (cacheDir) {
var filename = metadata.filename
var sourceMap = null

if (_this._sourceMap) sourceMap = _this._handleSourceMap(cacheDir, code, hash, filename)
if (_this._sourceMap) sourceMap = _this.sourceMaps.extractAndRegister(code, hash, filename)

try {
instrumented = instrumenter.instrumentSync(code, filename, sourceMap)
Expand All @@ -289,19 +290,6 @@ NYC.prototype._transformFactory = function (cacheDir) {
}
}

NYC.prototype._handleSourceMap = function (cacheDir, code, hash, filename) {
var sourceMap = convertSourceMap.fromSource(code) || convertSourceMap.fromMapFileSource(code, path.dirname(filename))
if (sourceMap) {
if (hash) {
var mapPath = path.join(cacheDir, hash + '.map')
fs.writeFileSync(mapPath, sourceMap.toJSON())
} else {
this.sourceMapCache.registerMap(filename, sourceMap.sourcemap)
}
}
return sourceMap
}

NYC.prototype._handleJs = function (code, filename) {
var relFile = path.relative(this.cwd, filename)
// ensure the path has correct casing (see istanbuljs/nyc#269 and nodejs/node#6624)
Expand Down Expand Up @@ -333,7 +321,7 @@ NYC.prototype.cleanup = function () {
}

NYC.prototype.clearCache = function () {
if (this.enableCache) {
if (this.cache) {
rimraf.sync(this.cacheDirectory)
}
}
Expand Down Expand Up @@ -379,14 +367,14 @@ NYC.prototype.writeCoverageFile = function () {
var coverage = coverageFinder()
if (!coverage) return

if (this.enableCache) {
if (this.cache) {
Object.keys(coverage).forEach(function (absFile) {
if (this.hashCache[absFile] && coverage[absFile]) {
coverage[absFile].contentHash = this.hashCache[absFile]
}
}, this)
} else {
coverage = this.sourceMapTransform(coverage)
coverage = this.sourceMaps.remapCoverage(coverage)
}

var id = this.generateUniqueID()
Expand All @@ -411,13 +399,6 @@ NYC.prototype.writeCoverageFile = function () {
)
}

NYC.prototype.sourceMapTransform = function (obj) {
var transformed = this.sourceMapCache.transformCoverage(
libCoverage.createCoverageMap(obj)
)
return transformed.map.data
}

function coverageFinder () {
var coverage = global.__coverage__
if (typeof __coverage__ === 'object') coverage = __coverage__
Expand Down Expand Up @@ -497,10 +478,6 @@ NYC.prototype.loadReports = function (filenames) {
var _this = this
var files = filenames || fs.readdirSync(this.tempDirectory())

var cacheDir = _this.cacheDirectory

var loadedMaps = this.loadedMaps || (this.loadedMaps = {})

return files.map(function (f) {
var report
try {
Expand All @@ -512,25 +489,8 @@ NYC.prototype.loadReports = function (filenames) {
return {}
}

Object.keys(report).forEach(function (absFile) {
var fileReport = report[absFile]
if (fileReport && fileReport.contentHash) {
var hash = fileReport.contentHash
if (!(hash in loadedMaps)) {
try {
var mapPath = path.join(cacheDir, hash + '.map')
loadedMaps[hash] = JSON.parse(fs.readFileSync(mapPath, 'utf8'))
} catch (e) {
// set to false to avoid repeatedly trying to load the map
loadedMaps[hash] = false
}
}
if (loadedMaps[hash]) {
_this.sourceMapCache.registerMap(absFile, loadedMaps[hash])
}
}
})
report = _this.sourceMapTransform(report)
_this.sourceMaps.reloadCachedSourceMaps(report)
report = _this.sourceMaps.remapCoverage(report)
return report
})
}
Expand Down
56 changes: 56 additions & 0 deletions lib/source-maps.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,56 @@
var convertSourceMap = require('convert-source-map')
var libCoverage = require('istanbul-lib-coverage')
var libSourceMaps = require('istanbul-lib-source-maps')
var fs = require('fs')
var path = require('path')
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

You have consts elsewhere, but vars here. I'm guessing we're going to Node v4+ soon so I'd like to be consistent :)

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

👍 will make more consistent usage of const.


// TODO: write unit tests for source-maps,
function SourceMaps (opts) {
this.cacheDirectory = opts.cacheDirectory
this.sourceMapCache = libSourceMaps.createSourceMapStore()
this.loadedMaps = {}
}

SourceMaps.prototype.extractAndRegister = function (code, hash, filename) {
var sourceMap = convertSourceMap.fromSource(code) || convertSourceMap.fromMapFileSource(code, path.dirname(filename))
if (sourceMap) {
if (hash) {
var mapPath = path.join(this.cacheDir, hash + '.map')
fs.writeFileSync(mapPath, sourceMap.toJSON())
} else {
this.sourceMapCache.registerMap(filename, sourceMap.sourcemap)
}
}
return sourceMap
}

SourceMaps.prototype.remapCoverage = function (obj) {
var transformed = this.sourceMapCache.transformCoverage(
libCoverage.createCoverageMap(obj)
)
return transformed.map.data
}

SourceMaps.prototype.reloadCachedSourceMaps = function (report) {
var _this = this
Object.keys(report).forEach(function (absFile) {
var fileReport = report[absFile]
if (fileReport && fileReport.contentHash) {
var hash = fileReport.contentHash
if (!(hash in _this.loadedMaps)) {
try {
var mapPath = path.join(_this.cacheDirectory, hash + '.map')
_this.loadedMaps[hash] = JSON.parse(fs.readFileSync(mapPath, 'utf8'))
} catch (e) {
// set to false to avoid repeatedly trying to load the map
_this.loadedMaps[hash] = false
}
}
if (_this.loadedMaps[hash]) {
_this.sourceMapCache.registerMap(absFile, _this.loadedMaps[hash])
}
}
})
}

module.exports = SourceMaps