Unregister and login commands

This commit is contained in:
Mat Scales
2014-04-01 16:41:32 +01:00
committed by Adam Stankiewicz
parent 1080cb71c4
commit 126da9ee12
10 changed files with 233 additions and 1 deletions

View File

@@ -20,7 +20,7 @@ module.exports = function (grunt) {
simplemocha: {
options: {
reporter: 'spec',
timeout: '10000'
timeout: '15000'
},
full: {
src: ['test/test.js']

View File

@@ -66,11 +66,13 @@ module.exports = {
install: commandFactory('./install'),
link: commandFactory('./link'),
list: commandFactory('./list'),
login: commandFactory('./login'),
lookup: commandFactory('./lookup'),
prune: commandFactory('./prune'),
register: commandFactory('./register'),
search: commandFactory('./search'),
update: commandFactory('./update'),
uninstall: commandFactory('./uninstall'),
unregister: commandFactory('./unregister'),
version: commandFactory('./version')
};

90
lib/commands/login.js Normal file
View File

@@ -0,0 +1,90 @@
var Configstore = require('configstore');
var GitHub = require('github');
var Q = require('q');
var createError = require('../util/createError');
var defaultConfig = require('../config');
function login(logger, options, config) {
var configstore = new Configstore('bower-github');
config = defaultConfig(config);
var promise;
if (options.token) {
promise = Q.resolve({ token: options.token });
} else {
// This command requires interactive to be enabled
if (!config.interactive) {
process.nextTick(function () {
logger.emit('error', createError('Login requires an interactive shell', 'ENOINT', {
details: 'Note that you can manually force an interactive shell with --config.interactive'
}));
});
return logger;
}
var questions = [
{
'name': 'username',
'message': 'Username',
'type': 'input',
'default': configstore.get('username')
},
{
'name': 'password',
'message': 'Password',
'type': 'password'
}
];
var github = new GitHub({
version: '3.0.0'
});
promise = Q.nfcall(logger.prompt.bind(logger), questions)
.then(function (answers) {
configstore.set('username', answers.username);
github.authenticate({
type: 'basic',
username: answers.username,
password: answers.password
});
return Q.ninvoke(github.authorization, 'create', {
scopes: ['user', 'repo'],
note: 'Bower command line client (' + (new Date()).toISOString() + ')'
});
});
}
promise
.fail(function (error) {
logger.error('login error', 'Could not authenticate');
})
.then(function (result) {
configstore.set('accessToken', result.token);
logger.emit('end', result);
});
return logger;
}
// -------------------
login.readOptions = function (argv) {
var cli = require('../util/cli');
var options = cli.readOptions({
token: { type: String, shorthand: 't' },
}, argv);
delete options.argv;
return [options];
};
module.exports = login;

View File

@@ -0,0 +1,95 @@
var chalk = require('chalk');
var Q = require('q');
var defaultConfig = require('../config');
var PackageRepository = require('../core/PackageRepository');
var Tracker = require('../util/analytics').Tracker;
var createError = require('../util/createError');
function unregister(logger, name, config) {
if (!name) {
return;
}
var repository;
var registryClient;
var tracker;
var force;
config = defaultConfig(config);
force = config.force;
tracker = new Tracker(config);
// Bypass any cache
config.offline = false;
config.force = true;
// Trim name
name = name.trim();
repository = new PackageRepository(config, logger);
process.nextTick(function () {
tracker.track('unregister');
if (!config.accessToken) {
return logger.emit('error',
createError('Use "bower login" with collaborator credentials', 'EFORBIDDEN')
);
}
Q.resolve()
.then(function () {
// If non interactive or user forced, bypass confirmation
if (!config.interactive || force) {
return true;
}
// Confirm if the user really wants to unregister
logger.warn('confirm unregister', 'You are about to remove component "' + chalk.cyan.underline(name) + '" from the bower registry (' + chalk.cyan.underline(config.registry.register) + '). It is generally considered bad behavior to remove versions of a library that others are depending on.');
return Q.nfcall(logger.prompt.bind(logger), {
type: 'confirm',
message: 'Are you really sure?',
default: false
});
})
.then(function (result) {
// If user response was negative, abort
if (!result) {
return;
}
// Register
registryClient = repository.getRegistryClient();
logger.action('unregister', name, {
name: name
});
return Q.nfcall(registryClient.unregister.bind(registryClient), name);
})
.done(function (result) {
tracker.track('unregistered');
logger.info('Package unregistered', name);
logger.emit('end', result);
}, function (error) {
logger.emit('error', error);
});
});
return logger;
}
// -------------------
unregister.readOptions = function (argv) {
var cli = require('../util/cli');
var options = cli.readOptions(argv);
var name = options.argv.remain[1];
return [name];
};
module.exports = unregister;

View File

@@ -1,6 +1,7 @@
var tty = require('tty');
var object = require('mout').object;
var bowerConfig = require('bower-config');
var Configstore = require('configstore');
var cachedConfigs = {};
@@ -18,6 +19,9 @@ function readCachedConfig(cwd) {
}
var config = cachedConfigs[cwd] = bowerConfig.read(cwd);
var configstore = new Configstore('bower-github').all;
object.mixIn(config, configstore);
// Delete the json attribute because it is no longer supported
// and conflicts with --json

View File

@@ -26,9 +26,11 @@
"cardinal": "0.4.4",
"chalk": "^1.0.0",
"chmodr": "0.1.0",
"configstore": "^0.3.2",
"decompress-zip": "^0.1.0",
"fstream": "^1.0.3",
"fstream-ignore": "^1.0.2",
"github": "^0.2.3",
"glob": "^4.3.2",
"graceful-fs": "^3.0.5",
"handlebars": "^2.0.0",

View File

@@ -0,0 +1,19 @@
{
"command": "login",
"description": "Authenticate with GitHub and store credentials to be used later.",
"usage": [
"login [<options>]"
],
"options": [
{
"shorthand": "-h",
"flag": "--help",
"description": "Show this help message"
},
{
"shorthand": "-t",
"flag": "--token",
"description": "Pass an existing GitHub auth token rather than prompting for username and password."
}
]
}

View File

@@ -0,0 +1,14 @@
{
"command": "unregister",
"description": "Unregisters a package.",
"usage": [
"unregister <name> [<options>]"
],
"options": [
{
"shorthand": "-h",
"flag": "--help",
"description": "Show this help message"
}
]
}

View File

@@ -11,12 +11,14 @@
"install": "Install a package locally",
"link": "Symlink a package folder",
"list": "List local packages - and possible updates",
"login": "Authenticate with GitHub and store credentials",
"lookup": "Look up a package URL by name",
"prune": "Removes local extraneous packages",
"register": "Register a package",
"search": "Search for a package by name",
"update": "Update a local package",
"uninstall": "Remove a local package",
"unregister": "Remove a package from the registry",
"version": "Bump a package version"
},
"options": [

View File

@@ -70,6 +70,8 @@ describe('GitHub', function () {
});
it('should retry using the GitRemoteResolver mechanism if download failed', function (next) {
this.timeout(20000);
var resolver;
var retried;
@@ -100,6 +102,8 @@ describe('GitHub', function () {
});
it('should retry using the GitRemoteResolver mechanism if extraction failed', function (next) {
this.timeout(20000);
var resolver;
var retried;