diff --git a/config-path.js b/config-path.js new file mode 100644 index 0000000..a5e389f --- /dev/null +++ b/config-path.js @@ -0,0 +1,33 @@ +const path = require('path'); +const userHome = require('user-home'); + +const env = process.env; +const name = 'js-v8flags'; + +function macos () { + const library = path.join(userHome, 'Library'); + return path.join(library, 'Caches', name); +} + +function windows () { + const appData = env.LOCALAPPDATA || path.join(userHome, 'AppData', 'Local'); + return path.join(appData, name, 'Cache'); +} + +// https://specifications.freedesktop.org/basedir-spec/basedir-spec-latest.html +function linux () { + const username = path.basename(userHome); + return path.join(env.XDG_CACHE_HOME || path.join(userHome, '.cache'), name); +} + +module.exports = function (platform) { + if (platform === 'darwin') { + return macos(); + } + + if (platform === 'win32') { + return windows(); + } + + return linux(); +}; diff --git a/index.js b/index.js index 40404d0..39a28a8 100644 --- a/index.js +++ b/index.js @@ -7,6 +7,7 @@ const fs = require('fs'); const path = require('path'); const crypto = require('crypto'); const execFile = require('child_process').execFile; +const configPath = require('./config-path.js')(process.platform); const env = process.env; const user = env.LOGNAME || env.USER || env.LNAME || env.USERNAME || ''; const exclusions = ['--help']; @@ -33,10 +34,12 @@ function openConfig (cb) { return tryOpenConfig(path.join(os.tmpdir(), configfile), cb); } - tryOpenConfig(path.join(userHome, configfile), function (err, fd) { - if (err) return tryOpenConfig(path.join(os.tmpdir(), configfile), cb); - return cb(null, fd); - }); + fs.mkdir(configPath, function () { + tryOpenConfig(path.join(configPath, configfile), function (err, fd) { + if (err) return tryOpenConfig(path.join(os.tmpdir(), configfile), cb); + return cb(null, fd); + }); + }) } function tryOpenConfig (configpath, cb) { @@ -131,3 +134,4 @@ module.exports = function (cb) { }; module.exports.configfile = configfile; +module.exports.configPath = configPath; diff --git a/test.js b/test.js index e132957..acceb25 100644 --- a/test.js +++ b/test.js @@ -16,6 +16,8 @@ function eraseHome() { delete env.USER; delete env.LNAME; delete env.USERNAME; + delete env.XDG_CACHE_HOME; + delete env.LOCALAPPDATA; } function setTemp(dir) { @@ -24,11 +26,9 @@ function setTemp(dir) { function cleanup () { var v8flags = require('./'); - var userHome = require('user-home'); - if (userHome === null) userHome = __dirname; var files = [ - path.resolve(userHome, v8flags.configfile), + path.resolve(v8flags.configPath, v8flags.configfile), path.resolve(os.tmpdir(), v8flags.configfile), ]; files.forEach(function (file) { @@ -47,7 +47,7 @@ describe('v8flags', function () { it('should cache and call back with the v8 flags for the running process', function (done) { var v8flags = require('./'); - var configfile = path.resolve(require('user-home'), v8flags.configfile); + var configfile = path.resolve(v8flags.configPath, v8flags.configfile); v8flags(function (err, flags) { expect(flags).to.be.a('array'); expect(fs.existsSync(configfile)).to.be.true; @@ -62,7 +62,7 @@ describe('v8flags', function () { it('should not append the file when multiple calls happen concurrently and the config file does not yet exist', function (done) { var v8flags = require('./'); - var configfile = path.resolve(require('user-home'), v8flags.configfile); + var configfile = path.resolve(v8flags.configPath, v8flags.configfile); async.parallel([v8flags, v8flags, v8flags], function (err, result) { v8flags(function (err2, res) { done(); @@ -83,7 +83,11 @@ describe('v8flags', function () { it('should fall back to writing to a temp dir if user home is unwriteable', function (done) { eraseHome(); env.HOME = path.join(__dirname, 'does-not-exist'); + // Clear require cached modules so the modified environment variable HOME is used + delete require.cache[require.resolve('./')]; + delete require.cache[require.resolve('./config-path.js')]; var v8flags = require('./'); + v8flags.configPath = env.HOME; var configfile = path.resolve(os.tmpdir(), v8flags.configfile); v8flags(function (err, flags) { expect(fs.existsSync(configfile)).to.be.true; @@ -133,6 +137,46 @@ describe('v8flags', function () { v8flags(function (err, flags) { expect(err).to.be.null; done(); - }) + }); + }); +}); + +describe('config-path', function () { + const moduleName = 'js-v8flags'; + + beforeEach(function() { + env.HOME = 'somehome'; + cleanup(); + }); + afterEach(cleanup); + + it('should return default linux path in other environments', function(done) { + delete require.cache[require.resolve('./config-path.js')]; + const configPath = require('./config-path.js')('other'); + + expect(configPath).to.equal( + path.join(env.HOME, '.cache', moduleName) + ); + done(); + }); + + it('should return default macos path in darwin environment', function(done) { + delete require.cache[require.resolve('./config-path.js')]; + const configPath = require('./config-path.js')('darwin'); + + expect(configPath).to.equal( + path.join(env.HOME, 'Library', 'Caches', moduleName) + ); + done(); + }); + + it('should return default windows path in win32 environment', function(done) { + delete require.cache[require.resolve('./config-path.js')]; + const configPath = require('./config-path.js')('win32'); + + expect(configPath).to.equal( + path.join(env.HOME, 'AppData', 'Local', moduleName, 'Cache') + ); + done(); }); });