mirror of
https://github.com/verdaccio/verdaccio.git
synced 2024-12-23 22:27:34 -05:00
153 lines
3.2 KiB
JavaScript
153 lines
3.2 KiB
JavaScript
|
/**
|
||
|
* file-locking.js - file system locking (replaces fs-ext)
|
||
|
*/
|
||
|
|
||
|
var async = require('async'),
|
||
|
locker = require('lockfile'),
|
||
|
fs = require('fs'),
|
||
|
path = require('path')
|
||
|
|
||
|
// locks a file by creating a lock file
|
||
|
function lockFile(name, next) {
|
||
|
var lockFileName = name + '.lock',
|
||
|
lockOpts = {
|
||
|
wait: 1000, // time (ms) to wait when checking for stale locks
|
||
|
pollPeriod: 100, // how often (ms) to re-check stale locks
|
||
|
|
||
|
stale: 5 * 60 * 1000, // locks are considered stale after 5 minutes
|
||
|
|
||
|
retries: 100, // number of times to attempt to create a lock
|
||
|
retryWait: 100 // time (ms) between tries
|
||
|
}
|
||
|
|
||
|
async.series({
|
||
|
|
||
|
statdir: function (callback) {
|
||
|
// test to see if the directory exists
|
||
|
fs.stat(path.dirname(name), function (err, stats) {
|
||
|
if (err) {
|
||
|
callback(err)
|
||
|
} else if (!stats.isDirectory()) {
|
||
|
callback(new Error(path.dirname(name) + ' is not a directory'))
|
||
|
} else {
|
||
|
callback(null)
|
||
|
}
|
||
|
})
|
||
|
},
|
||
|
|
||
|
statfile: function (callback) {
|
||
|
// test to see if the file to lock exists
|
||
|
fs.stat(name, function (err, stats) {
|
||
|
if (err) {
|
||
|
callback(err)
|
||
|
} else if (!stats.isFile()) {
|
||
|
callback(new Error(path.dirname(name) + ' is not a file'))
|
||
|
} else {
|
||
|
callback(null)
|
||
|
}
|
||
|
});
|
||
|
},
|
||
|
|
||
|
lockfile: function (callback) {
|
||
|
// try to lock the file
|
||
|
locker.lock(lockFileName, lockOpts, callback)
|
||
|
}
|
||
|
|
||
|
}, function (err) {
|
||
|
if (err) {
|
||
|
// lock failed
|
||
|
return next(err)
|
||
|
}
|
||
|
|
||
|
// lock succeeded
|
||
|
return next(null);
|
||
|
})
|
||
|
|
||
|
}
|
||
|
|
||
|
// unlocks file by removing existing lock file
|
||
|
function unlockFile(name, next) {
|
||
|
var lockFileName = name + '.lock'
|
||
|
|
||
|
locker.unlock(lockFileName, function (err) {
|
||
|
if (err) {
|
||
|
return next(err)
|
||
|
}
|
||
|
|
||
|
return next(null)
|
||
|
})
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* reads a local file, which involves
|
||
|
* optionally taking a lock
|
||
|
* reading the file contents
|
||
|
* optionally parsing JSON contents
|
||
|
*/
|
||
|
function readFile(name, options, next) {
|
||
|
if (typeof options === 'function' && next === null) {
|
||
|
next = options;
|
||
|
options = {}
|
||
|
}
|
||
|
|
||
|
options = options || {}
|
||
|
options.lock = options.lock || false
|
||
|
options.parse = options.parse || false
|
||
|
|
||
|
function lock(callback) {
|
||
|
if (!options.lock) {
|
||
|
return callback(null)
|
||
|
}
|
||
|
|
||
|
lockFile(name, function (err) {
|
||
|
if (err) {
|
||
|
return callback(err)
|
||
|
}
|
||
|
return callback(null)
|
||
|
})
|
||
|
}
|
||
|
|
||
|
function read(callback) {
|
||
|
fs.readFile(name, 'utf8', function (err, contents) {
|
||
|
if (err) {
|
||
|
return callback(err)
|
||
|
}
|
||
|
|
||
|
callback(null, contents)
|
||
|
|
||
|
})
|
||
|
}
|
||
|
|
||
|
function parseJSON(contents, callback) {
|
||
|
if (!options.parse) {
|
||
|
return callback(null, contents)
|
||
|
}
|
||
|
|
||
|
try {
|
||
|
contents = JSON.parse(contents)
|
||
|
return callback(null, contents)
|
||
|
} catch (err) {
|
||
|
return callback(err)
|
||
|
}
|
||
|
}
|
||
|
|
||
|
async.waterfall([
|
||
|
lock,
|
||
|
read,
|
||
|
parseJSON
|
||
|
],
|
||
|
|
||
|
function (err, result) {
|
||
|
if (err) {
|
||
|
return next(err)
|
||
|
} else {
|
||
|
return next(null, result)
|
||
|
}
|
||
|
})
|
||
|
}
|
||
|
|
||
|
exports.lockFile = lockFile;
|
||
|
exports.unlockFile = unlockFile;
|
||
|
|
||
|
exports.readFile = readFile;
|