Socket
Socket
Sign inDemoInstall

proper-lockfile

Package Overview
Dependencies
4
Maintainers
1
Versions
33
Alerts
File Explorer

Advanced tools

Install Socket

Detect and block malicious and high-risk dependencies

Install

Comparing version 1.1.3 to 1.2.0

.eslintrc.json

74

index.js

@@ -55,3 +55,3 @@ 'use strict';

if (stat.mtime.getTime() >= Date.now() - options.stale) {
if (!isLockStale(stat, options)) {
return callback(errcode('Lock file is already being hold', 'ELOCKED', { file: file }));

@@ -73,2 +73,6 @@ }

function isLockStale(stat, options) {
return stat.mtime.getTime() < Date.now() - options.stale;
}
function removeLock(file, options, callback) {

@@ -172,3 +176,3 @@ // Remove lockfile, ignoring ENOENT errors

retries: 0,
fs: fs
fs: fs,
}, options);

@@ -209,3 +213,3 @@

compromised: compromised,
lastUpdate: Date.now()
lastUpdate: Date.now(),
};

@@ -237,3 +241,3 @@

fs: fs,
realpath: true
realpath: true,
}, options);

@@ -266,4 +270,4 @@

function lockSync(file, options, compromised) {
var err,
release;
var err;
var release;

@@ -312,3 +316,57 @@ if (typeof options === 'function') {

function check(file, options, callback) {
if (typeof options === 'function') {
callback = options;
options = null;
}
options = extend({
stale: 10000,
realpath: true,
fs: fs,
}, options);
options.stale = Math.max(options.stale || 0, 2000);
// Resolve to a canonical file path
canonicalPath(file, options, function (err, file) {
if (err) {
return callback(err);
}
// Check if lockfile exists
options.fs.stat(getLockFile(file), function (err, stat) {
if (err) {
// if does not exist, file is not locked. Otherwise, callback with error
return (err.code === 'ENOENT') ? callback(null, false) : callback(err);
}
if (options.stale <= 0) { return callback(null, true); }
// Otherwise, check if lock is stale by analyzing the file mtime
return callback(null, !isLockStale(stat, options));
});
});
}
function checkSync(file, options) {
var err;
var locked;
options = options || {};
options.fs = syncFs(options.fs || fs);
check(file, options, function (_err, _locked) {
err = _err;
locked = _locked;
});
if (err) {
throw err;
}
return locked;
}
// Remove acquired locks on exit

@@ -318,3 +376,3 @@ /* istanbul ignore next */

Object.keys(locks).forEach(function (file) {
try { locks[file].options.fs.rmdirSync(getLockFile(file)); } catch (e) {}
try { locks[file].options.fs.rmdirSync(getLockFile(file)); } catch (e) { /* empty */ }
});

@@ -328,1 +386,3 @@ });

module.exports.unlockSync = unlockSync;
module.exports.check = check;
module.exports.checkSync = checkSync;

12

lib/syncFs.js

@@ -7,5 +7,5 @@ 'use strict';

return function () {
var callback = arguments[arguments.length - 1],
args = Array.prototype.slice.call(arguments, 0, -1),
ret;
var callback = arguments[arguments.length - 1];
var args = Array.prototype.slice.call(arguments, 0, -1);
var ret;

@@ -23,5 +23,5 @@ try {

function syncFs(fs) {
var fns = ['mkdir', 'realpath', 'stat', 'rmdir', 'utimes'],
obj = {},
key;
var fns = ['mkdir', 'realpath', 'stat', 'rmdir', 'utimes'];
var obj = {};
var key;

@@ -28,0 +28,0 @@ // Create the sync versions of the methods that we need

{
"name": "proper-lockfile",
"version": "1.1.3",
"version": "1.2.0",
"description": "A inter-process and inter-machine lockfile utility that works on a local or network file system.",
"main": "index.js",
"scripts": {
"lint": "eslint '{*.js,lib/**/*.js,test/**/*.js}' --ignore-pattern=test/coverage",
"test": "mocha --bail",

@@ -37,5 +38,8 @@ "test-cov": "istanbul cover --dir test/coverage _mocha -- --bail && echo open test/coverage/lcov-report/index.html",

"devDependencies": {
"@satazor/eslint-config": "^3.1.1",
"async": "^2.0.0",
"buffered-spawn": "^2.0.4",
"coveralls": "^2.11.6",
"eslint": "^3.5.0",
"eslint-plugin-react": "^6.2.0",
"expect.js": "^0.3.1",

@@ -42,0 +46,0 @@ "istanbul": "^0.4.1",

@@ -137,3 +137,22 @@ # proper-lockfile

### .check(file, [options], callback)
Check if the file is locked and its lockfile is not stale. Callback is called with callback(error, isLocked).
Available options:
- `stale`: Duration in milliseconds in which the lock is considered stale, defaults to `10000` (minimum value is `5000`)
- `realpath`: Resolve symlinks using realpath, defaults to `true` (note that if `true`, the `file` must exist previously)
- `fs`: A custom fs to use, defaults to `graceful-fs`
```js
var lockfile = require('proper-lockfile');
lockfile.check('some/file', function (err, isLocked) {
if (err) throw err;
// isLocked will be true if 'some/file' is locked, otherwise will be false if not locked
});
```
### .lockSync(file, [options], [compromised])

@@ -150,3 +169,8 @@

### .checkSync(file, [options])
Sync version of `.check()`.
Returns a boolean or throws on error.
## Graceful exit

@@ -153,0 +177,0 @@

@@ -19,6 +19,6 @@ 'use strict';

function master() {
var logs = [],
numCPUs = os.cpus().length,
i,
acquired;
var logs = [];
var numCPUs = os.cpus().length;
var i;
var acquired;

@@ -62,11 +62,14 @@ fs.writeFileSync(file, '');

return 1;
} else if (log1.timestamp < log2.timestamp) {
}
if (log1.timestamp < log2.timestamp) {
return -1;
} else if (log1.message === 'LOCK_RELEASED') {
}
if (log1.message === 'LOCK_RELEASED') {
return -1;
} else if (log2.message === 'LOCK_RELEASED') {
}
if (log2.message === 'LOCK_RELEASED') {
return 1;
} else {
return 0;
}
return 0;
});

@@ -86,3 +89,3 @@

acquired = true;
break;
break;
case 'LOCK_RELEASED':

@@ -96,2 +99,5 @@ if (!acquired) {

acquired = false;
break;
default:
// do nothing
}

@@ -98,0 +104,0 @@ });

@@ -6,3 +6,3 @@ 'use strict';

var cp = require('child_process');
var expect = require('expect.js');
var expect = require('expect.js');
var extend = require('extend');

@@ -306,2 +306,3 @@ var rimraf = require('rimraf');

var stat = fs.statSync(tmpFileLock);
expect(stat.mtime.getTime()).to.be.greaterThan(mtime.getTime());

@@ -314,2 +315,3 @@ mtime = stat.mtime;

var stat = fs.statSync(tmpFileLock);
expect(stat.mtime.getTime()).to.be.greaterThan(mtime.getTime());

@@ -394,3 +396,2 @@ mtime = stat.mtime;

next();
}, function (err) {

@@ -734,2 +735,167 @@ expect(err).to.not.be.ok();

describe('.check()', function () {
beforeEach(function () {
fs.writeFileSync(tmpFile, '');
rimraf.sync(tmpFileSymlink);
});
afterEach(clearLocks);
this.timeout(5000);
it('should fail if the file does not exist by default', function (next) {
lockfile.check(tmpNonExistentFile, function (err) {
expect(err).to.be.an(Error);
expect(err.code).to.be('ENOENT');
next();
});
});
it('should not fail if the file does not exist and realpath is false', function (next) {
lockfile.check(tmpNonExistentFile, { realpath: false }, function (err) {
expect(err).to.not.be.ok();
next();
});
});
it('should callback with true if file is locked', function (next) {
lockfile.lock(tmpFile, function (err) {
expect(err).to.not.be.ok();
lockfile.check(tmpFile, function (err, locked) {
expect(err).to.not.be.ok();
expect(locked).to.be(true);
next();
});
});
});
it('should callback with false if file is not locked', function (next) {
lockfile.check(tmpFile, function (err, locked) {
expect(err).to.not.be.ok();
expect(locked).to.be(false);
next();
});
});
it('should use the custom fs', function (next) {
var customFs = extend({}, fs);
customFs.realpath = function (path, callback) {
customFs.realpath = fs.realpath;
callback(new Error('foo'));
};
lockfile.check(tmpFile, { fs: customFs }, function (err, locked) {
expect(err).to.be.an(Error);
expect(locked).to.be(undefined);
next();
});
});
it('should resolve symlinks by default', function (next) {
// Create a symlink to the tmp file
fs.symlinkSync(tmpFileRealPath, tmpFileSymlinkRealPath);
lockfile.lock(tmpFileSymlink, function (err) {
expect(err).to.not.be.ok();
lockfile.check(tmpFile, function (err, locked) {
expect(err).to.not.be.ok();
expect(locked).to.be(true);
lockfile.check(tmpFile + '/../../test/tmp', function (err, locked) {
expect(err).to.not.be.ok();
expect(locked).to.be(true);
next();
});
});
});
});
it('should not resolve symlinks if realpath is false', function (next) {
// Create a symlink to the tmp file
fs.symlinkSync(tmpFileRealPath, tmpFileSymlinkRealPath);
lockfile.lock(tmpFileSymlink, { realpath: false }, function (err) {
expect(err).to.not.be.ok();
lockfile.check(tmpFile, { realpath: false }, function (err, locked) {
expect(err).to.not.be.ok();
expect(locked).to.be(false);
lockfile.check(tmpFile + '/../../test/tmp', { realpath: false }, function (err, locked) {
expect(err).to.not.be.ok();
expect(locked).to.be(false);
next();
});
});
});
});
it('should fail if stating the lockfile errors out when verifying staleness', function (next) {
var mtime = (Date.now() - 60000) / 1000;
var customFs = extend({}, fs);
customFs.stat = function (path, callback) {
callback(new Error('foo'));
};
fs.mkdirSync(tmpFileLock);
fs.utimesSync(tmpFileLock, mtime, mtime);
lockfile.check(tmpFile, { fs: customFs }, function (err, locked) {
expect(err).to.be.an(Error);
expect(err.message).to.be('foo');
expect(locked).to.be(undefined);
next();
});
});
it('should set stale to a minimum of 2000', function (next) {
fs.mkdirSync(tmpFileLock);
setTimeout(function () {
lockfile.lock(tmpFile, { stale: 2000 }, function (err) {
expect(err).to.be.an(Error);
expect(err.code).to.be('ELOCKED');
});
}, 200);
setTimeout(function () {
lockfile.check(tmpFile, { stale: 100 }, function (err, locked) {
expect(err).to.not.be.ok();
expect(locked).to.equal(false);
next();
});
}, 2200);
});
it('should set stale to a minimum of 2000 (falsy)', function (next) {
fs.mkdirSync(tmpFileLock);
setTimeout(function () {
lockfile.lock(tmpFile, { stale: 2000 }, function (err) {
expect(err).to.be.an(Error);
expect(err.code).to.be('ELOCKED');
});
}, 200);
setTimeout(function () {
lockfile.check(tmpFile, { stale: false }, function (err, locked) {
expect(err).to.not.be.ok();
expect(locked).to.equal(false);
next();
});
}, 2200);
});
});
describe('release()', function () {

@@ -833,2 +999,3 @@ beforeEach(function () {

var release = lockfile.lockSync(tmpFile, { retries: 0 });
release();

@@ -839,2 +1006,3 @@ }).to.not.throwException();

var release = lockfile.lockSync(tmpFile, { retries: { retries: 0 } });
release();

@@ -869,2 +1037,3 @@ }).to.not.throwException();

var stat = fs.statSync(tmpFileLock);
expect(stat.mtime.getTime()).to.be.greaterThan(mtime.getTime());

@@ -877,2 +1046,3 @@ mtime = stat.mtime;

var stat = fs.statSync(tmpFileLock);
expect(stat.mtime.getTime()).to.be.greaterThan(mtime.getTime());

@@ -886,4 +1056,4 @@ mtime = stat.mtime;

it('should use a custom fs', function () {
var customFs = extend({}, fs),
called;
var customFs = extend({}, fs);
var called;

@@ -898,2 +1068,44 @@ customFs.realpathSync = function () {

});
it('should expose a working checkSync', function () {
var release;
var locked;
// Test success unlocked
locked = lockfile.checkSync(tmpFile);
expect(locked).to.be.a('boolean');
expect(locked).to.be(false);
// Test success locked
release = lockfile.lockSync(tmpFile);
locked = lockfile.checkSync(tmpFile);
expect(locked).to.be.a('boolean');
expect(locked).to.be(true);
// Test success unlocked after release
release();
locked = lockfile.checkSync(tmpFile);
expect(locked).to.be.a('boolean');
expect(locked).to.be(false);
// Test options being passed
locked = lockfile.checkSync(tmpFile, {});
expect(locked).to.be.a('boolean');
expect(locked).to.be(false);
release = lockfile.lockSync(tmpFile);
locked = lockfile.checkSync(tmpFile, {});
expect(locked).to.be.a('boolean');
expect(locked).to.be(true);
release();
locked = lockfile.checkSync(tmpFile, {});
expect(locked).to.be.a('boolean');
expect(locked).to.be(false);
// Test fail with non-existent file
expect(function () {
lockfile.checkSync('nonexistentdir/nonexistentfile');
}).to.throwException(/ENOENT/);
});
});

@@ -900,0 +1112,0 @@

SocketSocket SOC 2 Logo

Product

  • Package Alerts
  • Integrations
  • Docs
  • Pricing
  • FAQ
  • Roadmap

Packages

Stay in touch

Get open source security insights delivered straight into your inbox.


  • Terms
  • Privacy
  • Security

Made with ⚡️ by Socket Inc