@@ -22,27 +22,64 @@ if (!global.setImmediate || !require('timers').setImmediate) {
2222}
2323
2424var spawn = require ( 'child_process' ) . spawn
25+ const spawnSync = require ( 'child_process' ) . spawnSync
2526var path = require ( 'path' )
2627
28+ // space these out to help prevent collisions
29+ const testId = 3 * ( + process . env . TAP_CHILD_ID || 0 )
30+
2731// provide a working dir unique to each test
2832const main = require . main . filename
29- exports . pkg = path . resolve ( path . dirname ( main ) , path . basename ( main , '.js' ) )
33+ const testName = path . basename ( main , '.js' )
34+ exports . pkg = path . resolve ( path . dirname ( main ) , testName )
35+ var commonCache = path . resolve ( __dirname , 'npm_cache_' + testName )
36+ exports . cache = commonCache
37+
3038const mkdirp = require ( 'mkdirp' )
3139const rimraf = require ( 'rimraf' )
40+ rimraf . sync ( exports . pkg )
41+ rimraf . sync ( commonCache )
3242mkdirp . sync ( exports . pkg )
43+ mkdirp . sync ( commonCache )
44+ // if we're in sudo mode, make sure that the cache is not root-owned
45+ const isRoot = process . getuid && process . getuid ( ) === 0
46+ const isSudo = isRoot && process . env . SUDO_UID && process . env . SUDO_GID
47+ if ( isSudo ) {
48+ const sudoUid = + process . env . SUDO_UID
49+ const sudoGid = + process . env . SUDO_GID
50+ fs . chownSync ( commonCache , sudoUid , sudoGid )
51+ }
52+
53+ const returnCwd = path . dirname ( __dirname )
54+ const find = require ( 'which' ) . sync ( 'find' )
3355require ( 'tap' ) . teardown ( ( ) => {
56+ // work around windows folder locking
57+ process . chdir ( returnCwd )
3458 try {
35- rimraf . sync ( exports . pkg )
59+ if ( isSudo ) {
60+ // running tests as sudo. ensure we didn't leave any root-owned
61+ // files in the cache by mistake.
62+ const args = [ commonCache , '-uid' , '0' ]
63+ const found = spawnSync ( find , args )
64+ const output = found && found . stdout && found . stdout . toString ( )
65+ if ( output . length ) {
66+ const er = new Error ( 'Root-owned files left in cache!' )
67+ er . testName = main
68+ er . files = output . trim ( ) . split ( '\n' )
69+ throw er
70+ }
71+ }
72+ if ( ! process . env . NO_TEST_CLEANUP ) {
73+ rimraf . sync ( exports . pkg )
74+ rimraf . sync ( commonCache )
75+ }
3676 } catch ( e ) {
3777 if ( process . platform !== 'win32' ) {
3878 throw e
3979 }
4080 }
4181} )
4282
43- // space these out to help prevent collisions
44- const testId = 3 * ( + process . env . TAP_CHILD_ID || 0 )
45-
4683var port = exports . port = 15443 + testId
4784exports . registry = 'http://localhost:' + port
4885
@@ -59,8 +96,8 @@ ourenv.npm_config_progress = 'false'
5996ourenv . npm_config_metrics = 'false'
6097ourenv . npm_config_audit = 'false'
6198
62- var npm_config_cache = path . resolve ( __dirname , 'npm_cache_' + testId )
63- ourenv . npm_config_cache = exports . npm_config_cache = npm_config_cache
99+ ourenv . npm_config_unsafe_perm = 'true'
100+ ourenv . npm_config_cache = commonCache
64101ourenv . npm_config_userconfig = exports . npm_config_userconfig = configCommon . userconfig
65102ourenv . npm_config_globalconfig = exports . npm_config_globalconfig = configCommon . globalconfig
66103ourenv . npm_config_global_style = 'false'
@@ -94,7 +131,10 @@ exports.npm = function (cmd, opts, cb) {
94131 opts . env = opts . env || process . env
95132 if ( opts . env . _storage ) opts . env = Object . assign ( { } , opts . env . _storage )
96133 if ( ! opts . env . npm_config_cache ) {
97- opts . env . npm_config_cache = npm_config_cache
134+ opts . env . npm_config_cache = commonCache
135+ }
136+ if ( ! opts . env . npm_config_unsafe_perm ) {
137+ opts . env . npm_config_unsafe_perm = 'true'
98138 }
99139 if ( ! opts . env . npm_config_send_metrics ) {
100140 opts . env . npm_config_send_metrics = 'false'
0 commit comments