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 function tag_package_version(req, res, next) {
app.put('/:package/:tag', can('publish'), media('application/json'), function(req, res, next) {
if (typeof(req.body) !== 'string') return next('route') if (typeof(req.body) !== 'string') return next('route')
var tags = {} var tags = {}
tags[req.params.tag] = req.body 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) if (err) return next(err)
res.status(201) res.status(201)
return next({ ok: 'package tagged' }) 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 // publishing a package
@ -271,7 +331,7 @@ module.exports = function(config, auth, storage) {
} }
function add_tags(tags, cb) { 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) }, callback)
} }
Storage.prototype.add_tags = function(name, tags, callback) { Storage.prototype.merge_tags = function(name, tags, callback) {
var self = this var self = this
self.update_package(name, function updater(data, cb) { self.update_package(name, function updater(data, cb) {
for (var t in 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") )
}
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) { if (data.versions[tags[t]] == null) {
return cb( Error[404]("this version doesn't exist") ) 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) // Used storages: local (write)
// //
Storage.prototype.add_tags = function(name, tag_hash, callback) { Storage.prototype.merge_tags = function(name, tag_hash, callback) {
return this.local.add_tags(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": { "versions": {
"0.1.0": { "0.1.0": {
"name": "testexp_tags", "name": "__NAME__",
"version": "0.1.0", "version": "0.1.0",
"dist": { "dist": {
"shasum": "fake", "shasum": "fake",
"tarball": "http://localhost:55551/testexp_tags/-/blahblah" "tarball": "http://localhost:55551/__NAME__/-/blahblah"
} }
}, },
"0.1.1alpha": { "0.1.1alpha": {
"name": "testexp_tags", "name": "__NAME__",
"version": "0.1.1alpha", "version": "0.1.1alpha",
"dist": { "dist": {
"shasum": "fake", "shasum": "fake",
"tarball": "http://localhost:55551/testexp_tags/-/blahblah" "tarball": "http://localhost:55551/__NAME__/-/blahblah"
} }
}, },
"0.1.2": { "0.1.2": {
"name": "testexp_tags", "name": "__NAME__",
"version": "0.1.2", "version": "0.1.2",
"dist": { "dist": {
"shasum": "fake", "shasum": "fake",
"tarball": "http://localhost:55551/testexp_tags/-/blahblah" "tarball": "http://localhost:55551/__NAME__/-/blahblah"
} }
}, },
"0.1.3alpha": { "0.1.3alpha": {
"name": "testexp_tags", "name": "__NAME__",
"version": "0.1.3alpha", "version": "0.1.3alpha",
"dist": { "dist": {
"shasum": "fake", "shasum": "fake",
"tarball": "http://localhost:55551/testexp_tags/-/blahblah" "tarball": "http://localhost:55551/__NAME__/-/blahblah"
} }
}, },
"1.1": { "1.1": {
"name": "testexp_tags", "name": "__NAME__",
"version": "1.1", "version": "1.1",
"dist": { "dist": {
"shasum": "fake", "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() { describe('tags', function() {
before(function () { before(function () {
express.get('/testexp_tags', function(req, res) { 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' })
})
})
})
})
} }