From 2f45649a2caabad3451d76dd8190cb9393863437 Mon Sep 17 00:00:00 2001 From: Alex Kocharin Date: Sun, 8 Dec 2013 02:55:50 +0400 Subject: [PATCH] improving tags support, ref #8 --- lib/storage.js | 65 ++++++++++++++++++++++++++++++++++++++---------- lib/utils.js | 2 +- test/st_merge.js | 43 ++++++++++++++++++++++++++++++++ 3 files changed, 96 insertions(+), 14 deletions(-) create mode 100644 test/st_merge.js diff --git a/lib/storage.js b/lib/storage.js index 87a639ed6..0af05ceba 100644 --- a/lib/storage.js +++ b/lib/storage.js @@ -6,6 +6,7 @@ var async = require('async') , mystreams = require('./streams') , utils = require('./utils') , transaction = require('./transaction') + , Logger = require('./logger') // // Implements Storage interface @@ -24,6 +25,7 @@ function Storage(config) { this.uplinks[p].upname = p } this.local = new Local(config) + this.logger = Logger.logger.child() return this } @@ -422,6 +424,10 @@ Storage.prototype.get_package = function(name, callback) { try { utils.validate_metadata(up_res, name) } catch(err) { + self.logger.error({ + sub: 'out', + err: err, + }, 'package.json validating error @{!err.message}\n@{err.stack}') return cb(null, [err]) } @@ -429,21 +435,16 @@ Storage.prototype.get_package = function(name, callback) { etag: etag } - var this_version = up_res['dist-tags'].latest - if (latest == null - || (!semver.gt(latest, this_version) && this_version)) { - latest = this_version - var is_latest = true + try { + Storage._merge_versions(result, up_res) + } catch(err) { + self.logger.error({ + sub: 'out', + err: err, + }, 'package.json parsing error @{!err.message}\n@{err.stack}') + return cb(null, [err]) } - ;['versions', 'dist-tags'].forEach(function(key) { - for (var i in up_res[key]) { - if (!result[key][i] || is_latest) { - result[key][i] = up_res[key][i] - } - } - }) - // if we got to this point, assume that the correct package exists // on the uplink exists = true @@ -465,11 +466,49 @@ Storage.prototype.get_package = function(name, callback) { for (var i in result) { if (!~whitelist.indexOf(i)) delete result[i] } + + result['dist-tags'].latest = Object.keys(result.versions).sort(semver.compare) + for (var i in result['dist-tags']) { + if (Array.isArray(result['dist-tags'][i])) { + result['dist-tags'][i] = result['dist-tags'][i][result['dist-tags'][i].length-1] + } + } + callback(null, result, uplink_errors) }) }) }) } +// function gets a local info and an info from uplinks and tries to merge it +// exported for unit tests only +Storage._merge_versions = function(local, up) { + // copy new versions to a cache + // NOTE: if a certain version was updated, we can't refresh it reliably + for (var i in up.versions) { + if (local.versions[i] == null) { + local.versions[i] = up.versions[i] + } + } + + // refresh dist-tags + for (var i in up['dist-tags']) { + if (i === 'latest') continue + switch(typeof(local['dist-tags'][i])) { + case 'string': + local['dist-tags'][i] = [local['dist-tags'][i]] + break + case 'object': // array + break + default: + local['dist-tags'][i] = [] + } + if (local['dist-tags'][i].indexOf(up['dist-tags'][i]) === -1) { + local['dist-tags'][i].push(up['dist-tags'][i]) + local['dist-tags'][i].sort(semver.compare) + } + } +} + module.exports = Storage diff --git a/lib/utils.js b/lib/utils.js index f08446228..ba6c67e57 100644 --- a/lib/utils.js +++ b/lib/utils.js @@ -24,7 +24,7 @@ module.exports.is_object = function(obj) { } module.exports.validate_metadata = function(object, name) { - assert(module.exports.is_object(object)) + assert(module.exports.is_object(object), 'not a json object') assert.equal(object.name, name) if (!module.exports.is_object(object['dist-tags'])) { diff --git a/test/st_merge.js b/test/st_merge.js new file mode 100644 index 000000000..014d0c514 --- /dev/null +++ b/test/st_merge.js @@ -0,0 +1,43 @@ +var assert = require('assert') + , merge = require('../lib/storage')._merge_versions + +//require('../lib/logger').setup() + +exports['Merge'] = { + 'simple': function() { + var x = { + versions: {a:1,b:1,c:1}, + 'dist-tags': {}, + } + merge(x, {versions: {a:2,q:2}}) + assert.deepEqual(x, { + versions: {a:1,b:1,c:1,q:2}, + 'dist-tags': {}, + }) + }, + + 'dist-tags - compat': function() { + var x = { + versions: {}, + 'dist-tags': {q:'1.1.1',w:['2.2.2']}, + } + merge(x, {'dist-tags':{q:'2.2.2',w:'3.3.3',t:'4.4.4'}}) + assert.deepEqual(x, { + versions: {}, + 'dist-tags': {q:['1.1.1','2.2.2'],w:['2.2.2','3.3.3'],t:['4.4.4']}, + }) + }, + + 'dist-tags - sort': function() { + var x = { + versions: {}, + 'dist-tags': {w:['2.2.2','1.1.1','12.2.2','2.2.2-rc2']}, + } + merge(x, {'dist-tags':{w:'3.3.3'}}) + assert.deepEqual(x, { + versions: {}, + 'dist-tags': {w:["1.1.1","2.2.2-rc2","2.2.2","3.3.3","12.2.2"]}, + }) + }, +} +