/* eslint-disable node-core/require-common-first, node-core/required-modules */ 'use strict'; const { execSync } = require('child_process'); const fs = require('fs'); const path = require('path'); const { debuglog } = require('util'); const debug = debuglog('test/tmpdir'); function rimrafSync(pathname, { spawn = true } = {}) { const st = (() => { try { return fs.lstatSync(pathname); } catch (e) { if (fs.existsSync(pathname)) throw new Error(`Something wonky happened rimrafing ${pathname}`); debug(e); } })(); // If (!st) then nothing to do. if (!st) { return; } // On Windows first try to delegate rmdir to a shell. if (spawn && process.platform === 'win32' && st.isDirectory()) { try { // Try `rmdir` first. execSync(`rmdir /q /s ${pathname}`, { timout: 1000 }); } catch (e) { // Attempt failed. Log and carry on. debug(e); } } try { if (st.isDirectory()) rmdirSync(pathname, null); else fs.unlinkSync(pathname); } catch (e) { debug(e); switch (e.code) { case 'ENOENT': // It's not there anymore. Work is done. Exiting. return; case 'EPERM': // This can happen, try again with `rmdirSync`. break; case 'EISDIR': // Got 'EISDIR' even after testing `st.isDirectory()`... // Try again with `rmdirSync`. break; default: throw e; } rmdirSync(pathname, e); } } function rmdirSync(p, originalEr) { try { fs.rmdirSync(p); } catch (e) { if (e.code === 'ENOTDIR') throw originalEr; if (e.code === 'ENOTEMPTY' || e.code === 'EEXIST' || e.code === 'EPERM') { const enc = process.platform === 'linux' ? 'buffer' : 'utf8'; fs.readdirSync(p, enc).forEach((f) => { if (f instanceof Buffer) { const buf = Buffer.concat([Buffer.from(p), Buffer.from(path.sep), f]); rimrafSync(buf); } else { rimrafSync(path.join(p, f)); } }); fs.rmdirSync(p); } } } const testRoot = process.env.NODE_TEST_DIR ? fs.realpathSync(process.env.NODE_TEST_DIR) : path.resolve(__dirname, '..'); // Using a `.` prefixed name, which is the convention for "hidden" on POSIX, // gets tools to ignore it by default or by simple rules, especially eslint. const tmpdirName = '.tmp.' + (process.env.TEST_SERIAL_ID || process.env.TEST_THREAD_ID || '0'); const tmpPath = path.join(testRoot, tmpdirName); function refresh(opts = {}) { rimrafSync(this.path, opts); fs.mkdirSync(this.path); } module.exports = { path: tmpPath, refresh };