Compare commits

..

10 Commits
1.1.0 ... 1.2.2

Author SHA1 Message Date
dead_horse
764c32646e Release 1.2.2 2014-08-08 10:47:50 +08:00
dead_horse
dea16e72de bump koa 2014-08-08 10:45:50 +08:00
fengmk2
7f951a6c5d Release 1.2.1 2014-08-07 18:19:08 +08:00
fengmk2
a1f2bc87b7 Merge pull request #418 from cnpm/undeprecate
deprecated bug fix and support undeprecate
2014-08-07 18:18:31 +08:00
fengmk2
706a5e053b deprecated bug fix and support undeprecate 2014-08-07 18:06:32 +08:00
fengmk2
eddc1a1bb9 Release 1.2.0 2014-08-07 17:27:39 +08:00
dead_horse
6e5abe44b9 Merge pull request #417 from cnpm/deprecate-api
Deprecate API
2014-08-07 17:20:30 +08:00
fengmk2
e6484e7e7b show deprecated message 2014-08-07 17:18:44 +08:00
fengmk2
7a88fa49d2 Sync deprecated field if it missing 2014-08-07 16:48:41 +08:00
fengmk2
82189bd393 Support $ cnpm deprecate [pkgname]@[version] "message". fixed #415 2014-08-07 16:24:35 +08:00
11 changed files with 426 additions and 51 deletions

View File

@@ -1,4 +1,21 @@
1.2.2 / 2014-08-08
==================
* bump koa
1.2.1 / 2014-08-07
==================
* deprecated bug fix and support undeprecate
1.2.0 / 2014-08-07
==================
* show deprecated message
* Sync deprecated field if it missing
* Support $ cnpm deprecate [pkgname]@[version] "message". fixed #415
1.1.0 / 2014-08-07
==================

View File

@@ -0,0 +1,60 @@
/**!
* cnpmjs.org - controllers/registry/deprecate.js
*
* Copyright(c) fengmk2 and other contributors.
* MIT Licensed
*
* Authors:
* fengmk2 <fengmk2@gmail.com> (http://fengmk2.github.com)
*/
'use strict';
/**
* Module dependencies.
*/
var Module = require('../../proxy/module');
module.exports = deprecateVersions;
/**
* @see https://github.com/cnpm/cnpmjs.org/issues/415
*/
function* deprecateVersions(next) {
var body = this.request.body;
var name = this.params.name || this.params[0];
var tasks = [];
for (var version in body.versions) {
tasks.push(Module.get(name, version));
}
var rs = yield tasks;
var updateTasks = [];
for (var i = 0; i < rs.length; i++) {
var row = rs[i];
if (!row) {
// some version not exists
this.status = 400;
this.body = {
error: 'version_error',
reason: 'Some versions: ' + JSON.stringify(Object.keys(body.versions)) + ' not found'
};
return;
}
var data = body.versions[row.package.version];
if (typeof data.deprecated === 'string') {
row.package.deprecated = data.deprecated;
updateTasks.push(Module.updatePackage(row.id, row.package));
}
}
yield updateTasks;
// update last modified
yield* Module.updateLastModified(name);
this.status = 201;
this.body = {
ok: true
};
}

View File

@@ -41,6 +41,7 @@ var ModuleUnpublished = require('../../proxy/module_unpublished');
var packageService = require('../../services/package');
var UserService = require('../../services/user');
var downloadAsReadStream = require('../utils').downloadAsReadStream;
var deprecateVersions = require('./deprecate');
/**
* show all version of a module
@@ -431,11 +432,43 @@ exports.addPackageAndDist = function *(next) {
var name = this.params.name || this.params[0];
var filename = Object.keys(pkg._attachments || {})[0];
var version = Object.keys(pkg.versions || {})[0];
if (!version || !filename) {
if (!version) {
this.status = 400;
this.body = {
error: 'version_error',
reason: 'filename or version not found, filename: ' + filename + ', version: ' + version
reason: 'version ' + version + ' not found'
};
return;
}
// check maintainers
var isMaintainer = yield* packageService.isMaintainer(name, username);
if (!isMaintainer) {
this.status = 403;
this.body = {
error: 'forbidden user',
reason: username + ' not authorized to modify ' + name
};
return;
}
if (!filename) {
var hasDeprecated = false;
for (var v in pkg.versions) {
var row = pkg.versions[v];
if (typeof row.deprecated === 'string') {
hasDeprecated = true;
break;
}
}
if (hasDeprecated) {
return yield* deprecateVersions.call(this, next);
}
this.status = 400;
this.body = {
error: 'filename_error',
reason: 'filename ' + filename + ' not found'
};
return;
}
@@ -501,17 +534,6 @@ exports.addPackageAndDist = function *(next) {
return;
}
// check maintainers
var isMaintainer = yield* packageService.isMaintainer(name, username);
if (!isMaintainer) {
this.status = 403;
this.body = {
error: 'forbidden user',
reason: username + ' not authorized to modify ' + name
};
return;
}
// upload attachment
var tarballBuffer;
tarballBuffer = new Buffer(attachment.data, 'base64');

View File

@@ -1,6 +1,6 @@
{
"name": "cnpmjs.org",
"version": "1.1.0",
"version": "1.2.2",
"description": "Private npm registry and web for Enterprise, base on MySQL and Simple Store Service",
"main": "index.js",
"scripts": {
@@ -28,7 +28,7 @@
"graceful": "~0.1.0",
"gravatar": "~1.0.6",
"humanize-number": "~0.0.2",
"koa": "~0.8.2",
"koa": "~0.9.0",
"koa-limit": "~1.0.2",
"koa-markdown": "~0.0.3",
"koa-middlewares": "~1.2.0",

View File

@@ -162,26 +162,6 @@ exports.updateDescription = function (id, description, callback) {
mysql.query(UPDATE_DESC_SQL, [description, id], callback);
};
var UPDATE_PACKAGE_SQL = multiline(function () {;/*
UPDATE
module
SET
package=?
WHERE
id=?;
*/});
exports.updateReadme = function (id, readme, callback) {
exports.getById(id, function (err, data) {
if (err) {
return callback(err);
}
data.package = data.package || {};
data.package.readme = readme;
var pkg = stringifyPackage(data.package);
mysql.query(UPDATE_PACKAGE_SQL, [pkg, id], callback);
});
};
var UPDATE_DIST_SQL = 'UPDATE module SET ? WHERE id=?';
exports.update = function (mod, callback) {
var pkg;
@@ -746,3 +726,39 @@ exports.listByAuthor = function* (author, callback) {
});
return yield mysql.query(LIST_BY_AUTH_SQLS[3], [ids]);
};
var UPDATE_PACKAGE_SQL = multiline(function () {;/*
UPDATE
module
SET
package=?
WHERE
id=?;
*/});
exports.updatePackage = function* (id, pkg) {
pkg = stringifyPackage(pkg);
return yield mysql.query(UPDATE_PACKAGE_SQL, [pkg, id]);
};
exports.updatePackageFields = function* (id, fields) {
var data = yield exports.getById(id);
if (!data) {
throw new Error('module#' + id + ' not exists');
}
data.package = data.package || {};
for (var k in fields) {
data.package[k] = fields[k];
}
return yield* exports.updatePackage(id, data.package);
};
exports.updateReadme = function* (id, readme) {
var data = yield exports.getById(id);
if (!data) {
throw new Error('module#' + id + ' not exists');
}
data.package = data.package || {};
data.package.readme = readme;
return yield* exports.updatePackage(id, data.package);
};

View File

@@ -341,6 +341,7 @@ SyncModuleWorker.prototype._sync = function* (name, pkg) {
var missingReadmes = [];
var missingStarUsers = [];
var npmUsernames = {};
var missingDeprecateds = [];
// find out all user names
for (var v in pkg.versions) {
@@ -430,8 +431,9 @@ SyncModuleWorker.prototype._sync = function* (name, pkg) {
var sourceAuthor = version.maintainers && version.maintainers[0] &&
version.maintainers[0].name || exists.author;
if (exists.package && exists.package.dist.shasum === version.dist.shasum &&
exists.author === sourceAuthor) {
if (exists.package &&
exists.package.dist.shasum === version.dist.shasum &&
exists.author === sourceAuthor) {
// * author make sure equal
// * shasum make sure equal
if ((version.publish_time === exists.publish_time) ||
@@ -454,6 +456,14 @@ SyncModuleWorker.prototype._sync = function* (name, pkg) {
readme: version.readme
});
}
if (version.deprecated && version.deprecated !== exists.package.deprecated) {
// need to sync deprecated field
missingDeprecateds.push({
id: exists.id,
deprecated: version.deprecated
});
}
continue;
}
}
@@ -604,6 +614,29 @@ SyncModuleWorker.prototype._sync = function* (name, pkg) {
}
}
function *syncDeprecateds() {
if (missingDeprecateds.length === 0) {
return;
}
that.log(' [%s] saving %d Deprecated fields', name, missingDeprecateds.length);
var res = yield gather(missingDeprecateds.map(function (item) {
return Module.updatePackageFields(item.id, {
deprecated: item.deprecated
});
}));
for (var i = 0; i < res.length; i++) {
var item = missingDeprecateds[i];
var r = res[i];
if (r.error) {
that.log(' save error, id: %s, error: %s', item.id, r.error.message);
} else {
that.log(' saved, id: %s', item.id);
}
}
}
function *syncMissingUsers() {
var missingUsers = [];
var names = Object.keys(npmUsernames);
@@ -660,7 +693,9 @@ SyncModuleWorker.prototype._sync = function* (name, pkg) {
}
}
yield [syncDes(), syncTag(), syncReadme(), syncMissingStarUsers(), syncMissingUsers()];
yield [
syncDes(), syncTag(), syncReadme(), syncDeprecateds(),
syncMissingStarUsers(), syncMissingUsers()];
return syncedVersionNames;
};

View File

@@ -0,0 +1,211 @@
/**!
* cnpmjs.org - test/controllers/registry/deprecate.test.js
*
* Copyright(c) cnpmjs.org and other contributors.
* MIT Licensed
*
* Authors:
* fengmk2 <fengmk2@gmail.com> (http://fengmk2.github.com)
*/
'use strict';
/**
* Module dependencies.
*/
var fs = require('fs');
var path = require('path');
var should = require('should');
var request = require('supertest');
var mm = require('mm');
var pedding = require('pedding');
var app = require('../../../servers/registry');
var utils = require('../../utils');
var fixtures = path.join(path.dirname(path.dirname(__dirname)), 'fixtures');
describe('controllers/registry/deprecate.test.js', function () {
var pkgname = 'testmodule-deprecate';
before(function (done) {
done = pedding(2, done);
var pkg = utils.getPackage(pkgname, '0.0.1', utils.admin);
request(app.listen())
.put('/' + pkgname)
.set('authorization', utils.adminAuth)
.send(pkg)
.expect(201, function (err) {
should.not.exist(err);
pkg = utils.getPackage(pkgname, '0.0.2', utils.admin);
// publish 0.0.2
request(app.listen())
.put('/' + pkgname)
.set('authorization', utils.adminAuth)
.send(pkg)
.expect(201, done);
});
pkg = utils.getPackage(pkgname, '1.0.0', utils.admin);
request(app.listen())
.put('/' + pkgname)
.set('authorization', utils.adminAuth)
.send(pkg)
.expect(201, done);
});
afterEach(mm.restore);
describe('PUT /:name', function () {
it('should deprecate version@1.0.0', function (done) {
request(app.listen())
.put('/' + pkgname)
.set('authorization', utils.adminAuth)
.send({
name: pkgname,
versions: {
'1.0.0': {
deprecated: 'mock test deprecated message 1.0.0'
}
}
})
.expect({
ok: true
})
.expect(201, function (err, res) {
should.not.exist(err);
request(app.listen())
.get('/' + pkgname + '/1.0.0')
.expect(200, function (err, res) {
should.not.exist(err);
res.body.deprecated.should.equal('mock test deprecated message 1.0.0');
// undeprecated
request(app.listen())
.put('/' + pkgname)
.set('authorization', utils.adminAuth)
.send({
name: pkgname,
versions: {
'1.0.0': {
deprecated: ''
}
}
})
.expect({
ok: true
})
.expect(201, function (err) {
should.not.exist(err);
request(app.listen())
.get('/' + pkgname + '/1.0.0')
.expect(200, function (err, res) {
should.not.exist(err);
res.body.deprecated.should.equal('');
done();
});
});
});
});
});
it('should deprecate version@<1.0.0', function (done) {
request(app.listen())
.put('/' + pkgname)
.set('authorization', utils.adminAuth)
.send({
name: pkgname,
versions: {
'1.0.0': {
version: '1.0.0'
},
'0.0.1': {
deprecated: 'mock test deprecated message 0.0.1'
},
'0.0.2': {
deprecated: 'mock test deprecated message 0.0.2'
}
}
})
.expect({
ok: true
})
.expect(201, function (err, res) {
should.not.exist(err);
done = pedding(3, done);
request(app.listen())
.get('/' + pkgname + '/0.0.1')
.expect(200, function (err, res) {
should.not.exist(err);
res.body.deprecated.should.equal('mock test deprecated message 0.0.1');
done();
});
request(app.listen())
.get('/' + pkgname + '/0.0.2')
.expect(200, function (err, res) {
should.not.exist(err);
res.body.deprecated.should.equal('mock test deprecated message 0.0.2');
done();
});
// not change 1.0.0
request(app.listen())
.get('/' + pkgname + '/1.0.0')
.expect(200, function (err, res) {
should.not.exist(err);
res.body.deprecated.should.equal('');
done();
});
});
});
it('should 404 deprecate not exists version', function (done) {
request(app.listen())
.put('/' + pkgname)
.set('authorization', utils.adminAuth)
.send({
name: pkgname,
versions: {
'1.0.1': {
deprecated: 'mock test deprecated message'
},
'1.0.0': {
deprecated: 'mock test deprecated message'
}
}
})
.expect({
error: 'version_error',
reason: 'Some versions: ["1.0.1","1.0.0"] not found'
})
.expect(400, done);
});
it('should 403', function (done) {
request(app.listen())
.put('/' + pkgname)
.set('authorization', utils.otherUserAuth)
.send({
name: pkgname,
versions: {
'1.0.0': {
version: '1.0.0'
},
'0.0.1': {
deprecated: 'mock test deprecated message 0.0.1'
},
'0.0.2': {
deprecated: 'mock test deprecated message 0.0.2'
}
}
})
.expect({
error: 'no_perms',
reason: 'Private mode enable, only admin can publish this module'
})
.expect(403, done);
});
});
});

View File

@@ -477,7 +477,7 @@ describe('controllers/registry/module.test.js', function () {
.send(pkg)
.expect(400, function (err, res) {
should.not.exist(err);
res.body.reason.should.containEql('filename or version not found');
res.body.reason.should.equal('version undefined not found');
done();
});
});
@@ -502,7 +502,7 @@ describe('controllers/registry/module.test.js', function () {
should.not.exist(err);
res.body.should.eql({
error: 'version_error',
reason: 'filename or version not found, filename: undefined, version: undefined'
reason: 'version undefined not found'
});
done();
});
@@ -580,7 +580,7 @@ describe('controllers/registry/module.test.js', function () {
should.not.exist(err);
res.body.should.eql({
error: 'version_error',
reason: 'filename or version not found, filename: mk2testmodule-0.0.1.tgz, version: undefined'
reason: 'version undefined not found'
});
done();
});

View File

@@ -18,14 +18,30 @@ var should = require('should');
var mm = require('mm');
var fs = require('fs');
var path = require('path');
var request = require('supertest');
var mysql = require('../../common/mysql');
var Module = require('../../proxy/module');
var config = require('../../config');
var utils = require('../utils');
var app = require('../../servers/registry');
var fixtures = path.join(path.dirname(__dirname), 'fixtures');
var id;
var pkgname = 'module-proxy-test-pkg';
var pkgversion = '1.0.0';
describe('proxy/module.test.js', function () {
before(function (done) {
var pkg = utils.getPackage(pkgname, pkgversion, utils.admin);
request(app.listen())
.put('/' + pkgname)
.set('authorization', utils.adminAuth)
.send(pkg)
.expect(201, done);
});
afterEach(mm.restore);
describe('addTag()', function () {
@@ -154,15 +170,12 @@ describe('proxy/module.test.js', function () {
});
describe('updateReadme()', function () {
it('should update ok', function (done) {
Module.updateReadme(id, 'test', function (err, data) {
should.not.exist(err);
Module.getById(id, function (err, data) {
should.not.exist(err);
data.package.readme.should.equal('test');
done();
});
});
it('should update ok', function* () {
var row = yield Module.get(pkgname, pkgversion);
should.exist(row);
yield* Module.updateReadme(row.id, 'test');
var data = yield Module.getById(row.id);
data.package.readme.should.equal('test');
});
});

View File

@@ -34,6 +34,7 @@
.nav-tabs{margin:20px 0;}
.nav-cont{display:none;}
.nav-cont.active{display:block;}
.deprecated{color:red;}
</style>
<script>
$(function () {

View File

@@ -11,7 +11,7 @@
</h1>
<% if (package.deprecated) { %>
<p class="deprecated"><%= package.deprecated %></p>
<p class="deprecated">[DEPRECATED] <%= package.deprecated %></p>
<% } %>
<% if (package.description) { %>