Skip to content
This repository has been archived by the owner on Jun 2, 2024. It is now read-only.

Commit

Permalink
add module tag. fix #6
Browse files Browse the repository at this point in the history
  • Loading branch information
fengmk2 committed Dec 9, 2013
1 parent 8b84d69 commit 3dab321
Show file tree
Hide file tree
Showing 6 changed files with 183 additions and 49 deletions.
76 changes: 52 additions & 24 deletions controllers/registry/module.js
Original file line number Diff line number Diff line change
Expand Up @@ -35,25 +35,32 @@ var SyncModuleWorker = require('./sync_module_worker');

exports.show = function (req, res, next) {
var name = req.params.name;
Module.listByName(name, function (err, rows) {
if (err || rows.length === 0) {
return next(err);
var ep = eventproxy.create();
ep.fail(next);

Module.listTags(name, ep.done('tags'));
Module.listByName(name, ep.done('rows'));

ep.all('tags', 'rows', function (tags, rows) {
if (rows.length === 0) {
return next();
}

var nextMod = rows[0];
var latest = rows[1];
var startIndex = 1;
var latestMod = null;
if (nextMod.version !== 'next') {
// next create fail
latest = nextMod;
startIndex = 0;
nextMod = null;
}

if (!latest) {
latest = nextMod;
var distTags = {};
for (var i = 0; i < tags.length; i++) {
var t = tags[i];
distTags[t.tag] = t.version;
}

var distTags = {};
var versions = {};
var times = {};
var attachments = {};
Expand All @@ -62,10 +69,13 @@ exports.show = function (req, res, next) {
var pkg = row.package;
versions[pkg.version] = pkg;
times[pkg.version] = row.gmt_modified;
if ((!distTags.latest && !latestMod) || distTags.latest === row.version) {
latestMod = row;
}
}

if (latest.package.version && latest.package.version !== 'next') {
distTags.latest = latest.package.version;
if (!latestMod) {
latestMod = nextMod;
}

var rev = '';
Expand All @@ -74,28 +84,41 @@ exports.show = function (req, res, next) {
}

var info = {
_id: latest.name,
_id: name,
_rev: rev,
name: latest.name,
description: latest.package.description,
name: name,
description: latestMod.package.description,
versions: versions,
"dist-tags": distTags,
readme: latest.package.readme,
maintainers: latest.package.maintainers,
readme: latestMod.package.readme,
maintainers: latestMod.package.maintainers,
time: times,
author: latest.package.author,
repository: latest.package.repository,
author: latestMod.package.author,
repository: latestMod.package.repository,
_attachments: attachments
};

res.json(info);
});
};

var VERSION_RE = /^\d+\.\d+\.\d+/;

exports.get = function (req, res, next) {
var name = req.params.name;
var version = req.params.version;
Module.get(name, version, function(err, mod) {
if (VERSION_RE.test(version)) {
Module.get(name, version, function (err, mod) {
if (err || !mod) {
return next(err);
}
res.json(mod.package);
});
return;
}

var tag = version;
Module.getByTag(name, tag, function (err, mod) {
if (err || !mod) {
return next(err);
}
Expand Down Expand Up @@ -222,7 +245,6 @@ exports.updateLatest = function (req, res, next) {
if (!body.author) {
body.author = {
name: username,
email: req.session.email,
};
}
nextMod.package = body;
Expand All @@ -232,13 +254,19 @@ exports.updateLatest = function (req, res, next) {
if (err) {
return next(err);
}
// add a new latest version
nextMod.version = 'next';
Module.add(nextMod, function (err, result) {
// set latest tag
Module.addTag(name, 'latest', version, function (err) {
if (err) {
return next(err);
return next();
}
res.json(201, {ok: true, rev: String(result.id)});
// add a new next version
nextMod.version = 'next';
Module.add(nextMod, function (err, result) {
if (err) {
return next(err);
}
res.json(201, {ok: true, rev: String(result.id)});
});
});
});
});
Expand Down
44 changes: 42 additions & 2 deletions controllers/registry/sync_module_worker.js
Original file line number Diff line number Diff line change
Expand Up @@ -119,13 +119,26 @@ SyncModuleWorker.prototype._sync = function (pkg, callback) {
if (r.version === 'next') {
continue;
}
if (!map.latest) {
map.latest = r;
}
map[r.version] = r;
}
ep.emit('existsMap', map);
}));

Module.listTags(name, ep.done(function (rows) {
var tags = {};
for (var i = 0; i < rows.length; i++) {
var r = rows[i];
tags[r.tag] = r.version;
}
ep.emit('existsTags', tags);
}));

var missingVersions = [];
ep.on('existsMap', function (map) {
var missingTags = [];
ep.all('existsMap', 'existsTags', function (map, tags) {
var times = pkg.time || {};
var versions = [];
for (var v in times) {
Expand All @@ -141,6 +154,14 @@ SyncModuleWorker.prototype._sync = function (pkg, callback) {
versions.push(version);
}

var sourceTags = pkg['dist-tags'] || {};
for (var t in sourceTags) {
var sourceTagVersion = sourceTags[t];
if (sourceTagVersion && tags[t] !== sourceTagVersion) {
missingTags.push([t, sourceTagVersion]);
}
}

if (versions.length === 0) {
that.log(' [%s] all versions are exists', pkg.name);
return ep.emit('done');
Expand All @@ -160,12 +181,31 @@ SyncModuleWorker.prototype._sync = function (pkg, callback) {
that._syncOneVersion(versionNames.length, syncModule, ep.done(function (result) {
var nextVersion = missingVersions.shift();
if (!nextVersion) {
return ep.emit('done', result);
return ep.emit('syncDone', result);
}
ep.emit('syncModule', nextVersion);
}));
});

ep.on('syncDone', function () {
if (missingTags.length === 0) {
return ep.emit('done');
}

that.log(' [%s] adding %d tags', pkg.name, missingTags.length);
// sync tags
missingTags.forEach(function (item) {
Module.addTag(pkg.name, item[0], item[1], ep.done(function (result) {
that.log(' added tag %s:%s', item[0], item[1]);
ep.emit('addTag');
}));
});

ep.after('addTag', missingTags.length, function () {
ep.emit('done');
});
});

ep.on('done', function () {
// TODO: set latest version
callback(null, versionNames);
Expand Down
13 changes: 12 additions & 1 deletion docs/db.sql
Original file line number Diff line number Diff line change
Expand Up @@ -42,10 +42,21 @@ CREATE TABLE `module_log` (
KEY `name` (`name`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8 COMMENT='module sync log';

CREATE TABLE `tag` (
`id` bigint(20) unsigned NOT NULL AUTO_INCREMENT COMMENT 'primary key',
`gmt_create` datetime NOT NULL COMMENT 'create time',
`gmt_modified` datetime NOT NULL COMMENT 'modified time',
`name` varchar(100) NOT NULL COMMENT 'module name',
`tag` varchar(30) NOT NULL COMMENT 'tag name',
`version` varchar(30) NOT NULL COMMENT 'module version',
PRIMARY KEY (`id`),
UNIQUE KEY `name` (`name`, `tag`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8 COMMENT='module tag';

CREATE TABLE `total` (
`name` varchar(100) NOT NULL COMMENT 'total name',
`gmt_modified` datetime NOT NULL COMMENT 'modified time',
`module_delete` bigint(20) unsigned NOT NULL DEFAULT '0' COMMENT 'module delete count',
PRIMARY KEY (`name`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8 COMMENT='total info';
INSERT INTO total(name, gmt_modified, module_delete) VALUES('total', now(), 0);
INSERT INTO total(name, gmt_modified, module_delete) VALUES('total', now(), 0);
58 changes: 49 additions & 9 deletions proxy/module.js
Original file line number Diff line number Diff line change
Expand Up @@ -108,20 +108,60 @@ exports.get = function (name, version, callback) {
});
};

var SELECT_LATEST_MODULE_SQL = 'SELECT ' + MODULE_COLUMNS + ' FROM module WHERE name=? AND version <> "next" ORDER BY id DESC LIMIT 1;';
var INSERT_TAG_SQL = 'INSERT INTO tag(gmt_create, gmt_modified, \
name, tag, version) \
VALUES(now(), now(), ?, ?, ?) \
ON DUPLICATE KEY UPDATE gmt_modified=now(), \
name=VALUES(name), tag=VALUES(tag), version=VALUES(version);';

exports.getLatest = function (name, callback) {
mysql.queryOne(SELECT_LATEST_MODULE_SQL, [name], function (err, row) {
exports.addTag = function (name, tag, version, callback) {
mysql.query(INSERT_TAG_SQL, [name, tag, version], function (err, result) {
if (err) {
return callback(err);
}
callback(null, {id: result.insertId, gmt_modified: new Date()});
});
};

var SELECT_TAG_SQL = 'SELECT tag, version, gmt_modified FROM tag WHERE name=? AND tag=?;';

exports.getByTag = function (name, tag, callback) {
mysql.queryOne(SELECT_TAG_SQL, [name, tag], function (err, row) {
if (err || !row) {
return callback(err, row);
}
try {
parseRow(row);
} catch (e) {
e.data = row;
return callback(e);
exports.get(name, row.version, callback);
});
};

var SELECT_ALL_TAGS_SQL = 'SELECT tag, version, gmt_modified FROM tag WHERE name=?;';

exports.listTags = function (name, callback) {
mysql.query(SELECT_ALL_TAGS_SQL, [name], callback);
};

var SELECT_LATEST_MODULE_SQL = 'SELECT ' + MODULE_COLUMNS +
' FROM module WHERE name=? AND version <> "next" ORDER BY id DESC LIMIT 1;';

exports.getLatest = function (name, callback) {
exports.getByTag(name, 'latest', function (err, row) {
if (err || row) {
return callback(err, row);
}
callback(null, row);

// get latest order by id
mysql.queryOne(SELECT_LATEST_MODULE_SQL, [name], function (err, row) {
if (err || !row) {
return callback(err, row);
}
try {
parseRow(row);
} catch (e) {
e.data = row;
return callback(e);
}
callback(null, row);
});
});
};

Expand Down
32 changes: 23 additions & 9 deletions test/controllers/registry/module.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -73,27 +73,41 @@ describe('controllers/registry/module.test.js', function () {
res.body.should.have.keys('_id', '_rev', 'name', 'description',
'versions', 'dist-tags', 'readme', 'maintainers',
'time', 'author', 'repository', '_attachments');
res.body.author.should.eql({
"name": "fengmk2",
"email": "[email protected]",
"url": "http://fengmk2.github.com"
});
// res.body.author.should.eql({
// "name": "fengmk2",
// "email": "[email protected]",
// "url": "http://fengmk2.github.com"
// });
res.body.name.should.equal('cnpmjs.org');
done();
});
});
});

describe('GET /:name/:version', function () {
describe('GET /:name/:(version|tag)', function () {
it('should return module@version info', function (done) {
request(app)
.get('/cnpmjs.org/0.0.2')
.get('/cnpmjs.org/0.0.4')
.expect(200, function (err, res) {
should.not.exist(err);
var body = res.body;
body.name.should.equal('cnpmjs.org');
body.version.should.equal('0.0.4');
body._id.should.equal('[email protected]');
body.dist.should.have.keys('tarball', 'shasum', 'size');
done();
});
});

it('should return module@tag info', function (done) {
request(app)
.get('/cnpmjs.org/latest')
.expect(200, function (err, res) {
should.not.exist(err);
var body = res.body;
body.name.should.equal('cnpmjs.org');
body.version.should.equal('0.0.2');
body._id.should.equal('[email protected].2');
body.version.should.equal('0.0.4');
body._id.should.equal('[email protected].4');
body.dist.should.have.keys('tarball', 'shasum', 'size');
done();
});
Expand Down
9 changes: 5 additions & 4 deletions test/middleware/auth.test.js
Original file line number Diff line number Diff line change
@@ -1,10 +1,11 @@
/*!
* cnpmjs.org - test/controllers/registry/user.test.js
/**!
* cnpmjs.org - test/middleware/auth.test.js
*
* Copyright(c) cnpmjs.org and other contributors.
* MIT Licensed
*
* Authors:
* dead_horse <[email protected]> (http://deadhorse.me)
* fengmk2 <[email protected]> (http://fengmk2.github.com)
*/

Expand All @@ -20,7 +21,7 @@ var app = require('../../servers/registry');
var mm = require('mm');
var mysql = require('../../common/mysql');

describe('middleware/auth', function () {
describe('middleware/auth.test.js', function () {
before(function (done) {
app.listen(0, done);
});
Expand Down Expand Up @@ -56,6 +57,6 @@ describe('middleware/auth', function () {
.get('/-/user/org.couchdb.user:cnpmjstest10')
.set('authorization', 'basic ' + new Buffer('cnpmjstest10:cnpmjstest10').toString('base64'))
.expect(500, done);
});
});
});
});

0 comments on commit 3dab321

Please sign in to comment.