mirror of
https://github.com/verdaccio/verdaccio.git
synced 2025-01-06 22:40:26 -05:00
231 lines
5.1 KiB
JavaScript
231 lines
5.1 KiB
JavaScript
/* eslint prefer-spread: "off" */
|
|
|
|
'use strict';
|
|
|
|
const fs = require('fs');
|
|
const Error = require('http-errors');
|
|
const mkdirp = require('mkdirp');
|
|
const Path = require('path');
|
|
const MyStreams = require('./streams');
|
|
const locker = require('./file-locking');
|
|
|
|
const fSError = function(code) {
|
|
const err = Error(code);
|
|
err.code = code;
|
|
return err;
|
|
};
|
|
|
|
const tempFile = function(str) {
|
|
return `${str}.tmp${String(Math.random()).substr(2)}`;
|
|
};
|
|
|
|
const renameTmp = function(src, dst, _cb) {
|
|
const cb = function(err) {
|
|
if (err) {
|
|
fs.unlink(src, function() {});
|
|
}
|
|
_cb(err);
|
|
};
|
|
|
|
if (process.platform !== 'win32') {
|
|
return fs.rename(src, dst, cb);
|
|
}
|
|
|
|
// windows can't remove opened file,
|
|
// but it seem to be able to rename it
|
|
let tmp = tempFile(dst);
|
|
fs.rename(dst, tmp, function(err) {
|
|
fs.rename(src, dst, cb);
|
|
if (!err) {
|
|
fs.unlink(tmp, () => {});
|
|
}
|
|
});
|
|
};
|
|
|
|
const write = function(dest, data, cb) {
|
|
let safe_write = function(cb) {
|
|
let tmpname = tempFile(dest);
|
|
fs.writeFile(tmpname, data, function(err) {
|
|
if (err) return cb(err);
|
|
renameTmp(tmpname, dest, cb);
|
|
});
|
|
};
|
|
|
|
safe_write(function(err) {
|
|
if (err && err.code === 'ENOENT') {
|
|
mkdirp(Path.dirname(dest), function(err) {
|
|
if (err) return cb(err);
|
|
safe_write(cb);
|
|
});
|
|
} else {
|
|
cb(err);
|
|
}
|
|
});
|
|
};
|
|
|
|
const write_stream = function(name) {
|
|
const stream = MyStreams.uploadTarballStream();
|
|
let _ended = 0;
|
|
stream.on('end', function() {
|
|
_ended = 1;
|
|
});
|
|
|
|
fs.exists(name, function(exists) {
|
|
if (exists) {
|
|
return stream.emit('error', fSError('EEXISTS'));
|
|
}
|
|
|
|
let tmpname = name + '.tmp-'+String(Math.random()).replace(/^0\./, '');
|
|
let file = fs.createWriteStream(tmpname);
|
|
let opened = false;
|
|
stream.pipe(file);
|
|
|
|
stream.done = function() {
|
|
const onend = function() {
|
|
file.on('close', function() {
|
|
renameTmp(tmpname, name, function(err) {
|
|
if (err) {
|
|
stream.emit('error', err);
|
|
} else {
|
|
stream.emit('success');
|
|
}
|
|
});
|
|
});
|
|
file.destroySoon();
|
|
};
|
|
if (_ended) {
|
|
onend();
|
|
} else {
|
|
stream.on('end', onend);
|
|
}
|
|
};
|
|
stream.abort = function() {
|
|
if (opened) {
|
|
opened = false;
|
|
file.on('close', function() {
|
|
fs.unlink(tmpname, function() {});
|
|
});
|
|
}
|
|
file.destroySoon();
|
|
};
|
|
file.on('open', function() {
|
|
opened = true;
|
|
// re-emitting open because it's handled in storage.js
|
|
stream.emit('open');
|
|
});
|
|
file.on('error', function(err) {
|
|
stream.emit('error', err);
|
|
});
|
|
});
|
|
return stream;
|
|
};
|
|
|
|
const read_stream = function(name, stream, callback) {
|
|
let rstream = fs.createReadStream(name);
|
|
rstream.on('error', function(err) {
|
|
stream.emit('error', err);
|
|
});
|
|
rstream.on('open', function(fd) {
|
|
fs.fstat(fd, function(err, stats) {
|
|
if (err) return stream.emit('error', err);
|
|
stream.emit('content-length', stats.size);
|
|
stream.emit('open');
|
|
rstream.pipe(stream);
|
|
});
|
|
});
|
|
|
|
stream = MyStreams.readTarballStream();
|
|
stream.abort = function() {
|
|
rstream.close();
|
|
};
|
|
return stream;
|
|
};
|
|
|
|
const create = function(name, contents, callback) {
|
|
fs.exists(name, function(exists) {
|
|
if (exists) {
|
|
return callback( fSError('EEXISTS') );
|
|
}
|
|
write(name, contents, callback);
|
|
});
|
|
};
|
|
|
|
const update = function(name, contents, callback) {
|
|
fs.exists(name, function(exists) {
|
|
if (!exists) {
|
|
return callback( fSError('ENOENT') );
|
|
}
|
|
write(name, contents, callback);
|
|
});
|
|
};
|
|
|
|
const read = function(name, callback) {
|
|
fs.readFile(name, callback);
|
|
};
|
|
|
|
module.exports.read = read;
|
|
|
|
module.exports.read_json = function(name, cb) {
|
|
read(name, function(err, res) {
|
|
if (err) {
|
|
return cb(err);
|
|
}
|
|
|
|
let args = [];
|
|
try {
|
|
args = [null, JSON.parse(res.toString('utf8'))];
|
|
} catch(err) {
|
|
args = [err];
|
|
}
|
|
cb.apply(null, args);
|
|
});
|
|
};
|
|
|
|
module.exports.lock_and_read = function(name, cb) {
|
|
locker.readFile(name, {lock: true}, function(err, res) {
|
|
if (err) {
|
|
return cb(err);
|
|
}
|
|
return cb(null, res);
|
|
});
|
|
};
|
|
|
|
module.exports.lock_and_read_json = function(name, cb) {
|
|
locker.readFile(name, {lock: true, parse: true}, function(err, res) {
|
|
if (err) {
|
|
return cb(err);
|
|
}
|
|
return cb(null, res);
|
|
});
|
|
};
|
|
|
|
module.exports.unlock_file = function(name, cb) {
|
|
locker.unlockFile(name, cb);
|
|
};
|
|
|
|
module.exports.create = create;
|
|
|
|
module.exports.create_json = function(name, value, cb) {
|
|
create(name, JSON.stringify(value, null, '\t'), cb);
|
|
};
|
|
|
|
module.exports.update = update;
|
|
|
|
module.exports.update_json = function(name, value, cb) {
|
|
update(name, JSON.stringify(value, null, '\t'), cb);
|
|
};
|
|
|
|
module.exports.write = write;
|
|
|
|
module.exports.write_json = function(name, value, cb) {
|
|
write(name, JSON.stringify(value, null, '\t'), cb);
|
|
};
|
|
|
|
module.exports.write_stream = write_stream;
|
|
|
|
module.exports.read_stream = read_stream;
|
|
|
|
module.exports.unlink = fs.unlink;
|
|
|
|
module.exports.rmdir = fs.rmdir;
|
|
|