mirror of
https://github.com/verdaccio/verdaccio.git
synced 2024-12-16 21:56:25 -05:00
parent
060dcb49b4
commit
a8dc1b2f7b
8 changed files with 193 additions and 43 deletions
|
@ -46,7 +46,12 @@ Storage.prototype._internal_error = function(err, file, message) {
|
|||
}
|
||||
|
||||
Storage.prototype.add_package = function(name, metadata, callback) {
|
||||
this.storage(name).create_json(info_file, get_boilerplate(name), function(err) {
|
||||
var storage = this.storage(name)
|
||||
if (!storage) return callback(new UError({
|
||||
status: 404,
|
||||
message: 'this package cannot be added'
|
||||
}))
|
||||
storage.create_json(info_file, get_boilerplate(name), function(err) {
|
||||
if (err && err.code === 'EEXISTS') {
|
||||
return callback(new UError({
|
||||
status: 409,
|
||||
|
@ -60,7 +65,13 @@ Storage.prototype.add_package = function(name, metadata, callback) {
|
|||
Storage.prototype.remove_package = function(name, callback) {
|
||||
var self = this
|
||||
self.logger.info({name: name}, 'unpublishing @{name} (all)')
|
||||
self.storage(name).read_json(info_file, function(err, data) {
|
||||
|
||||
var storage = self.storage(name)
|
||||
if (!storage) return callback(new UError({
|
||||
status: 404,
|
||||
message: 'no such package available',
|
||||
}))
|
||||
storage.read_json(info_file, function(err, data) {
|
||||
if (err) {
|
||||
if (err.code === 'ENOENT') {
|
||||
return callback(new UError({
|
||||
|
@ -73,7 +84,7 @@ Storage.prototype.remove_package = function(name, callback) {
|
|||
}
|
||||
self._normalize_package(data)
|
||||
|
||||
self.storage(name).unlink(info_file, function(err) {
|
||||
storage.unlink(info_file, function(err) {
|
||||
if (err) return callback(err)
|
||||
|
||||
var files = Object.keys(data._attachments)
|
||||
|
@ -82,14 +93,14 @@ Storage.prototype.remove_package = function(name, callback) {
|
|||
if (files.length === 0) return cb()
|
||||
|
||||
var file = files.shift()
|
||||
self.storage(name).unlink(file, function() {
|
||||
storage.unlink(file, function() {
|
||||
unlinkNext(cb)
|
||||
})
|
||||
}
|
||||
|
||||
unlinkNext(function() {
|
||||
// try to unlink the directory, but ignore errors because it can fail
|
||||
self.storage(name).rmdir('.', function(err) {
|
||||
storage.rmdir('.', function(err) {
|
||||
callback(err)
|
||||
})
|
||||
})
|
||||
|
@ -99,7 +110,13 @@ Storage.prototype.remove_package = function(name, callback) {
|
|||
|
||||
Storage.prototype._read_create_package = function(name, callback) {
|
||||
var self = this
|
||||
self.storage(name).read_json(info_file, function(err, data) {
|
||||
var storage = self.storage(name)
|
||||
if (!storage) {
|
||||
var data = get_boilerplate(name)
|
||||
self._normalize_package(data)
|
||||
return callback(null, data)
|
||||
}
|
||||
storage.read_json(info_file, function(err, data) {
|
||||
// TODO: race condition
|
||||
if (err) {
|
||||
if (err.code === 'ENOENT') {
|
||||
|
@ -293,7 +310,8 @@ Storage.prototype.remove_tarball = function(name, filename, revision, callback)
|
|||
}
|
||||
}, function(err) {
|
||||
if (err) return callback(err)
|
||||
self.storage(name).unlink(filename, callback)
|
||||
var storage = self.storage(name)
|
||||
if (storage) storage.unlink(filename, callback)
|
||||
})
|
||||
}
|
||||
|
||||
|
@ -305,6 +323,8 @@ Storage.prototype.add_tarball = function(name, filename) {
|
|||
, length = 0
|
||||
, shasum = crypto.createHash('sha1')
|
||||
|
||||
stream.abort = stream.done = function(){}
|
||||
|
||||
stream._transform = function(data) {
|
||||
shasum.update(data)
|
||||
length += data.length
|
||||
|
@ -313,13 +333,27 @@ Storage.prototype.add_tarball = function(name, filename) {
|
|||
|
||||
var self = this
|
||||
if (name === info_file || name === '__proto__') {
|
||||
stream.emit('error', new UError({
|
||||
status: 403,
|
||||
message: 'can\'t use this filename'
|
||||
}))
|
||||
process.nextTick(function() {
|
||||
stream.emit('error', new UError({
|
||||
status: 403,
|
||||
message: 'can\'t use this filename'
|
||||
}))
|
||||
})
|
||||
return stream
|
||||
}
|
||||
|
||||
var wstream = this.storage(name).write_stream(filename)
|
||||
var storage = self.storage(name)
|
||||
if (!storage) {
|
||||
process.nextTick(function() {
|
||||
stream.emit('error', new UError({
|
||||
status: 404,
|
||||
message: 'can\'t upload this package'
|
||||
}))
|
||||
})
|
||||
return stream
|
||||
}
|
||||
|
||||
var wstream = storage.write_stream(filename)
|
||||
|
||||
wstream.on('error', function(err) {
|
||||
if (err.code === 'EEXISTS') {
|
||||
|
@ -380,13 +414,25 @@ Storage.prototype.add_tarball = function(name, filename) {
|
|||
|
||||
Storage.prototype.get_tarball = function(name, filename, callback) {
|
||||
assert(utils.validate_name(filename))
|
||||
var self = this
|
||||
|
||||
var stream = new mystreams.ReadTarballStream()
|
||||
stream.abort = function() {
|
||||
rstream.abort()
|
||||
if (rstream) rstream.abort()
|
||||
}
|
||||
|
||||
var rstream = this.storage(name).read_stream(filename)
|
||||
var storage = self.storage(name)
|
||||
if (!storage) {
|
||||
process.nextTick(function() {
|
||||
stream.emit('error', new UError({
|
||||
status: 404,
|
||||
message: 'no such file available',
|
||||
}))
|
||||
})
|
||||
return stream
|
||||
}
|
||||
|
||||
var rstream = storage.read_stream(filename)
|
||||
rstream.on('error', function(err) {
|
||||
if (err && err.code === 'ENOENT') {
|
||||
stream.emit('error', new UError({
|
||||
|
@ -412,8 +458,13 @@ Storage.prototype.get_package = function(name, options, callback) {
|
|||
if (typeof(options) === 'function') callback = options, options = {}
|
||||
|
||||
var self = this
|
||||
var storage = self.storage(name)
|
||||
if (!storage) return callback(new UError({
|
||||
status: 404,
|
||||
message: 'no such package available'
|
||||
}))
|
||||
|
||||
self.storage(name).read_json(info_file, function(err, result) {
|
||||
storage.read_json(info_file, function(err, result) {
|
||||
if (err) {
|
||||
if (err.code === 'ENOENT') {
|
||||
return callback(new UError({
|
||||
|
@ -433,13 +484,17 @@ Storage.prototype.get_recent_packages = function(startkey, callback) {
|
|||
var self = this
|
||||
var i = 0
|
||||
var list = []
|
||||
fs.readdir(self.storage('').path, function(err, files) {
|
||||
|
||||
var storage = self.storage('')
|
||||
if (!storage) return callback(null, [])
|
||||
|
||||
fs.readdir(storage.path, function(err, files) {
|
||||
if (err) return callback(null, [])
|
||||
|
||||
var filesL = files.length
|
||||
|
||||
files.forEach(function(file) {
|
||||
fs.stat(self.storage(file).path, function(err, stats) {
|
||||
fs.stat(storage.path, function(err, stats) {
|
||||
if (err) return callback(err)
|
||||
if (stats.mtime > startkey) {
|
||||
list.push({
|
||||
|
@ -474,7 +529,12 @@ Storage.prototype.get_recent_packages = function(startkey, callback) {
|
|||
//
|
||||
Storage.prototype.update_package = function(name, updateFn, _callback) {
|
||||
var self = this
|
||||
self.storage(name).lock_and_read_json(info_file, function(err, fd, json) {
|
||||
var storage = self.storage(name)
|
||||
if (!storage) return callback(new UError({
|
||||
status: 404,
|
||||
message: 'no such package available',
|
||||
}))
|
||||
storage.lock_and_read_json(info_file, function(err, fd, json) {
|
||||
function callback() {
|
||||
var _args = arguments
|
||||
if (fd) {
|
||||
|
@ -526,16 +586,21 @@ Storage.prototype._write_package = function(name, json, callback) {
|
|||
var rev = json._rev.split('-')
|
||||
json._rev = ((+rev[0] || 0) + 1) + '-' + crypto.pseudoRandomBytes(8).toString('hex')
|
||||
|
||||
this.storage(name).write_json(info_file, json, callback)
|
||||
var storage = this.storage(name)
|
||||
if (!storage) return callback()
|
||||
storage.write_json(info_file, json, callback)
|
||||
}
|
||||
|
||||
Storage.prototype.storage = function(package) {
|
||||
var path = this.config.get_package_setting(package, 'storage')
|
||||
if (path == null) path = this.config.storage
|
||||
if (path == null || path === false) {
|
||||
this.logger.debug({name: package}, 'this package has no storage defined: @{name}')
|
||||
return null
|
||||
}
|
||||
return new Path_Wrapper(
|
||||
Path.join(
|
||||
Path.resolve(
|
||||
Path.dirname(this.config.self_path),
|
||||
this.config.get_package_setting(package, 'storage') || this.config.storage
|
||||
),
|
||||
Path.resolve(Path.dirname(this.config.self_path), path),
|
||||
package
|
||||
)
|
||||
)
|
||||
|
|
|
@ -250,26 +250,32 @@ Storage.prototype.get_tarball = function(name, filename) {
|
|||
}
|
||||
|
||||
var savestream = self.local.add_tarball(name, filename)
|
||||
savestream.on('error', function(err) {
|
||||
savestream.abort()
|
||||
stream.emit('error', err)
|
||||
})
|
||||
savestream.on('open', function() {
|
||||
function on_open() {
|
||||
var rstream2 = uplink.get_url(file.url)
|
||||
rstream2.on('error', function(err) {
|
||||
savestream.abort()
|
||||
if (savestream) savestream.abort()
|
||||
savestream = null
|
||||
stream.emit('error', err)
|
||||
})
|
||||
rstream2.on('end', function() {
|
||||
savestream.done()
|
||||
if (savestream) savestream.done()
|
||||
})
|
||||
|
||||
rstream2.on('content-length', function(v) {
|
||||
stream.emit('content-length', v)
|
||||
savestream.emit('content-length', v)
|
||||
if (savestream) savestream.emit('content-length', v)
|
||||
})
|
||||
rstream2.pipe(stream)
|
||||
rstream2.pipe(savestream)
|
||||
if (savestream) rstream2.pipe(savestream)
|
||||
}
|
||||
|
||||
savestream.on('open', function() {
|
||||
on_open()
|
||||
})
|
||||
savestream.on('error', function() {
|
||||
if (savestream) savestream.abort()
|
||||
savestream = null
|
||||
on_open()
|
||||
})
|
||||
}
|
||||
}
|
||||
|
|
|
@ -58,7 +58,7 @@ keywords:
|
|||
- server
|
||||
|
||||
scripts:
|
||||
test: mocha ./test/functional ./test/unit
|
||||
test: mocha -R dot ./test/functional ./test/unit
|
||||
lint: eslint -c ./.eslint.yaml ./lib
|
||||
#prepublish: js-yaml package.yaml > package.json
|
||||
|
||||
|
|
|
@ -37,6 +37,12 @@ packages:
|
|||
allow_publish: all
|
||||
proxy_access: express
|
||||
|
||||
'test-nullstorage*':
|
||||
allow_access: all
|
||||
allow_publish: all
|
||||
proxy_access: server2
|
||||
storage: false
|
||||
|
||||
'baduplink':
|
||||
allow_access: all
|
||||
allow_publish: all
|
||||
|
|
|
@ -28,6 +28,10 @@ packages:
|
|||
allow_publish: test anonymous
|
||||
proxy_access: server1
|
||||
|
||||
'test-nullstorage*':
|
||||
allow_access: all
|
||||
allow_publish: all
|
||||
|
||||
'*':
|
||||
allow_access: test anonymous
|
||||
allow_publish: test anonymous
|
||||
|
|
|
@ -43,6 +43,7 @@ describe('Func', function() {
|
|||
require('./incomplete')()
|
||||
require('./mirror')()
|
||||
require('./newnpmreg')()
|
||||
require('./nullstorage')()
|
||||
require('./race')()
|
||||
require('./racycrash')()
|
||||
require('./security')()
|
||||
|
|
78
test/functional/nullstorage.js
Normal file
78
test/functional/nullstorage.js
Normal file
|
@ -0,0 +1,78 @@
|
|||
require('./lib/startup')
|
||||
|
||||
var assert = require('assert')
|
||||
, async = require('async')
|
||||
, crypto = require('crypto')
|
||||
|
||||
function readfile(x) {
|
||||
return require('fs').readFileSync(__dirname + '/' + x)
|
||||
}
|
||||
|
||||
module.exports = function() {
|
||||
var server = process.server
|
||||
var server2 = process.server2
|
||||
|
||||
it('trying to fetch non-existent package / null storage', function(cb) {
|
||||
server.get_package('test-nullstorage-nonexist', function(res, body) {
|
||||
assert.equal(res.statusCode, 404)
|
||||
assert(~body.error.indexOf('no such package'))
|
||||
cb()
|
||||
})
|
||||
})
|
||||
|
||||
describe('test-nullstorage on server2', function() {
|
||||
before(server2.add_package.bind(server2, 'test-nullstorage2'))
|
||||
|
||||
it('creating new package - server2', function(){/* test for before() */})
|
||||
|
||||
it('downloading non-existent tarball', function(cb) {
|
||||
server.get_tarball('test-nullstorage2', 'blahblah', function(res, body) {
|
||||
assert.equal(res.statusCode, 404)
|
||||
assert(~body.error.indexOf('no such file'))
|
||||
cb()
|
||||
})
|
||||
})
|
||||
|
||||
describe('tarball', function() {
|
||||
before(function(cb) {
|
||||
server2.put_tarball('test-nullstorage2', 'blahblah', readfile('fixtures/binary'), function(res, body) {
|
||||
assert.equal(res.statusCode, 201)
|
||||
assert(body.ok)
|
||||
cb()
|
||||
})
|
||||
})
|
||||
|
||||
before(function(cb) {
|
||||
var pkg = require('./lib/package')('test-nullstorage2')
|
||||
pkg.dist.shasum = crypto.createHash('sha1').update(readfile('fixtures/binary')).digest('hex')
|
||||
server2.put_version('test-nullstorage2', '0.0.1', pkg, function(res, body) {
|
||||
assert.equal(res.statusCode, 201)
|
||||
assert(~body.ok.indexOf('published'))
|
||||
cb()
|
||||
})
|
||||
})
|
||||
|
||||
it('uploading new tarball', function(){/* test for before() */})
|
||||
|
||||
it('downloading newly created tarball', function(cb) {
|
||||
server.get_tarball('test-nullstorage2', 'blahblah', function(res, body) {
|
||||
assert.equal(res.statusCode, 200)
|
||||
assert.deepEqual(body, readfile('fixtures/binary').toString('utf8'))
|
||||
cb()
|
||||
})
|
||||
})
|
||||
|
||||
it('downloading newly created package', function(cb) {
|
||||
server.get_package('test-nullstorage2', function(res, body) {
|
||||
assert.equal(res.statusCode, 200)
|
||||
assert.equal(body.name, 'test-nullstorage2')
|
||||
assert.equal(body.versions['0.0.1'].name, 'test-nullstorage2')
|
||||
assert.equal(body.versions['0.0.1'].dist.tarball, 'http://localhost:55551/test-nullstorage2/-/blahblah')
|
||||
assert.deepEqual(body['dist-tags'], {latest: '0.0.1'})
|
||||
cb()
|
||||
})
|
||||
})
|
||||
})
|
||||
})
|
||||
}
|
||||
|
|
@ -1,10 +0,0 @@
|
|||
#!/bin/sh
|
||||
|
||||
CWD=$(pwd)
|
||||
PATH='../node_modules/.bin':$PATH
|
||||
TESTDIR=$(dirname $0)
|
||||
cd $TESTDIR
|
||||
mocha ./functional ./unit
|
||||
TESTRES=$?
|
||||
cd $CWD
|
||||
exit $TESTRES
|
Loading…
Reference in a new issue