add dist-tags endpoints

This commit is contained in:
Alex Kocharin 2015-05-10 18:23:31 +03:00
parent 0da30ca089
commit c09d03b20d
5 changed files with 236 additions and 19 deletions

View File

@ -170,17 +170,77 @@ module.exports = function(config, auth, storage) {
}
})
// tagging a package
app.put('/:package/:tag', can('publish'), media('application/json'), function(req, res, next) {
function tag_package_version(req, res, next) {
if (typeof(req.body) !== 'string') return next('route')
var tags = {}
tags[req.params.tag] = req.body
storage.add_tags(req.params.package, tags, function(err) {
storage.merge_tags(req.params.package, tags, function(err) {
if (err) return next(err)
res.status(201)
return next({ ok: 'package tagged' })
})
}
// tagging a package
app.put('/:package/:tag',
can('publish'), media('application/json'), tag_package_version)
app.post('/-/package/:package/dist-tags/:tag',
can('publish'), media('application/json'), tag_package_version)
app.put('/-/package/:package/dist-tags/:tag',
can('publish'), media('application/json'), tag_package_version)
app.delete('/-/package/:package/dist-tags/:tag', can('publish'), function (req, res, next) {
var tags = {}
tags[req.params.tag] = null
storage.merge_tags(req.params.package, tags, function(err) {
if (err) return next(err)
res.status(201)
return next({ ok: 'tag removed' })
})
})
app.get('/-/package/:package/dist-tags', can('access'), function(req, res, next) {
storage.get_package(req.params.package, { req: req }, function(err, info) {
if (err) return next(err)
next(info['dist-tags'])
})
})
app.post('/-/package/:package/dist-tags',
can('publish'), media('application/json'), expect_json,
function(req, res, next) {
storage.merge_tags(req.params.package, req.body, function(err) {
if (err) return next(err)
res.status(201)
return next({ ok: 'tags updated' })
})
})
app.put('/-/package/:package/dist-tags',
can('publish'), media('application/json'), expect_json,
function(req, res, next) {
storage.replace_tags(req.params.package, req.body, function(err) {
if (err) return next(err)
res.status(201)
return next({ ok: 'tags updated' })
})
})
app.delete('/-/package/:package/dist-tags',
can('publish'), media('application/json'),
function(req, res, next) {
storage.replace_tags(req.params.package, {}, function(err) {
if (err) return next(err)
res.status(201)
return next({ ok: 'tags removed' })
})
})
// publishing a package
@ -271,7 +331,7 @@ module.exports = function(config, auth, storage) {
}
function add_tags(tags, cb) {
storage.add_tags(name, tags, cb)
storage.merge_tags(name, tags, cb)
}
})

View File

@ -251,11 +251,38 @@ Storage.prototype.add_version = function(name, version, metadata, tag, callback)
}, callback)
}
Storage.prototype.add_tags = function(name, tags, callback) {
Storage.prototype.merge_tags = function(name, tags, callback) {
var self = this
self.update_package(name, function updater(data, cb) {
for (var t in tags) {
if (tags[t] === null) {
delete data['dist-tags'][t]
continue
}
if (data.versions[tags[t]] == null) {
return cb( Error[404]("this version doesn't exist") )
}
Utils.tag_version(data, tags[t], t, self.config)
}
cb()
}, callback)
}
Storage.prototype.replace_tags = function(name, tags, callback) {
var self = this
self.update_package(name, function updater(data, cb) {
data['dist-tags'] = {}
for (var t in tags) {
if (tags[t] === null) {
delete data['dist-tags'][t]
continue
}
if (data.versions[tags[t]] == null) {
return cb( Error[404]("this version doesn't exist") )
}

View File

@ -110,8 +110,17 @@ Storage.prototype.add_version = function(name, version, metadata, tag, callback)
//
// Used storages: local (write)
//
Storage.prototype.add_tags = function(name, tag_hash, callback) {
return this.local.add_tags(name, tag_hash, callback)
Storage.prototype.merge_tags = function(name, tag_hash, callback) {
return this.local.merge_tags(name, tag_hash, callback)
}
//
// Tags a package version with a provided tag
//
// Used storages: local (write)
//
Storage.prototype.replace_tags = function(name, tag_hash, callback) {
return this.local.replace_tags(name, tag_hash, callback)
}
//

View File

@ -1,44 +1,44 @@
{
"name": "testexp_tags",
"name": "__NAME__",
"versions": {
"0.1.0": {
"name": "testexp_tags",
"name": "__NAME__",
"version": "0.1.0",
"dist": {
"shasum": "fake",
"tarball": "http://localhost:55551/testexp_tags/-/blahblah"
"tarball": "http://localhost:55551/__NAME__/-/blahblah"
}
},
"0.1.1alpha": {
"name": "testexp_tags",
"name": "__NAME__",
"version": "0.1.1alpha",
"dist": {
"shasum": "fake",
"tarball": "http://localhost:55551/testexp_tags/-/blahblah"
"tarball": "http://localhost:55551/__NAME__/-/blahblah"
}
},
"0.1.2": {
"name": "testexp_tags",
"name": "__NAME__",
"version": "0.1.2",
"dist": {
"shasum": "fake",
"tarball": "http://localhost:55551/testexp_tags/-/blahblah"
"tarball": "http://localhost:55551/__NAME__/-/blahblah"
}
},
"0.1.3alpha": {
"name": "testexp_tags",
"name": "__NAME__",
"version": "0.1.3alpha",
"dist": {
"shasum": "fake",
"tarball": "http://localhost:55551/testexp_tags/-/blahblah"
"tarball": "http://localhost:55551/__NAME__/-/blahblah"
}
},
"1.1": {
"name": "testexp_tags",
"name": "__NAME__",
"version": "1.1",
"dist": {
"shasum": "fake",
"tarball": "http://localhost:55551/testexp_tags/-/blahblah"
"tarball": "http://localhost:55551/__NAME__/-/blahblah"
}
}
},

View File

@ -18,7 +18,8 @@ module.exports = function() {
describe('tags', function() {
before(function () {
express.get('/testexp_tags', function(req, res) {
res.send(JSON.parse(readfile('fixtures/tags.json')))
var f = readfile('fixtures/tags.json').toString().replace(/__NAME__/g, 'testexp_tags')
res.send(JSON.parse(f))
})
})
@ -44,4 +45,124 @@ module.exports = function() {
})
})
})
describe('dist-tags methods', function() {
before(function () {
express.get('/testexp_tags2', function(req, res) {
var f = readfile('fixtures/tags.json').toString().replace(/__NAME__/g, 'testexp_tags2')
res.send(JSON.parse(f))
})
})
// populate cache
before(function () {
return server.get_package('testexp_tags2')
.status(200)
})
beforeEach(function () {
return server.request({
method: 'PUT',
uri: '/-/package/testexp_tags2/dist-tags',
json: {
foo: '0.1.0',
bar: '0.1.1alpha',
baz: '0.1.2',
},
}).status(201).body_ok(/tags updated/)
})
it('fetching tags', function () {
return server.request({
method: 'GET',
uri: '/-/package/testexp_tags2/dist-tags',
}).status(200).then(function (body) {
assert.deepEqual(body,
{ foo: '0.1.0',
bar: '0.1.1alpha',
baz: '0.1.2',
latest: '0.1.3alpha' })
})
})
it('merging tags', function () {
return server.request({
method: 'POST',
uri: '/-/package/testexp_tags2/dist-tags',
json: {
foo: '0.1.2',
quux: '0.1.0',
},
}).status(201).body_ok(/updated/).then(function () {
return server.request({
method: 'GET',
uri: '/-/package/testexp_tags2/dist-tags',
}).status(200).then(function (body) {
assert.deepEqual(body,
{ foo: '0.1.2',
bar: '0.1.1alpha',
baz: '0.1.2',
quux: '0.1.0',
latest: '0.1.3alpha' })
})
})
})
it('replacing tags', function () {
return server.request({
method: 'PUT',
uri: '/-/package/testexp_tags2/dist-tags',
json: {
foo: '0.1.2',
quux: '0.1.0',
},
}).status(201).body_ok(/updated/).then(function () {
return server.request({
method: 'GET',
uri: '/-/package/testexp_tags2/dist-tags',
}).status(200).then(function (body) {
assert.deepEqual(body,
{ foo: '0.1.2',
quux: '0.1.0',
latest: '0.1.3alpha' })
})
})
})
it('adding a tag', function () {
return server.request({
method: 'PUT',
uri: '/-/package/testexp_tags2/dist-tags/foo',
json: '0.1.3alpha',
}).status(201).body_ok(/tagged/).then(function () {
return server.request({
method: 'GET',
uri: '/-/package/testexp_tags2/dist-tags',
}).status(200).then(function (body) {
assert.deepEqual(body,
{ foo: '0.1.3alpha',
bar: '0.1.1alpha',
baz: '0.1.2',
latest: '0.1.3alpha' })
})
})
})
it('removing a tag', function () {
return server.request({
method: 'DELETE',
uri: '/-/package/testexp_tags2/dist-tags/foo',
}).status(201).body_ok(/removed/).then(function () {
return server.request({
method: 'GET',
uri: '/-/package/testexp_tags2/dist-tags',
}).status(200).then(function (body) {
assert.deepEqual(body,
{ bar: '0.1.1alpha',
baz: '0.1.2',
latest: '0.1.3alpha' })
})
})
})
})
}