Install: avoid race conditions when creating directories (#1358)

This commit is contained in:
ajhool 2018-08-29 04:20:26 -04:00 committed by Lovell Fuller
parent 5bed3a7d52
commit bf3254cb16
5 changed files with 50 additions and 12 deletions

View File

@ -4,6 +4,7 @@ const fs = require('fs');
const path = require('path'); const path = require('path');
const copyFileSync = require('fs-copy-file-sync'); const copyFileSync = require('fs-copy-file-sync');
const libvips = require('../lib/libvips');
const npmLog = require('npmlog'); const npmLog = require('npmlog');
if (process.platform === 'win32') { if (process.platform === 'win32') {
@ -11,8 +12,8 @@ if (process.platform === 'win32') {
const buildReleaseDir = path.join(buildDir, 'Release'); const buildReleaseDir = path.join(buildDir, 'Release');
npmLog.info('sharp', `Creating ${buildReleaseDir}`); npmLog.info('sharp', `Creating ${buildReleaseDir}`);
try { try {
fs.mkdirSync(buildDir); libvips.mkdirSync(buildDir);
fs.mkdirSync(buildReleaseDir); libvips.mkdirSync(buildReleaseDir);
} catch (err) {} } catch (err) {}
const vendorLibDir = path.join(__dirname, '..', 'vendor', 'lib'); const vendorLibDir = path.join(__dirname, '..', 'vendor', 'lib');
npmLog.info('sharp', `Copying DLLs from ${vendorLibDir} to ${buildReleaseDir}`); npmLog.info('sharp', `Copying DLLs from ${vendorLibDir} to ${buildReleaseDir}`);

View File

@ -20,9 +20,7 @@ const distBaseUrl = process.env.SHARP_DIST_BASE_URL || `https://github.com/lovel
const extractTarball = function (tarPath) { const extractTarball = function (tarPath) {
const vendorPath = path.join(__dirname, '..', 'vendor'); const vendorPath = path.join(__dirname, '..', 'vendor');
if (!fs.existsSync(vendorPath)) { libvips.mkdirSync(vendorPath);
fs.mkdirSync(vendorPath);
}
tar tar
.extract({ .extract({
file: tarPath, file: tarPath,

View File

@ -15,15 +15,21 @@ const spawnSyncOptions = {
shell: true shell: true
}; };
const mkdirSync = function (dirPath) {
try {
fs.mkdirSync(dirPath);
} catch (err) {
if (err.code !== 'EEXIST') {
throw err;
}
}
};
const cachePath = function () { const cachePath = function () {
const npmCachePath = env.npm_config_cache || (env.APPDATA ? path.join(env.APPDATA, 'npm-cache') : path.join(os.homedir(), '.npm')); const npmCachePath = env.npm_config_cache || (env.APPDATA ? path.join(env.APPDATA, 'npm-cache') : path.join(os.homedir(), '.npm'));
if (!fs.existsSync(npmCachePath)) { mkdirSync(npmCachePath);
fs.mkdirSync(npmCachePath);
}
const libvipsCachePath = path.join(npmCachePath, '_libvips'); const libvipsCachePath = path.join(npmCachePath, '_libvips');
if (!fs.existsSync(libvipsCachePath)) { mkdirSync(libvipsCachePath);
fs.mkdirSync(libvipsCachePath);
}
return libvipsCachePath; return libvipsCachePath;
}; };
@ -78,5 +84,6 @@ module.exports = {
globalLibvipsVersion: globalLibvipsVersion, globalLibvipsVersion: globalLibvipsVersion,
hasVendoredLibvips: hasVendoredLibvips, hasVendoredLibvips: hasVendoredLibvips,
pkgConfigPath: pkgConfigPath, pkgConfigPath: pkgConfigPath,
useGlobalLibvips: useGlobalLibvips useGlobalLibvips: useGlobalLibvips,
mkdirSync: mkdirSync
}; };

View File

@ -103,6 +103,7 @@
"exif-reader": "^1.0.2", "exif-reader": "^1.0.2",
"icc": "^1.0.0", "icc": "^1.0.0",
"mocha": "^5.2.0", "mocha": "^5.2.0",
"mock-fs": "^4.6.0",
"nyc": "^12.0.2", "nyc": "^12.0.2",
"prebuild": "^7.6.2", "prebuild": "^7.6.2",
"prebuild-ci": "^2.2.3", "prebuild-ci": "^2.2.3",

View File

@ -4,6 +4,7 @@ const assert = require('assert');
const fs = require('fs'); const fs = require('fs');
const semver = require('semver'); const semver = require('semver');
const libvips = require('../../lib/libvips'); const libvips = require('../../lib/libvips');
const mockFS = require('mock-fs');
const originalPlatform = process.platform; const originalPlatform = process.platform;
@ -74,4 +75,34 @@ describe('libvips binaries', function () {
assert.strictEqual(true, fs.existsSync(cachePath)); assert.strictEqual(true, fs.existsSync(cachePath));
}); });
}); });
describe('safe directory creation', function () {
before(function () {
mockFS({
exampleDirA: {
exampleDirB: {
exampleFile: 'Example test file'
}
}
});
});
after(function () { mockFS.restore(); });
it('mkdirSync creates a directory', function () {
const dirPath = 'createdDir';
libvips.mkdirSync(dirPath);
assert.strictEqual(true, fs.existsSync(dirPath));
});
it('mkdirSync does not throw error or overwrite an existing dir', function () {
const dirPath = 'exampleDirA';
const nestedDirPath = 'exampleDirA/exampleDirB';
assert.strictEqual(true, fs.existsSync(dirPath));
libvips.mkdirSync(dirPath);
assert.strictEqual(true, fs.existsSync(dirPath));
assert.strictEqual(true, fs.existsSync(nestedDirPath));
});
});
}); });