Compare commits

..

4 Commits

Author SHA1 Message Date
Adam Stankiewicz
ce9cd624d9 "commit" 2014-09-08 02:36:28 +02:00
Adam Stankiewicz
55954ee369 "commit" 2014-09-08 02:36:28 +02:00
Adam Stankiewicz
51ca095c44 "commit" 2014-09-08 02:36:16 +02:00
Adam Stankiewicz
b83840c10f "commit" 2014-09-08 02:35:50 +02:00
80 changed files with 458 additions and 3329 deletions

View File

@@ -1,25 +1,9 @@
env:
- NODE_VERSION=0.10
- NODE_VERSION=0.11
install:
- test $TRAVIS_OS_NAME = "osx" && brew install nvm && source $(brew --prefix nvm)/nvm.sh || test $TRAVIS_OS_NAME = "linux"
- nvm install $NODE_VERSION
- node --version
- npm --version
- git --version
- svn --version | head -n 1
- npm install -g grunt-cli
- npm install
os:
- osx
- linux
language: node_js
node_js:
- '0.10'
- '0.11'
matrix:
allow_failures:
- os: osx
- env: "NODE_VERSION=0.11"
- node_js: '0.11'
script:
- grunt travis

View File

@@ -1,31 +1,5 @@
# Changelog
## 1.3.12 - 2014-09-28
- [stability] Fix versions for unstable dependencies ([#1532](https://github.com/bower/bower/pull/1532))
- [fix] Update tar-fs to support old tar format ([#1537](https://github.com/bower/bower/issues/1537))
- [fix] Make analytics work again ([#1529](https://github.com/bower/bower/pull/1529))
- [fix] Always disable analytics for non-interactive mode ([#1529](https://github.com/bower/bower/pull/1529))
- [fix] Bower init can create private packages again ([#1522](https://github.com/bower/bower/issues/1522))
- [fix] Show again missing newline for bower search output ([#1538](https://github.com/bower/bower/issues/1538))
## 1.3.11 - 2014-09-17
- [fix] Restore install missing dependencies on update ([1519](https://github.com/bower/bower/pull/1519))
## 1.3.10 - 2014-09-13
- [fix] Back down concurrency from 50 to 5 ([#1483](https://github.com/bower/bower/pull/1483))
- [fix] Read .bowerrc from specified cwd ([#1301](https://github.com/bower/bower/pull/1301))
- [fix] Disable shallow clones except those from GitHub ([#1393](https://github.com/bower/bower/pull/1393))
- [fix] Expose bower version ([#1478](https://github.com/bower/bower/pull/1478))
- [fix] Bump dependencies, including "request" ([#1467](https://github.com/bower/bower/pull/1467))
- [fix] Prevent an error when piping bower output to head ([#1508](https://github.com/bower/bower/pull/1508))
- [fix] Disable removing unnecessary resolutions ([#1061](https://github.com/bower/bower/pull/1061))
- [fix] Display the output of hooks again ([#1484](https://github.com/bower/bower/issues/1484))
- [fix] analytics: true in .bowerrc prevents user prompt ([#1470](https://github.com/bower/bower/pull/1470))
- [perf] Use `tar-fs` instead of `tar` for faster TAR extraction ([#1490](https://github.com/bower/bower/pull/1490))
## 1.3.9 - 2014-08-06
- [fix] Handle `tmp` sometimes returning an array ([#1434](https://github.com/bower/bower/pull/1434))

View File

@@ -20,7 +20,7 @@ module.exports = function (grunt) {
simplemocha: {
options: {
reporter: 'spec',
timeout: '10000'
timeout: '5000'
},
full: {
src: ['test/test.js']
@@ -40,7 +40,7 @@ module.exports = function (grunt) {
command: 'node test/packages.js --force && node test/packages-svn.js --force'
},
cover: {
command: 'STRICT_REQUIRE=1 node node_modules/istanbul/lib/cli.js cover --dir ./test/reports node_modules/mocha/bin/_mocha -- --timeout 30000 -R dot test/test.js'
command: 'STRICT_REQUIRE=1 node node_modules/istanbul/lib/cli.js cover --dir ./test/reports node_modules/mocha/bin/_mocha -- -R dot test/test.js'
},
coveralls: {
command: 'node node_modules/.bin/coveralls < test/reports/lcov.info'

View File

@@ -1,4 +1,4 @@
Copyright (c) 2015 Twitter and other contributors
Copyright (c) 2014 Twitter and other contributors
Permission is hereby granted, free of charge, to any person obtaining a copy of
this software and associated documentation files (the "Software"), to deal in

View File

@@ -1,3 +0,0 @@
This is stub for feature mentioned in #505.
You can send PR against this branch (feature/shrinkwrap).

View File

@@ -1,6 +1,6 @@
# Bower
[![Build Status](https://travis-ci.org/bower/bower.svg?branch=master)](https://travis-ci.org/bower/bower) [![Windows Build](https://ci.appveyor.com/api/projects/status/jr6vfra8w84plh2g/branch/master?svg=true)](https://ci.appveyor.com/project/sheerun/bower/history) [![Coverage Status](https://img.shields.io/coveralls/bower/bower.svg)](https://coveralls.io/r/bower/bower?branch=master)
[![Build Status](https://travis-ci.org/bower/bower.svg?branch=master)](https://travis-ci.org/bower/bower) [![Coverage Status](https://coveralls.io/repos/bower/bower/badge.png?branch=feature%2Fintegration)](https://coveralls.io/r/bower/bower?branch=feature%2Fintegration)
<img align="right" height="300" src="http://bower.io/img/bower-logo.png">
@@ -114,12 +114,6 @@ review the [guidelines for contributing](CONTRIBUTING.md).
* [Pull requests](CONTRIBUTING.md#pull-requests)
Note that on Windows for tests to pass you need to configure Git before cloning:
```
git config --global core.autocrlf input
```
## Bower Team
Bower is made by lots of people across the globe, contributions large and small. Our thanks to everyone who has played a part.
@@ -130,6 +124,7 @@ Bower is made by lots of people across the globe, contributions large and small.
* [@wibblymat](https://github.com/wibblymat)
* [@paulirish](https://github.com/paulirish)
* [@benschwarz](https://github.com/benschwarz)
* [@sindresorhus](https://github.com/sindresorhus)
* [@svnlto](https://github.com/svnlto)
* [@sheerun](https://github.com/sheerun)
@@ -141,6 +136,6 @@ Bower is made by lots of people across the globe, contributions large and small.
## License
Copyright (c) 2015 Twitter and other contributors
Copyright (c) 2014 Twitter and other contributors
Licensed under the MIT License

View File

@@ -1,40 +0,0 @@
# Thanks for Grunt for template of this file!
# http://www.appveyor.com/docs/appveyor-yml
# Fix line endings in Windows. (runs before repo cloning)
init:
- git config --global core.autocrlf input
# Test against these versions of Node.js.
environment:
matrix:
- nodejs_version: "0.10"
# - nodejs_version: "0.11"
# Allow failing jobs for bleeding-edge Node.js versions.
matrix:
allow_failures:
- nodejs_version: "0.11"
# Install scripts. (runs after repo cloning)
install:
# Get the latest stable version of Node 0.STABLE.latest
- ps: Install-Product node $env:nodejs_version
# Install subversion
- choco install svn
# Install bower
- npm install
# Post-install test scripts.
test_script:
# Output useful info for debugging.
- node --version
- npm --version
- cmd: npm test
# Don't actually build.
build: off
# Set build version format here instead of in the admin panel.
version: "{build}"

View File

@@ -6,7 +6,7 @@ process.bin = process.title = 'bower';
var Q = require('q');
var mout = require('mout');
var Logger = require('bower-logger');
var userHome = require('user-home');
var osenv = require('osenv');
var bower = require('../lib');
var pkg = require('../package.json');
var cli = require('../lib/util/cli');
@@ -125,15 +125,18 @@ analytics.setup(bower.config).then(function () {
});
// Warn if HOME is not SET
if (!userHome) {
logger.warn('no-home', 'HOME environment variable not set. User config will not be loaded.');
if (!osenv.home()) {
logger.warn('no-home', 'HOME not set, user configuration will not be loaded');
}
if (bower.config.interactive) {
var updateNotifier = require('update-notifier');
// Check for newer version of Bower
var notifier = updateNotifier({pkg: pkg});
var notifier = updateNotifier({
packageName: pkg.name,
packageVersion: pkg.version
});
if (notifier.update && levels.info >= loglevel) {
notifier.notify();

View File

@@ -6,6 +6,7 @@ var rimraf = require('rimraf');
var endpointParser = require('bower-endpoint-parser');
var PackageRepository = require('../../core/PackageRepository');
var semver = require('../../util/semver');
var cli = require('../../util/cli');
var defaultConfig = require('../../config');
function clean(logger, endpoints, options, config) {
@@ -32,7 +33,8 @@ function clean(logger, endpoints, options, config) {
return Q.all([
clearPackages(decEndpoints, config, logger),
clearLinks(names, config, logger)
clearLinks(names, config, logger),
!names ? clearCompletion(config, logger) : null
])
.spread(function (entries) {
return entries;
@@ -170,16 +172,34 @@ function clearLinks(names, config, logger) {
});
}
function clearCompletion(config, logger) {
var dir = config.storage.completion;
return Q.nfcall(fs.stat, dir)
.then(function () {
return Q.nfcall(rimraf, dir)
.then(function () {
logger.info('deleted', 'Completion cache', {
file: dir
});
});
}, function (error) {
if (error.code !== 'ENOENT') {
throw error;
}
});
}
// -------------------
clean.readOptions = function (argv) {
var cli = require('../../util/cli');
clean.line = function (logger, argv) {
var options = cli.readOptions(argv);
var endpoints = options.argv.remain.slice(2);
return clean(logger, endpoints, options);
};
delete options.argv;
return [endpoints, options];
clean.completion = function () {
// TODO:
};
module.exports = clean;

View File

@@ -1,5 +1,6 @@
var mout = require('mout');
var PackageRepository = require('../../core/PackageRepository');
var cli = require('../../util/cli');
var defaultConfig = require('../../config');
function list(logger, packages, options, config) {
@@ -30,14 +31,14 @@ function list(logger, packages, options, config) {
// -------------------
list.readOptions = function (argv) {
var cli = require('../../util/cli');
list.line = function (logger, argv) {
var options = cli.readOptions(argv);
var packages = options.argv.remain.slice(2);
return list(logger, packages, options);
};
delete options.argv;
return [packages, options];
list.completion = function () {
// TODO:
};
module.exports = list;

View File

@@ -0,0 +1,21 @@
var Q = require('q');
var cli = require('../util/cli');
function completion(config) {
return new Q();
}
// -------------------
completion.line = function (logger, argv) {
var options = cli.readOptions(argv);
var name = options.argv.remain[1];
return completion(logger, name);
};
completion.completion = function () {
// TODO:
};
module.exports = completion;

View File

@@ -1,9 +1,10 @@
var Q = require('q');
var path = require('path');
var fs = require('graceful-fs');
var cli = require('../util/cli');
var createError = require('../util/createError');
function help(logger, name, config) {
function help(logger, name) {
var json;
if (name) {
@@ -17,7 +18,7 @@ function help(logger, name, config) {
})
.then(function (exists) {
if (!exists) {
throw createError('Unknown command: ' + name, 'EUNKNOWNCMD', {
throw createError('Unknown command: ' + name, 'EUNKOWNCMD', {
command: name
});
}
@@ -28,12 +29,14 @@ function help(logger, name, config) {
// -------------------
help.readOptions = function (argv) {
var cli = require('../util/cli');
help.line = function (logger, argv) {
var options = cli.readOptions(argv);
var name = options.argv.remain.slice(1).join(' ');
return help(logger, name);
};
return [name];
help.completion = function () {
// TODO
};
module.exports = help;

View File

@@ -1,6 +1,7 @@
var Project = require('../core/Project');
var open = require('opn');
var endpointParser = require('bower-endpoint-parser');
var cli = require('../util/cli');
var createError = require('../util/createError');
var defaultConfig = require('../config');
@@ -47,12 +48,15 @@ function home(logger, name, config) {
// -------------------
home.readOptions = function (argv) {
var cli = require('../util/cli');
home.line = function (logger, argv) {
var options = cli.readOptions(argv);
var name = options.argv.remain[1];
return [name];
return home(logger, name);
};
home.completion = function () {
// TODO:
};
module.exports = home;

View File

@@ -24,12 +24,7 @@ function commandFactory(id) {
function runFromArgv(argv) {
return withLogger(function (logger) {
var command = require(id);
var commandArgs = command.readOptions(argv);
commandArgs.unshift(logger);
return command.apply(undefined, commandArgs);
return require(id).line.call(undefined, logger, argv);
});
}
@@ -49,7 +44,6 @@ function commandFactory(id) {
}
command.line = runFromArgv;
return command;
}
@@ -59,6 +53,7 @@ module.exports = {
clean: commandFactory('./cache/clean'),
list: commandFactory('./cache/list'),
},
completion: commandFactory('./completion'),
help: commandFactory('./help'),
home: commandFactory('./home'),
info: commandFactory('./info'),

View File

@@ -2,14 +2,11 @@ var mout = require('mout');
var Q = require('q');
var endpointParser = require('bower-endpoint-parser');
var PackageRepository = require('../core/PackageRepository');
var cli = require('../util/cli');
var Tracker = require('../util/analytics').Tracker;
var defaultConfig = require('../config');
function info(logger, endpoint, property, config) {
if (!endpoint) {
return;
}
var repository;
var decEndpoint;
var tracker;
@@ -56,13 +53,20 @@ function getPkgMeta(repository, decEndpoint, property) {
// -------------------
info.readOptions = function (argv) {
var cli = require('../util/cli');
info.line = function (logger, argv) {
var options = cli.readOptions(argv);
var pkg = options.argv.remain[1];
var property = options.argv.remain[2];
return [pkg, property];
if (!pkg) {
return new Q();
}
return info(logger, pkg, property);
};
info.completion = function () {
// TODO:
};
module.exports = info;

View File

@@ -7,6 +7,7 @@ var Project = require('../core/Project');
var defaultConfig = require('../config');
var GitHubResolver = require('../core/resolvers/GitHubResolver');
var GitFsResolver = require('../core/resolvers/GitFsResolver');
var cli = require('../util/cli');
var cmd = require('../util/cmd');
var createError = require('../util/createError');
@@ -17,9 +18,12 @@ function init(logger, config) {
// This command requires interactive to be enabled
if (!config.interactive) {
throw createError('Register requires an interactive shell', 'ENOINT', {
details: 'Note that you can manually force an interactive shell with --config.interactive'
process.nextTick(function () {
logger.emit('error', createError('Register requires an interactive shell', 'ENOINT', {
details: 'Note that you can manually force an interactive shell with --config.interactive'
}));
});
return logger;
}
project = new Project(config, logger);
@@ -316,8 +320,13 @@ function setDependencies(project, json, answers) {
// -------------------
init.readOptions = function (argv) {
return [];
init.line = function (logger, argv) {
var options = cli.readOptions(argv);
return init(logger, options);
};
init.completion = function () {
// TODO:
};
module.exports = init;

View File

@@ -1,5 +1,6 @@
var endpointParser = require('bower-endpoint-parser');
var Project = require('../core/Project');
var cli = require('../util/cli');
var Tracker = require('../util/analytics').Tracker;
var defaultConfig = require('../config');
@@ -28,22 +29,22 @@ function install(logger, endpoints, options, config) {
// -------------------
install.readOptions = function (argv) {
var cli = require('../util/cli');
install.line = function (logger, argv) {
var options = install.options(argv);
return install(logger, options.argv.remain.slice(1), options);
};
var options = cli.readOptions({
install.options = function (argv) {
return cli.readOptions({
'force-latest': { type: Boolean, shorthand: 'F'},
'production': { type: Boolean, shorthand: 'p' },
'save': { type: Boolean, shorthand: 'S' },
'save-dev': { type: Boolean, shorthand: 'D' },
'save-exact': { type: Boolean, shorthand: 'E' }
'save-dev': { type: Boolean, shorthand: 'D' }
}, argv);
};
var packages = options.argv.remain.slice(1);
delete options.argv;
return [packages, options];
install.completion = function () {
// TODO:
};
module.exports = install;

View File

@@ -3,13 +3,14 @@ var rimraf = require('rimraf');
var Q = require('q');
var Project = require('../core/Project');
var createLink = require('../util/createLink');
var cli = require('../util/cli');
var defaultConfig = require('../config');
function link(logger, name, localName, config) {
function link(logger, name, localName) {
if (name) {
return linkTo(logger, name, localName, config);
return linkTo(logger, name, localName);
} else {
return linkSelf(logger, config);
return linkSelf(logger);
}
}
@@ -49,7 +50,7 @@ function linkTo(logger, name, localName, config) {
localName = localName || name;
src = path.join(config.storage.links, name);
dst = path.join(config.cwd, config.directory, localName);
dst = path.join(process.cwd(), config.directory, localName);
// Delete destination folder if any
return Q.nfcall(rimraf, dst)
@@ -72,13 +73,15 @@ function linkTo(logger, name, localName, config) {
// -------------------
link.readOptions = function (argv) {
var cli = require('../util/cli');
link.line = function (logger, argv) {
var options = cli.readOptions(argv);
var name = options.argv.remain[1];
var localName = options.argv.remain[2];
return link(logger, name, localName);
};
return [name, localName];
link.completion = function () {
// TODO:
};
module.exports = link;

View File

@@ -3,6 +3,7 @@ var mout = require('mout');
var Q = require('q');
var Project = require('../core/Project');
var semver = require('../util/semver');
var cli = require('../util/cli');
var defaultConfig = require('../config');
function list(logger, options, config) {
@@ -150,17 +151,20 @@ function normalize(src) {
// -------------------
list.readOptions = function (argv) {
var cli = require('../util/cli');
list.line = function (logger, argv) {
var options = list.options(argv);
return list(logger, options);
};
var options = cli.readOptions({
list.options = function (argv) {
return cli.readOptions({
'paths': { type: Boolean, shorthand: 'p' },
'relative': { type: Boolean, shorthand: 'r' }
}, argv);
};
delete options.argv;
return [options];
list.completion = function () {
// TODO:
};
module.exports = list;

View File

@@ -1,12 +1,9 @@
var Q = require('q');
var RegistryClient = require('bower-registry-client');
var cli = require('../util/cli');
var defaultConfig = require('../config');
function lookup(logger, name, config) {
if (!name) {
return new Q(null);
}
var registryClient;
config = defaultConfig(config);
@@ -27,12 +24,19 @@ function lookup(logger, name, config) {
// -------------------
lookup.readOptions = function (argv) {
var cli = require('../util/cli');
var options = cli.readOptions(argv);
lookup.line = function (logger, argv) {
var options = cli.readOptions(argv);
var name = options.argv.remain[1];
return [name];
if (!name) {
return new Q();
} else {
return lookup(logger, name);
}
};
lookup.completion = function () {
// TODO:
};
module.exports = lookup;

View File

@@ -1,5 +1,6 @@
var mout = require('mout');
var Project = require('../core/Project');
var cli = require('../util/cli');
var defaultConfig = require('../config');
function prune(logger, options, config) {
@@ -40,16 +41,19 @@ function clean(project, options, removed) {
// -------------------
prune.readOptions = function (argv) {
var cli = require('../util/cli');
prune.line = function (logger, argv) {
var options = prune.options(argv);
return prune(logger, options);
};
var options = cli.readOptions({
prune.options = function (argv) {
return cli.readOptions({
'production': { type: Boolean, shorthand: 'p' },
}, argv);
};
delete options.argv;
return [options];
prune.completion = function () {
// TODO:
};
module.exports = prune;

View File

@@ -4,6 +4,7 @@ var chalk = require('chalk');
var PackageRepository = require('../core/PackageRepository');
var Config = require('bower-config');
var Tracker = require('../util/analytics').Tracker;
var cli = require('../util/cli');
var createError = require('../util/createError');
var defaultConfig = require('../config');
var GitHubResolver = require('../core/resolvers/GitHubResolver');
@@ -18,17 +19,18 @@ function register(logger, name, url, config) {
force = config.force;
tracker = new Tracker(config);
name = (name || '').trim();
url = (url || '').trim();
// Bypass any cache
config.offline = false;
config.force = true;
// Trim name
name = name.trim();
return Q.try(function () {
// Verify name and url
if (!name || !url) {
throw createError('Usage: bower register <name> <url>', 'EINVFORMAT');
// Verify name
// TODO: Verify with the new spec regexp?
if (!name) {
throw createError('Please type a name', 'EINVNAME');
}
// The public registry only allows git:// endpoints
@@ -102,14 +104,20 @@ function convertUrl(url, logger) {
// -------------------
register.readOptions = function (argv) {
var cli = require('../util/cli');
register.line = function (logger, argv) {
var options = cli.readOptions(argv);
var name = options.argv.remain[1];
var url = options.argv.remain[2];
return [name, url];
if (!name || !url) {
return new Q();
} else {
return register(logger, name, url);
}
};
register.completion = function () {
// TODO:
};
module.exports = register;

View File

@@ -1,5 +1,6 @@
var Q = require('q');
var RegistryClient = require('bower-registry-client');
var cli = require('../util/cli');
var Tracker = require('../util/analytics').Tracker;
var defaultConfig = require('../config');
@@ -25,12 +26,14 @@ function search(logger, name, config) {
// -------------------
search.readOptions = function (argv) {
var cli = require('../util/cli');
search.line = function (logger, argv) {
var options = cli.readOptions(argv);
var name = options.argv.remain.slice(1).join(' ');
return search(logger, name, options);
};
return [name];
search.completion = function () {
// TODO:
};
module.exports = search;

View File

@@ -1,14 +1,11 @@
var mout = require('mout');
var Q = require('q');
var Project = require('../core/Project');
var cli = require('../util/cli');
var Tracker = require('../util/analytics').Tracker;
var defaultConfig = require('../config');
function uninstall(logger, names, options, config) {
if (!names.length) {
return new Q();
}
var project;
var tracker;
@@ -102,19 +99,26 @@ function clean(project, names, removed) {
// -------------------
uninstall.readOptions = function (argv) {
var cli = require('../util/cli');
uninstall.line = function (logger, argv) {
var options = uninstall.options(argv);
var names = options.argv.remain.slice(1);
var options = cli.readOptions({
if (!names.length) {
return new Q();
} else {
return uninstall(logger, names, options);
}
};
uninstall.options = function (argv) {
return cli.readOptions({
'save': { type: Boolean, shorthand: 'S' },
'save-dev': { type: Boolean, shorthand: 'D' }
}, argv);
};
var names = options.argv.remain.slice(1);
delete options.argv;
return [names, options];
uninstall.completion = function () {
// TODO:
};
module.exports = uninstall;

View File

@@ -1,4 +1,5 @@
var Project = require('../core/Project');
var cli = require('../util/cli');
var defaultConfig = require('../config');
function update(logger, names, options, config) {
@@ -18,19 +19,21 @@ function update(logger, names, options, config) {
// -------------------
update.readOptions = function (argv) {
var cli = require('../util/cli');
update.line = function (logger, argv) {
var options = update.options(argv);
var names = options.argv.remain.slice(1);
return update(logger, names, options);
};
var options = cli.readOptions({
update.options = function (argv) {
return cli.readOptions({
'force-latest': { type: Boolean, shorthand: 'F' },
'production': { type: Boolean, shorthand: 'p' }
}, argv);
};
var names = options.argv.remain.slice(1);
delete options.argv;
return [names, options];
update.completion = function () {
// TODO:
};
module.exports = update;

View File

@@ -5,13 +5,13 @@ var path = require('path');
var Q = require('q');
var execFile = require('child_process').execFile;
var Project = require('../core/Project');
var cli = require('../util/cli');
var defaultConfig = require('../config');
var createError = require('../util/createError');
function version(logger, versionArg, options, config) {
var project;
options = options || {};
config = defaultConfig(config);
project = new Project(config, logger);
@@ -19,11 +19,10 @@ function version(logger, versionArg, options, config) {
}
function bump(project, versionArg, message) {
var cwd = project._config.cwd || process.cwd();
var newVersion;
var doGitCommit = false;
return checkGit(cwd)
return checkGit()
.then(function (hasGit) {
doGitCommit = hasGit;
})
@@ -35,7 +34,7 @@ function bump(project, versionArg, message) {
.then(project.saveJson.bind(project))
.then(function () {
if (doGitCommit) {
return gitCommitAndTag(cwd, newVersion, message);
return gitCommitAndTag(newVersion, message);
}
})
.then(function () {
@@ -57,12 +56,12 @@ function getNewVersion(currentVersion, versionArg) {
return newVersion;
}
function checkGit(cwd) {
var gitDir = path.join(cwd, '.git');
function checkGit() {
var gitDir = path.join(process.cwd(), '.git');
return Q.nfcall(fs.stat, gitDir)
.then(function (stat) {
if (stat.isDirectory()) {
return checkGitStatus(cwd);
return checkGitStatus();
}
return false;
}, function () {
@@ -71,14 +70,14 @@ function checkGit(cwd) {
});
}
function checkGitStatus(cwd) {
function checkGitStatus() {
return Q.nfcall(which, 'git')
.fail(function (err) {
err.code = 'ENOGIT';
throw err;
})
.then(function () {
return Q.nfcall(execFile, 'git', ['status', '--porcelain'], {env: process.env, cwd: cwd});
return Q.nfcall(execFile, 'git', ['status', '--porcelain'], {env: process.env});
})
.then(function (value) {
var stdout = value[0];
@@ -99,29 +98,34 @@ function filterModifiedStatusLines(stdout) {
});
}
function gitCommitAndTag(cwd, newVersion, message) {
function gitCommitAndTag(newVersion, message) {
var tag = 'v' + newVersion;
message = message || tag;
message = message.replace(/%s/g, newVersion);
return Q.nfcall(execFile, 'git', ['add', 'bower.json'], {env: process.env, cwd: cwd})
return Q.nfcall(execFile, 'git', ['add', 'bower.json'], {env: process.env})
.then(function () {
return Q.nfcall(execFile, 'git', ['commit', '-m', message], {env: process.env, cwd: cwd});
return Q.nfcall(execFile, 'git', ['commit', '-m', message], {env: process.env});
})
.then(function () {
return Q.nfcall(execFile, 'git', ['tag', tag, '-am', message], {env: process.env, cwd: cwd});
return Q.nfcall(execFile, 'git', ['tag', tag, '-am', message], {env: process.env});
});
}
// -------------------
version.readOptions = function (argv) {
var cli = require('../util/cli');
version.line = function (logger, argv) {
var options = version.options(argv);
return version(logger, options.argv.remain[1], options);
};
var options = cli.readOptions({
version.options = function (argv) {
return cli.readOptions({
'message': { type: String, shorthand: 'm'}
}, argv);
};
return [options.argv.remain[1], options];
version.completion = function () {
// TODO:
};
module.exports = version;

View File

@@ -1,6 +1,7 @@
var tty = require('tty');
var object = require('mout').object;
var bowerConfig = require('bower-config');
var cli = require('./util/cli');
var cachedConfigs = {};
@@ -32,21 +33,24 @@ function readCachedConfig(cwd) {
);
}
// Merge common CLI options into the config
if (process.bin === 'bower') {
var cli = require('./util/cli');
object.mixIn(config, cli.readOptions({
force: { type: Boolean, shorthand: 'f' },
offline: { type: Boolean, shorthand: 'o' },
verbose: { type: Boolean, shorthand: 'V' },
quiet: { type: Boolean, shorthand: 'q' },
loglevel: { type: String, shorthand: 'l' },
json: { type: Boolean, shorthand: 'j' },
silent: { type: Boolean, shorthand: 's' }
}));
// If `analytics` hasn't been explicitly set, we disable
// it when ran programatically.
if (config.analytics == null) {
// Don't enable analytics on CI server unless explicitly configured.
config.analytics = config.interactive;
}
// Merge common CLI options into the config
object.mixIn(config, cli.readOptions({
force: { type: Boolean, shorthand: 'f' },
offline: { type: Boolean, shorthand: 'o' },
verbose: { type: Boolean, shorthand: 'V' },
quiet: { type: Boolean, shorthand: 'q' },
loglevel: { type: String, shorthand: 'l' },
json: { type: Boolean, shorthand: 'j' },
silent: { type: Boolean, shorthand: 's' }
}));
return config;
}

View File

@@ -775,7 +775,7 @@ Manager.prototype._electSuitable = function (name, semvers, nonSemvers) {
choices = picks.map(function (pick, index) { return index + 1; });
return Q.nfcall(this._logger.prompt.bind(this._logger), {
type: 'input',
message: 'Answer',
message: 'Answer:',
validate: function (choice) {
choice = Number(mout.string.trim(choice.trim(), '!'));
@@ -827,7 +827,7 @@ Manager.prototype._storeResolution = function (pick) {
*
* It is used in two situations:
* * checks if resolved component matches dependency constraint
* * checks if not resolved component matches already fetched component
* * checks if not resolved component matches alredy fetched component
*
* If candidate matches already resolved component, it won't be downloaded.
*

View File

@@ -93,10 +93,6 @@ Project.prototype.install = function (decEndpoints, options, config) {
jsonEndpoint = endpointParser.decomposed2json(decEndpoint);
if (that._options.saveExact) {
jsonEndpoint[decEndpoint.name] = decEndpoint.pkgMeta.version;
}
if (that._options.save) {
that._json.dependencies = mout.object.mixIn(that._json.dependencies || {}, jsonEndpoint);
}
@@ -196,9 +192,6 @@ Project.prototype.update = function (names, options) {
.then(function () {
return that._manager.preinstall(that._json);
})
.then(function () {
return that._manager.install(that._json);
})
.then(function (installed) {
// Save JSON, might contain changes to resolutions
return that.saveJson()

View File

@@ -3,7 +3,6 @@ var Q = require('q');
var which = require('which');
var LRU = require('lru-cache');
var mout = require('mout');
var path = require('path');
var Resolver = require('./Resolver');
var semver = require('../../util/semver');
var createError = require('../../util/createError');
@@ -87,13 +86,13 @@ SvnResolver.prototype._export = function () {
});
if (resolution.type === 'commit') {
promise = cmd('svn', ['export', '--force', this._source + path.normalize('/trunk'), '-r' + resolution.commit, this._tempDir]);
promise = cmd('svn', ['export', '--force', this._source + '/trunk', '-r' + resolution.commit, this._tempDir]);
} else if (resolution.type === 'branch' && resolution.branch === 'trunk') {
promise = cmd('svn', ['export', '--force', this._source + path.normalize('/trunk'), this._tempDir]);
promise = cmd('svn', ['export', '--force', this._source + '/trunk', this._tempDir]);
} else if (resolution.type === 'branch') {
promise = cmd('svn', ['export', '--force', this._source + path.normalize('/branches/' + resolution.branch), this._tempDir]);
promise = cmd('svn', ['export', '--force', this._source + '/branches/' + resolution.branch, this._tempDir]);
} else {
promise = cmd('svn', ['export', '--force', this._source + path.normalize('/tags/' + resolution.tag), this._tempDir]);
promise = cmd('svn', ['export', '--force', this._source + '/tags/' + resolution.tag, this._tempDir]);
}
// Throttle the progress reporter to 1 time each sec
@@ -325,7 +324,7 @@ SvnResolver.tags = function (source) {
return Q.resolve(value);
}
value = cmd('svn', ['list', source + path.normalize('/tags'), '--verbose'])
value = cmd('svn', ['list', source + '/tags', '--verbose'])
.spread(function (stout) {
var tags = SvnResolver.parseSubversionListOutput(stout.toString());

View File

@@ -23,7 +23,7 @@ function StandardRenderer(command, config) {
};
this._command = command;
this._config = config || {};
this._config = config;
if (this.constructor._wideCommands.indexOf(command) === -1) {
this._compact = true;
@@ -79,7 +79,7 @@ StandardRenderer.prototype.error = function (err) {
/*jshint camelcase:true*/
this._write(process.stderr, str);
this._write(process.stderr, new Error().stack);
console.trace();
// Print bower version, node version and system info.
this._write(process.stderr, chalk.yellow('\nSystem info:\n'));

View File

@@ -2,94 +2,47 @@ var Q = require('q');
var mout = require('mout');
var analytics = module.exports;
var insight;
var enableAnalytics = false;
// Insight takes long to load, and often causes problems
// in non-interactive environment, so we load it lazily
//
// Insight is used in two cases:
//
// 1. Read insight configuration (whether track user actions)
// 2. Track user actions (Tracker.track method)
//
// We don't want to instantiate Insight in non-interactive mode
// because it takes time to read config and configstore has concurrency issues:
//
// https://github.com/yeoman/configstore/issues/20
function ensureInsight () {
if (!insight) {
var Insight = require('insight');
insight = new Insight({
trackingCode: 'UA-43531210-1',
pkg: require('../../package.json')
});
}
}
// Initializes the application-wide insight singleton and asks for the
// permission on the CLI during the first run.
//
// This method is called only from bin/bower. Programmatic API skips it.
analytics.setup = function setup (config) {
analytics.setup = function setup(config) {
var deferred = Q.defer();
// No need for asking if analytics is set in bower config
if (config.analytics === undefined) {
ensureInsight();
// Display the ask prompt only if it hasn't been answered before
// and the current session is looking to configure the analytics.
if (config.analytics) {
var Insight = require('insight');
var pkg = require('../../package.json');
// For non-interactive call from bin/bower we disable analytics
if (config.interactive) {
if (insight.optOut !== undefined) {
deferred.resolve(!insight.optOut);
} else {
insight.askPermission(null, function(err, optIn) {
// optIn callback param was exactly opposite before 0.4.3
// so we force at least insight@0.4.3 in package.json
deferred.resolve(optIn);
});
}
insight = new Insight({
trackingCode: 'UA-43531210-1',
packageName: pkg.name,
packageVersion: pkg.version
});
if (insight.optOut === undefined) {
insight.askPermission(null, deferred.resolve);
} else {
// no specified value, no stored value, and can't prompt for one
// most likely CI environment; defaults to false to reduce data noise
deferred.resolve(false);
deferred.resolve();
}
} else {
// use the specified value
deferred.resolve(config.analytics);
deferred.resolve();
}
return deferred.promise.then(function (enabled) {
enableAnalytics = enabled;
return enabled;
});
return deferred.promise;
};
var Tracker = analytics.Tracker = function Tracker(config) {
function analyticsEnabled () {
// Allow for overriding analytics default
if (config && config.analytics !== undefined) {
return config.analytics;
}
// TODO: let bower pass this variable from bin/bower instead closure
return enableAnalytics;
}
if (analyticsEnabled()) {
ensureInsight();
} else {
this.track = function noop () {};
this.trackDecomposedEndpoints = function noop () {};
this.trackPackages = function noop () {};
this.trackNames = function noop () {};
if (!config.analytics) {
this.track = function noop() {};
}
};
Tracker.prototype.track = function track() {
if (!insight) {
throw new Error('You must call analytics.setup() prior to tracking.');
}
insight.track.apply(insight, arguments);
};

View File

@@ -99,7 +99,7 @@ function executeCmd(command, args, options) {
fullCommand += args.length ? ' ' + args.join(' ') : '';
// Build the error instance
error = createError('Failed to execute "' + fullCommand + '", exit code of #' + code + '\n' + stderr, 'ECMDERR', {
error = createError('Failed to execute "' + fullCommand + '", exit code of #' + code, 'ECMDERR', {
details: stderr,
exitCode: code
});

View File

@@ -52,9 +52,7 @@ function extractTar(archive, dst) {
fs.createReadStream(archive)
.on('error', deferred.reject)
.pipe(tar.extract(dst, {
ignore: isSymlink, // Filter symlink files
dmode: 0555, // Ensure dirs are readable
fmode: 0444 // Ensure files are readable
ignore: isSymlink // Filter symlink files
}))
.on('error', deferred.reject)
.on('finish', deferred.resolve.bind(deferred, dst));
@@ -70,9 +68,7 @@ function extractTarGz(archive, dst) {
.pipe(zlib.createGunzip())
.on('error', deferred.reject)
.pipe(tar.extract(dst, {
ignore: isSymlink, // Filter symlink files
dmode: 0555, // Ensure dirs are readable
fmode: 0444 // Ensure files are readable
ignore: isSymlink // Filter symlink files
}))
.on('error', deferred.reject)
.on('finish', deferred.resolve.bind(deferred, dst));

View File

@@ -2,6 +2,7 @@
'use strict';
var isRoot = require('is-root');
var createError = require('./createError');
var cli = require('./cli');
var renderer;
@@ -22,7 +23,6 @@ https://gist.github.com/isaacs/579814\n\n\
You can however run a command with sudo using --allow-root option';
if (isRoot()) {
var cli = require('./cli');
renderer = cli.getRenderer('', false, config);
renderer.error(createError('Cannot be run with sudo', 'ESUDO', { details : errorMsg }));
process.exit(1);

View File

@@ -1,6 +1,6 @@
{
"name": "bower",
"version": "1.3.12",
"version": "1.3.9",
"description": "The browser package manager",
"author": "Twitter",
"licenses": [
@@ -16,65 +16,63 @@
"node": ">=0.10.0"
},
"dependencies": {
"abbrev": "^1.0.5",
"archy": "1.0.0",
"bower-config": "^0.5.2",
"bower-endpoint-parser": "^0.2.2",
"bower-json": "^0.4.0",
"bower-logger": "^0.2.2",
"bower-registry-client": "^0.2.1",
"cardinal": "0.4.4",
"chalk": "^1.0.0",
"chmodr": "0.1.0",
"decompress-zip": "^0.1.0",
"fstream": "^1.0.3",
"fstream-ignore": "^1.0.2",
"glob": "^4.3.2",
"graceful-fs": "^3.0.5",
"handlebars": "^2.0.0",
"inquirer": "0.8.0",
"insight": "^0.5.0",
"is-root": "^1.0.0",
"junk": "^1.0.0",
"lockfile": "^1.0.0",
"lru-cache": "^2.5.0",
"mkdirp": "0.5.0",
"mout": "^0.11.0",
"nopt": "^3.0.1",
"opn": "^1.0.1",
"p-throttler": "0.1.1",
"promptly": "0.2.0",
"q": "^1.1.2",
"request": "^2.51.0",
"request-progress": "0.3.1",
"retry": "0.6.1",
"rimraf": "^2.2.8",
"semver": "^2.3.0",
"shell-quote": "^1.4.2",
"stringify-object": "^1.0.0",
"tar-fs": "^1.4.1",
"tmp": "0.0.24",
"update-notifier": "^0.3.0",
"user-home": "^1.1.0",
"which": "^1.0.8"
"abbrev": "~1.0.4",
"archy": "0.0.2",
"bower-config": "~0.5.2",
"bower-endpoint-parser": "~0.2.2",
"bower-json": "~0.4.0",
"bower-logger": "~0.2.2",
"bower-registry-client": "~0.2.0",
"cardinal": "~0.4.0",
"chalk": "~0.5.0",
"chmodr": "~0.1.0",
"decompress-zip": "0.0.8",
"fstream": "~1.0.2",
"fstream-ignore": "~1.0.1",
"glob": "~4.0.2",
"graceful-fs": "~3.0.1",
"handlebars": "~2.0.0",
"inquirer": "~0.7.1",
"insight": "~0.4.1",
"is-root": "~1.0.0",
"junk": "~1.0.0",
"lockfile": "~1.0.0",
"lru-cache": "~2.5.0",
"mkdirp": "~0.5.0",
"mout": "~0.10.0",
"nopt": "~3.0.0",
"opn": "~1.0.0",
"osenv": "~0.1.0",
"p-throttler": "0.0.1",
"promptly": "~0.2.0",
"q": "~1.0.1",
"request": "~2.42.0",
"request-progress": "~0.3.0",
"retry": "~0.6.0",
"rimraf": "~2.2.0",
"semver": "~2.3.0",
"shell-quote": "~1.4.1",
"stringify-object": "~1.0.0",
"tar-fs": "~0.5.0",
"tmp": "0.0.23",
"update-notifier": "~0.2.0",
"which": "~1.0.5"
},
"devDependencies": {
"chai": "^1.10.0",
"coveralls": "^2.11.2",
"expect.js": "^0.3.1",
"grunt": "^0.4.5",
"coveralls": "~2.11.0",
"expect.js": "~0.3.1",
"grunt": "~0.4.4",
"grunt-cli": "^0.1.13",
"grunt-contrib-jshint": "^0.10.0",
"grunt-contrib-watch": "^0.6.1",
"grunt-exec": "^0.4.6",
"grunt-simple-mocha": "^0.4.0",
"istanbul": "^0.3.5",
"load-grunt-tasks": "^2.0.0",
"mocha": "^2.1.0",
"multiline": "^1.0.2",
"nock": "^0.56.0",
"node-uuid": "^1.4.2",
"proxyquire": "^1.3.0"
"grunt-contrib-jshint": "~0.10.0",
"grunt-contrib-watch": "~0.6.1",
"grunt-exec": "~0.4.2",
"grunt-simple-mocha": "~0.4.0",
"istanbul": "~0.3.2",
"load-grunt-tasks": "~0.6.0",
"mocha": "~1.21.4",
"nock": "~0.46.0",
"node-uuid": "~1.4.1",
"proxyquire": "~1.0.1"
},
"scripts": {
"test": "grunt test"

View File

@@ -1,5 +1,5 @@
{
"command": "cache clean",
"command": "cache list",
"description": "Cleans cached packages.",
"usage": [
"cache clean [<options>]",

View File

@@ -1,5 +1,5 @@
{
"command": "cache list",
"command": "cache clean",
"description": "Lists cached packages.",
"usage": [
"cache list [<options>]",

View File

@@ -30,11 +30,6 @@
"shorthand": "-D",
"flag": "--save-dev",
"description": "Save installed packages into the project's bower.json devDependencies"
},
{
"shorthand": "-E",
"flag": "--save-exact",
"description": "Configure installed packages with an exact version rather than semver"
}
]
}

View File

@@ -62,10 +62,6 @@
{
"flag": "--version",
"description": "Output Bower version"
},
{
"flag": "--no-color",
"description": "Disable colors"
}
]
}

View File

@@ -1,11 +1,9 @@
{{#yellow}}Unable to find a suitable version for {{name}}, please choose one:{{/yellow}}
{{#condense}}
{{#each picks}}
{{#magenta}}{{sum @index 1}}){{/magenta}} {{#cyan}}{{endpoint.name}}#{{endpoint.target}}{{/cyan}}{{#if pkgMeta._release}} which resolved to {{#green}}{{pkgMeta._release}}{{/green}}{{/if}}{{#if dependants}} and is required by {{#green}}{{dependants}}{{/green}}{{/if}}
{{#magenta}}{{sum @index 1}}){{/magenta}} {{#cyan}}{{endpoint.name}}#{{endpoint.target}}{{/cyan}}{{#if pkgMeta._release}} which resolved to {{#green}}{{pkgMeta._release}}{{/green}}{{/if}}{{#if dependants}} and is required by {{#green}}{{dependants}}{{/green}} {{/if}}
{{/each}}
{{/condense}}
{{#unless saveResolutions}}
Prefix the choice with ! to persist it to bower.json
{{/unless}}

View File

@@ -14,4 +14,3 @@ Commands:
{{#rpad length="23"}}{{@key}}{{/rpad}} {{.}}
{{/each}}
{{/condense}}

View File

@@ -5,4 +5,3 @@
Package not found.
{{/if}}
{{/condense}}

View File

@@ -5,6 +5,5 @@
{{#cyan}}{{{name}}}{{/cyan}} {{{url}}}
{{/.}}
{{/condense}}
{{else}}No results.
{{/if}}
{{/if}}

View File

@@ -1,31 +0,0 @@
var expect = require('expect.js');
var helpers = require('../helpers');
describe('bower', function () {
var oldStdout;
var text;
before(function() {
oldStdout = process.stdout.write;
text = '';
process.stdout.write = function(args) {
text += args;
};
});
it('runs bower installation', function (done) {
helpers.require('bin/bower');
setTimeout(function() {
done();
}, 250);
});
after(function() {
process.stdout.write = oldStdout;
expect(text).to.contain('Usage:');
expect(text).to.contain('Commands:');
});
});

View File

@@ -1,89 +0,0 @@
var expect = require('expect.js');
var helpers = require('../../helpers');
var cacheClean = helpers.command('cache/clean');
var md5 = helpers.require('lib/util/md5');
var object = require('mout/object');
describe('bower cache clean', function () {
// Because directory names are required to be mp5 of _source
var cacheFilesFactory = function (spec) {
var files = {};
object.map(spec, function(bowerJson) {
bowerJson._source = bowerJson.name + '/' + bowerJson.version;
var path = md5(bowerJson._source) + '/' + bowerJson.version + '/.bower.json';
files[path] = bowerJson;
});
return files;
};
var cacheFiles = cacheFilesFactory([
{
name: 'angular',
version: '1.3.8'
},
{
name: 'angular',
version: '1.3.9'
},
{
name: 'jquery',
version: '1.0.0'
}
]);
var cacheDir = new helpers.TempDir(cacheFiles);
it('correctly reads arguments', function() {
expect(cacheClean.readOptions(['jquery', 'angular']))
.to.eql([['jquery', 'angular'], {}]);
});
it('removes all cache', function () {
cacheDir.prepare();
return helpers.run(cacheClean, [undefined, {}, {
storage: {
packages: cacheDir.path
}
}]).spread(function(result) {
object.map(cacheFiles, function (_, cacheFile) {
expect(cacheDir.exists(cacheFile)).to.be(false);
});
});
});
it('removes single package', function () {
cacheDir.prepare();
return helpers.run(cacheClean, [['angular'], {}, {
storage: {
packages: cacheDir.path
}
}]).spread(function(result) {
var paths = Object.keys(cacheFiles);
expect(cacheDir.exists(paths[0])).to.be(false);
expect(cacheDir.exists(paths[1])).to.be(false);
expect(cacheDir.exists(paths[2])).to.be(true);
});
});
it('removes single package package version', function () {
cacheDir.prepare();
return helpers.run(cacheClean, [['angular#1.3.8'], {}, {
storage: {
packages: cacheDir.path
}
}]).spread(function(result) {
var paths = Object.keys(cacheFiles);
expect(cacheDir.exists(paths[0])).to.be(false);
expect(cacheDir.exists(paths[1])).to.be(true);
expect(cacheDir.exists(paths[2])).to.be(true);
});
});
});

View File

@@ -1,60 +0,0 @@
var expect = require('expect.js');
var helpers = require('../../helpers');
var cacheList = helpers.command('cache/list');
describe('bower cache list', function () {
var cacheDir = new helpers.TempDir({
'87323d6d4e48be291a9616a033d4cc6c/1.3.8/.bower.json': {
name: 'angular',
version: '1.3.8'
},
'87323d6d4e48be291a9616a033d4cc6c/1.3.9/.bower.json': {
name: 'angular',
version: '1.3.9'
},
'9eaed103d6a7e78d91f673cfad796850/1.0.0/.bower.json': {
name: 'jquery',
version: '1.0.0'
}
});
it('correctly reads arguments', function() {
expect(cacheList.readOptions(['jquery', 'angular']))
.to.eql([['jquery', 'angular'], {}]);
});
it('lists packages from cache', function () {
cacheDir.prepare();
return helpers.run(cacheList, [undefined, {}, {
storage: {
packages: cacheDir.path
}
}]).spread(function(result) {
expect(result[0].canonicalDir)
.to.be(cacheDir.getPath('87323d6d4e48be291a9616a033d4cc6c/1.3.8'));
expect(result[0].pkgMeta.version).to.be('1.3.8');
expect(result[1].pkgMeta.version).to.be('1.3.9');
expect(result[2].pkgMeta.version).to.be('1.0.0');
});
});
it('lists selected package names', function () {
cacheDir.prepare();
return helpers.run(cacheList, [['angular'], {}, {
storage: {
packages: cacheDir.path
}
}]).spread(function(result) {
expect(result[0].canonicalDir)
.to.be(cacheDir.getPath('87323d6d4e48be291a9616a033d4cc6c/1.3.8'));
expect(result[0].pkgMeta.version).to.be('1.3.8');
expect(result[1].pkgMeta.version).to.be('1.3.9');
});
});
});

View File

@@ -1,43 +0,0 @@
var expect = require('expect.js');
var helpers = require('../helpers');
var help = helpers.command('help');
describe('bower help', function () {
it('correctly reads arguments', function() {
expect(help.readOptions(['foo'])).to.eql(['foo']);
});
it('shows general help', function () {
return helpers.run(help).spread(function(result) {
expect(result.usage[0]).to.be.a('string');
expect(result.commands).to.be.a('object');
expect(result.options).to.be.a('object');
});
});
var commands = [
'home', 'info', 'init', 'install',
'link', 'list', 'lookup', 'prune', 'register',
'search', 'update', 'uninstall', 'version',
'cache list', 'cache clean'
];
commands.forEach(function(command) {
it('shows help for ' + command + ' command', function() {
return helpers.run(help, [command]).spread(function(result) {
expect(result.command).to.be(command);
expect(result.description).to.be.a('string');
expect(result.usage[0]).to.be.a('string');
});
});
});
it('displays error for non-existing command', function() {
return helpers.run(help, ['fuu']).fail(function(e) {
expect(e.message).to.be('Unknown command: fuu');
expect(e.command).to.be('fuu');
expect(e.code).to.be('EUNKNOWNCMD');
});
});
});

View File

@@ -1,59 +0,0 @@
var Q = require('q');
var expect = require('expect.js');
var helpers = require('../helpers');
var home = helpers.command('home');
describe('bower home', function () {
it('correctly reads arguments', function() {
expect(home.readOptions(['foo'])).to.eql(['foo']);
});
var package = new helpers.TempDir({
'bower.json': {
name: 'package',
homepage: 'http://bower.io'
}
});
var wrongPackage = new helpers.TempDir({
'bower.json': {
name: 'package'
}
});
it('opens repository home page in web browser', function () {
package.prepare();
return Q.Promise(function(resolve) {
var home = helpers.command('home', { opn: resolve });
helpers.run(home, [package.path]);
}).then(function(url) {
expect(url).to.be('http://bower.io');
});
});
it('opens home page of current repository', function () {
package.prepare();
return Q.Promise(function(resolve) {
var home = helpers.command('home', { opn: resolve });
helpers.run(home, [undefined, { cwd: package.path }]);
}).then(function(url) {
expect(url).to.be('http://bower.io');
});
});
it('errors if no homepage is set', function () {
wrongPackage.prepare();
return Q.Promise(function(resolve) {
var home = helpers.command('home', { opn: resolve });
helpers.run(home, [wrongPackage.path]).fail(resolve);
}).then(function(reason) {
expect(reason.message).to.be('No homepage set for package');
expect(reason.code).to.be('ENOHOME');
});
});
});

View File

@@ -1,21 +1,5 @@
describe('integration tests', function () {
require('./cache/list');
require('./cache/clean');
require('./help');
require('./home');
require('./info');
require('./init');
require('./install');
require('./list');
require('./link');
require('./lookup');
require('./prune');
require('./register');
require('./search');
require('./uninstall');
require('./update');
require('./version');
// run last because it changes defaults
require('./bower');
});

View File

@@ -1,52 +0,0 @@
var expect = require('expect.js');
var helpers = require('../helpers');
var info = helpers.command('info');
describe('bower info', function () {
it('correctly reads arguments', function() {
expect(info.readOptions(['pkg', 'property']))
.to.eql(['pkg', 'property']);
});
var meta = {
name: 'package',
version: '0.1.2',
homepage: 'http://bower.io',
description: 'Hello world!'
};
var meta2 = {
name: 'package',
version: '0.1.3',
homepage: 'http://bower.io',
description: 'Hello world! Hello!'
};
var package = new helpers.TempDir({
'0.1.2': { 'bower.json': meta },
'0.1.3': { 'bower.json': meta2 }
});
it('just returns if not package is specified', function () {
return helpers.run(info).spread(function(results) {
expect(results).to.be(undefined);
});
});
it('shows info about given package', function () {
return package.prepareGit({}).then(function() {
return helpers.run(info, [package.path]).spread(function(results) {
expect(results).to.eql({
'latest': meta2,
'name': package.path,
'versions': [
'0.1.3',
'0.1.2'
]
});
});
});
});
});

View File

@@ -1,24 +1,24 @@
var path = require('path');
var expect = require('expect.js');
var helpers = require('../helpers');
var fs = require('fs');
var init = helpers.command('init');
var helpers = require('../helpers');
var bower = helpers.require('lib/index');
describe('bower init', function () {
var package = new helpers.TempDir();
var tempDir = new helpers.TempDir();
var bowerJsonPath = path.join(tempDir.path, 'bower.json');
it('correctly reads arguments', function() {
expect(init.readOptions([]))
.to.eql([]);
});
var config = {
cwd: tempDir.path,
interactive: true
};
it('generates bower.json file', function () {
package.prepare();
tempDir.prepare();
var logger = init({
cwd: package.path,
interactive: true
});
var logger = bower.commands.init(config);
return helpers.expectEvent(logger, 'prompt')
.spread(function (prompt, answer) {
@@ -37,49 +37,14 @@ describe('bower init', function () {
return helpers.expectEvent(logger, 'prompt');
})
.spread(function (prompt, answer) {
answer({ prompt: true });
answer({
prompt: true
});
return helpers.expectEvent(logger, 'end');
})
.then(function () {
expect(package.readJson('bower.json')).to.eql({
name: 'test-name',
version: 'test-version',
homepage: 'test-homepage',
authors: [ 'test-author' ],
description: 'test-description',
moduleType: 'test-moduleType',
keywords: [ 'test-keyword' ],
license: 'test-license'
});
});
});
it('errors on non-interactive mode', function () {
package.prepare();
return helpers.run(init, { cwd: package.path }).then(
function () { throw 'should fail'; },
function (reason) {
expect(reason.message).to.be('Register requires an interactive shell');
expect(reason.code).to.be('ENOINT');
}
);
});
it('warns about existing bower.json', function () {
package.prepare({
'bower.json': {
name: 'foobar'
}
});
var logger = init({ cwd: package.path, interactive: true });
return helpers.expectEvent(logger, 'log').spread(function(event) {
expect(event.level).to.be('warn');
expect(event.message).to.be(
'The existing bower.json file will be used and filled in'
);
expect(fs.existsSync(bowerJsonPath)).to.be(true);
});
});
});

View File

@@ -1,43 +1,30 @@
var expect = require('expect.js');
var object = require('mout').object;
var helpers = require('../helpers');
var commands = helpers.require('lib/index').commands;
describe('bower install', function () {
var tempDir = new helpers.TempDir();
var install = helpers.command('install', { cwd: tempDir.path });
it('correctly reads arguments', function() {
expect(install.readOptions(['jquery', 'angular', '-F', '-p', '-S', '-D', '-E']))
.to.eql([['jquery', 'angular'], {
forceLatest: true,
production: true,
save: true,
saveDev: true,
saveExact: true
}]);
});
it('correctly reads long arguments', function() {
expect(install.readOptions([
'jquery', 'angular',
'--force-latest', '--production', '--save', '--save-dev', '--save-exact'
])).to.eql([['jquery', 'angular'], {
forceLatest: true,
production: true,
save: true,
saveDev: true,
saveExact: true
}]);
});
var package = new helpers.TempDir({
'bower.json': {
name: 'package'
}
}).prepare();
var gitPackage = new helpers.TempDir();
var install = function(packages, options, config) {
config = object.merge(config || {}, {
cwd: tempDir.path
});
var logger = commands.install(
packages, options, config
);
return helpers.expectEvent(logger, 'end');
};
it('writes to bower.json if --save flag is used', function () {
package.prepare();
@@ -48,73 +35,11 @@ describe('bower install', function () {
}
});
return helpers.run(install, [[package.path], { save: true }]).then(function() {
return install([package.path], { save: true }).then(function() {
expect(tempDir.read('bower.json')).to.contain('dependencies');
});
});
it('writes an exact version number to dependencies in bower.json if --save --save-exact flags are used', function () {
package.prepare({
'bower.json': {
version: '1.2.3'
}
});
tempDir.prepare({
'bower.json': {
name: 'test'
}
});
return helpers.run(install, [
[package.path],
{ saveExact: true, save: true }
]).then(function() {
expect(tempDir.readJson('bower.json').dependencies.package).to.equal('1.2.3');
});
});
it('writes an exact version number to devDependencies in bower.json if --save-dev --save-exact flags are used', function () {
package.prepare({
'bower.json': {
version: '0.1.0'
}
});
tempDir.prepare({
'bower.json': {
name: 'test'
}
});
return helpers.run(install, [
[package.path],
{ saveExact: true, saveDev: true }
]).then(function() {
expect(tempDir.readJson('bower.json').devDependencies.package).to.equal('0.1.0');
});
});
it('does not write to bower.json if only --save-exact flag is used', function() {
package.prepare({
'bower.json': {
version: '1.2.3'
}
});
tempDir.prepare({
'bower.json': {
name: 'test'
}
});
return helpers.run(install, [[package.path], { saveExact: true }]).then(function() {
expect(tempDir.read('bower.json')).to.not.contain('dependencies');
expect(tempDir.read('bower.json')).to.not.contain('devDependencies');
});
});
it('reads .bowerrc from cwd', function () {
package.prepare({ foo: 'bar' });
@@ -128,7 +53,7 @@ describe('bower install', function () {
}
});
return helpers.run(install).then(function() {
return install().then(function() {
expect(tempDir.read('assets/package/foo')).to.be('bar');
});
});
@@ -145,12 +70,12 @@ describe('bower install', function () {
},
'.bowerrc': {
scripts: {
preinstall: 'node -e \'require("fs").writeFileSync("preinstall.txt", "%")\''
preinstall: 'bash -c "echo -n % > preinstall.txt"'
}
}
});
return helpers.run(install).then(function() {
return install().then(function() {
expect(tempDir.read('preinstall.txt')).to.be('package');
});
});
@@ -167,12 +92,12 @@ describe('bower install', function () {
},
'.bowerrc': {
scripts: {
postinstall: 'node -e \'require("fs").writeFileSync("postinstall.txt", "%")\''
postinstall: 'bash -c "echo -n % > postinstall.txt"'
}
}
});
return helpers.run(install).then(function() {
return install().then(function() {
expect(tempDir.read('postinstall.txt')).to.be('package');
});
});
@@ -185,13 +110,13 @@ describe('bower install', function () {
},
'.bowerrc': {
scripts: {
postinstall: 'node -e \'require("fs").writeFileSync("hooks.txt", "%")\'',
preinstall: 'node -e \'require("fs").writeFileSync("hooks.txt", "%")\''
postinstall: 'bash -c "echo -n % > hooks.txt"',
preinstall: 'bash -c "echo -n % > hooks.txt"'
}
}
});
return helpers.run(install).then(function() {
return install().then(function() {
expect(tempDir.exists('hooks.txt')).to.be(false);
});
});
@@ -205,72 +130,13 @@ describe('bower install', function () {
},
'.bowerrc': {
scripts: {
postinstall: 'node -e \'var fs = require("fs"); fs.writeFileSync("hook.txt", fs.readFileSync("bower.json"));\''
postinstall: 'bash -c "cat bower.json > hook.txt"',
}
}
});
return helpers.run(install, [[package.path], { save: true }]).then(function() {
return install([package.path], { save: true }).then(function() {
expect(tempDir.read('hook.txt')).to.contain('dependencies');
});
});
it('display the output of hook scripts', function (next) {
package.prepare();
tempDir.prepare({
'bower.json': {
name: 'test',
dependencies: {
package: package.path
}
},
'.bowerrc': {
scripts: {
postinstall: 'node -e \'process.stdout.write("foobar")\''
}
}
});
var lastAction = null;
helpers.run(install).logger.intercept(function (log) {
if (log.level === 'action') {
lastAction = log;
}
}).on('end', function () {
expect(lastAction.message).to.be('foobar');
next();
});
});
it('works for git repositories', function () {
return gitPackage.prepareGit({
'1.0.0': {
'bower.json': {
name: 'package'
},
'version.txt': '1.0.0'
},
'1.0.1': {
'bower.json': {
name: 'package'
},
'version.txt': '1.0.1'
}
}).then(function() {
tempDir.prepare({
'bower.json': {
name: 'test',
dependencies: {
package: gitPackage.path + '#1.0.0'
}
}
});
return helpers.run(install).then(function() {
expect(tempDir.read('bower_components/package/version.txt')).to.contain('1.0.0');
});
});
});
});

View File

@@ -1,110 +0,0 @@
var expect = require('expect.js');
var helpers = require('../helpers');
var link = helpers.command('link');
describe('bower link', function () {
var package = new helpers.TempDir({
'bower.json': {
name: 'package',
},
'index.js': 'Hello World!'
});
var otherPackage = new helpers.TempDir({
'bower.json': {
name: 'package2',
},
'index.js': 'Welcome World!'
});
var linksDir = new helpers.TempDir();
beforeEach(function() {
package.prepare();
otherPackage.prepare();
linksDir.prepare();
});
it('correctly reads arguments', function() {
expect(link.readOptions(['jquery', 'angular']))
.to.eql(['jquery', 'angular']);
});
it('creates self link', function () {
return helpers.run(link, [undefined, undefined,
{
cwd: package.path,
storage: {
links: linksDir.path
}
}
]).then(function() {
expect(linksDir.read('package/index.js'))
.to.be('Hello World!');
});
});
it('creates inter-link', function () {
return helpers.run(link, [undefined, undefined,
{
cwd: package.path,
storage: {
links: linksDir.path
}
}
]).then(function () {
return helpers.run(link, ['package', undefined,
{
cwd: otherPackage.path,
storage: {
links: linksDir.path
}
}
]);
}).then(function() {
expect(otherPackage.read('bower_components/package/index.js'))
.to.be('Hello World!');
});
});
it('creates inter-link with custom local name', function () {
return helpers.run(link, [undefined, undefined,
{
cwd: package.path,
storage: {
links: linksDir.path
}
}
]).then(function () {
return helpers.run(link, ['package', 'local',
{
cwd: otherPackage.path,
storage: {
links: linksDir.path
}
}
]);
}).then(function() {
expect(otherPackage.read('bower_components/local/index.js'))
.to.be('Hello World!');
});
});
it('errors on unexising package', function () {
return helpers.run(link, ['package', 'local',
{
cwd: otherPackage.path,
storage: {
links: linksDir.path
}
}
]).then(function() {
throw 'Should fail creating a link!';
}).fail(function(reason) {
expect(reason.code).to.be('ENOENT');
expect(reason.message).to.be('Failed to create link to package');
});
});
});

View File

@@ -1,254 +0,0 @@
var expect = require('expect.js');
var object = require('mout').object;
var path = require('path');
var helpers = require('../helpers');
var commands = {
install: helpers.command('install'),
list: helpers.command('list')
};
describe('bower list', function () {
var tempDir = new helpers.TempDir();
var gitPackage = new helpers.TempDir();
var install = function(packages, options, config) {
config = object.merge(config || {}, {
cwd: tempDir.path
});
return helpers.run(commands.install, [packages, options, config]);
};
var list = function(options, config) {
config = object.merge(config || {}, {
cwd: tempDir.path
});
return helpers.run(commands.list, [options, config]);
};
it('correctly reads arguments', function() {
expect(commands.list.readOptions(['-p', '-r']))
.to.eql([{
paths: true,
relative: true
}]);
});
it('correctly reads long arguments', function() {
expect(commands.list.readOptions(['--paths', '--relative']))
.to.eql([{
paths: true,
relative: true
}]);
});
it('lists no packages when nothing installed', function () {
tempDir.prepare();
return list().spread(function(results) {
expect(results).to.be.an(Object);
expect(results.canonicalDir).to.equal(tempDir.path);
expect(results.pkgMeta.dependencies).to.eql({});
expect(results.pkgMeta.devDependencies).to.eql({});
expect(results.dependencies).to.eql({});
expect(results.nrDependants).to.eql(0);
expect(results.versions).to.eql([]);
});
});
it('lists 1 dependency when 1 local package installed', function () {
var package = new helpers.TempDir({
'bower.json': {
name: 'package',
main: 'test.txt'
}
}).prepare();
package.prepare();
return install([package.path]).then(function() {
return list().spread(function(results) {
expect(results).to.be.an(Object);
expect(results.canonicalDir).to.equal(tempDir.path);
expect(results.pkgMeta.dependencies).to.eql({
package: package.path + '#*'
});
expect(results.pkgMeta.devDependencies).to.eql({});
expect(results.dependencies.package).to.be.an(Object);
expect(results.dependencies.package.pkgMeta).to.be.an(Object);
expect(results.dependencies.package.pkgMeta.main).to.equal('test.txt');
expect(results.dependencies.package.canonicalDir).to.equal(
path.join(tempDir.path, 'bower_components/package')
);
expect(results.dependencies.package.dependencies).to.eql({});
expect(results.dependencies.package.nrDependants).to.equal(1);
expect(results.dependencies.package.versions).to.eql([]);
expect(results.nrDependants).to.equal(0);
expect(results.versions).to.eql([]);
});
});
});
it('lists 1 dependency with relative paths when 1 local package installed', function () {
var package = new helpers.TempDir({
'bower.json': {
name: 'package',
main: 'test.txt'
}
}).prepare();
package.prepare();
return install([package.path]).then(function() {
return list({relative: true}).spread(function(results) {
expect(results).to.be.an(Object);
expect(results.canonicalDir).to.equal(tempDir.path);
expect(results.dependencies).to.be.an(Object);
expect(results.dependencies.package).to.be.an(Object);
expect(results.dependencies.package.pkgMeta).to.be.an(Object);
expect(results.dependencies.package.pkgMeta.main).to.equal('test.txt');
expect(results.pkgMeta.dependencies).to.eql({
package: package.path + '#*'
});
expect(results.dependencies.package.canonicalDir).to.equal(
path.normalize('bower_components/package')
);
});
});
});
it('lists 1 dependency with 1 source relative source mapping when 1 local package installed', function () {
var package = new helpers.TempDir({
'bower.json': {
name: 'package',
main: 'test.txt'
}
}).prepare();
package.prepare();
return install([package.path]).then(function() {
return list({paths: true}).spread(function(results) {
expect(results).to.be.an(Object);
expect(results.package).to.equal(
'bower_components/package/test.txt'
);
});
});
});
it('lists 1 dependency with 2 source relative source mapping when 1 local package installed', function () {
var package = new helpers.TempDir({
'bower.json': {
name: 'package',
main: ['test.txt', 'test2.txt']
}
}).prepare();
package.prepare();
return install([package.path]).then(function() {
return list({paths: true}).spread(function(results) {
expect(results).to.be.an(Object);
expect(results.package).to.be.an(Object);
expect(results.package).to.eql([
'bower_components/package/test.txt',
'bower_components/package/test2.txt'
]);
});
});
});
it('lists 1 dependency when 1 git package installed', function () {
return gitPackage.prepareGit({
'1.0.0': {
'bower.json': {
name: 'package',
main: 'test.txt'
},
'version.txt': '1.0.0'
},
'1.0.1': {
'bower.json': {
name: 'package',
main: 'test2.txt'
},
'version.txt': '1.0.1'
}
}).then(function() {
tempDir.prepare({
'bower.json': {
name: 'test',
dependencies: {
package: gitPackage.path + '#1.0.0'
}
}
});
return install().then(function() {
return list().spread(function(results) {
expect(results).to.be.an(Object);
expect(results.canonicalDir).to.equal(tempDir.path);
expect(results.pkgMeta.dependencies).to.eql({
package: gitPackage.path + '#1.0.0'
});
expect(results.pkgMeta.devDependencies).to.eql({});
expect(results.dependencies.package).to.be.an(Object);
expect(results.dependencies.package.pkgMeta).to.be.an(Object);
expect(results.dependencies.package.pkgMeta.main).to.equal('test.txt');
expect(results.dependencies.package.canonicalDir).to.equal(
path.join(tempDir.path, 'bower_components/package')
);
expect(results.dependencies.package.dependencies).to.eql({});
expect(results.dependencies.package.nrDependants).to.equal(1);
expect(results.dependencies.package.versions).to.eql(['1.0.1', '1.0.0']);
expect(results.nrDependants).to.equal(0);
expect(results.versions).to.eql([]);
});
});
});
});
it('lists 1 dependency with relative paths when 1 git package installed', function () {
return gitPackage.prepareGit({
'1.0.0': {
'bower.json': {
name: 'package',
main: 'test.txt'
},
'version.txt': '1.0.0'
},
'1.0.1': {
'bower.json': {
name: 'package',
main: 'test2.txt'
},
'version.txt': '1.0.1'
}
}).then(function() {
tempDir.prepare({
'bower.json': {
name: 'test',
dependencies: {
package: gitPackage.path + '#1.0.0'
}
}
});
return install().then(function() {
return list({relative: true}).spread(function(results) {
expect(results.canonicalDir).to.equal(tempDir.path);
expect(results.pkgMeta.dependencies).to.eql({
package: gitPackage.path + '#1.0.0'
});
expect(results.dependencies.package.canonicalDir).to.equal(
path.normalize('bower_components/package')
);
});
});
});
});
});

View File

@@ -1,55 +0,0 @@
var expect = require('expect.js');
var helpers = require('../helpers');
var lookup = helpers.command('lookup');
describe('bower lookup', function () {
var lookupWithResult = function (response) {
return helpers.command('lookup', {
'bower-registry-client': function() {
return {
lookup: function(query, callback) {
if (query in response) {
callback(null, response[query]);
} else {
callback();
}
}
};
}
});
};
it('correctly reads arguments', function() {
expect(lookup.readOptions(['jquery']))
.to.eql(['jquery']);
});
it('lookups package by name', function () {
var lookup = lookupWithResult({ jquery: { url: 'http://jquery.org' } });
return helpers.run(lookup, ['jquery']).spread(function(result) {
expect(result).to.eql({
name: 'jquery',
url: 'http://jquery.org'
});
});
});
it('returns null if no package is found', function () {
var lookup = lookupWithResult({ jquery: { url: 'http://jquery.org' } });
return helpers.run(lookup, ['foobar']).spread(function(result) {
expect(result).to.eql(null);
});
});
it('returns null if called without argument', function () {
var lookup = lookupWithResult({ jquery: { url: 'http://jquery.org' } });
return helpers.run(lookup, []).spread(function(result) {
expect(result).to.eql(null);
});
});
});

View File

@@ -1,65 +0,0 @@
var expect = require('expect.js');
var helpers = require('../helpers');
var prune = helpers.command('prune');
describe('bower home', function () {
var package = new helpers.TempDir({
'bower.json': {
name: 'package',
dependencies: {
jquery: '*'
}
},
'bower_components/jquery/jquery.js': 'jquery source'
});
it('correctly reads arguments', function() {
expect(prune.readOptions(['-p']))
.to.eql([{ production: true }]);
});
it('correctly reads long arguments', function() {
expect(prune.readOptions(['--production']))
.to.eql([{ production: true }]);
});
it('removes extraneous packages', function () {
package.prepare({
'bower_components/angular/angular.js': 'angular source',
'bower_components/angular/.bower.json': { name: 'angular' }
});
return helpers.run(prune, [{}, { cwd: package.path }]).then(function() {
expect(package.exists('bower_components/angular/angular.js'))
.to.be(false);
});
});
it('leaves non-bower packages', function () {
package.prepare({
'bower_components/angular/angular.js': 'angular source'
});
return helpers.run(prune, [{}, { cwd: package.path }]).then(function() {
expect(package.exists('bower_components/angular/angular.js'))
.to.be(true);
});
});
it('deals with custom directory', function () {
package.prepare({
'.bowerrc': { directory: 'components' },
'bower_components/angular/.bower.json': { name: 'angular' },
'bower_components/angular/angular.js': 'angular source',
'components/angular/.bower.json': { name: 'angular' },
'components/angular/angular.js': 'angular source'
});
return helpers.run(prune, [{}, { cwd: package.path }]).then(function() {
expect(package.exists('components/angular/angular.js')).to.be(false);
expect(package.exists('bower_components/angular/angular.js')).to.be(true);
});
});
});

View File

@@ -1,125 +0,0 @@
var Q = require('q');
var expect = require('expect.js');
var helpers = require('../helpers');
var register = helpers.command('register');
var fakeRepositoryFactory = function (canonicalDir, pkgMeta) {
function FakeRepository() { }
FakeRepository.prototype.fetch = function() {
return Q.fcall(function () {
return [canonicalDir, pkgMeta];
});
};
FakeRepository.prototype.getRegistryClient = function() {
return {
register: function (name, url, cb) {
cb(null, { name: name, url: url });
}
};
};
return FakeRepository;
};
var register = helpers.command('register');
var registerFactory = function (canonicalDir, pkgMeta) {
return helpers.command('register', {
'../core/PackageRepository': fakeRepositoryFactory(
canonicalDir, pkgMeta
)
});
};
describe('bower register', function () {
var package = new helpers.TempDir({
'bower.json': {
name: 'package'
}
});
it('correctly reads arguments', function() {
expect(register.readOptions(['jquery', 'url']))
.to.eql(['jquery', 'url']);
});
it('errors if name is not provided', function () {
return helpers.run(register).fail(function(reason) {
expect(reason.message).to.be('Usage: bower register <name> <url>');
expect(reason.code).to.be('EINVFORMAT');
});
});
it('errors if url is not provided', function () {
return helpers.run(register, ['some-name'])
.fail(function(reason) {
expect(reason.message).to.be('Usage: bower register <name> <url>');
expect(reason.code).to.be('EINVFORMAT');
});
});
it('errors if url is not correct', function () {
return helpers.run(register, ['some-name', 'url'])
.fail(function(reason) {
expect(reason.message).to.be('The registry only accepts URLs starting with git://');
expect(reason.code).to.be('EINVFORMAT');
});
});
it('errors if trying to register private package', function () {
package.prepare({ 'bower.json': { private: true } });
var register = registerFactory(package.path, package.meta());
return helpers.run(register, ['some-name', 'git://fake-url.git'])
.fail(function(reason) {
expect(reason.message).to.be('The package you are trying to register is marked as private');
expect(reason.code).to.be('EPRIV');
});
});
it('should call registry client with name and url', function () {
package.prepare();
var register = registerFactory(package.path, package.meta());
return helpers.run(register, ['some-name', 'git://fake-url.git'])
.spread(function(result) {
expect(result).to.eql({
// Result from register action on stub
name: 'some-name', url: 'git://fake-url.git'
});
});
});
it('should confirm in interactive mode', function () {
package.prepare();
var register = registerFactory(package.path, package.meta());
var promise = helpers.run(register,
['some-name', 'git://fake-url.git', { interactive: true }]
);
return helpers.expectEvent(promise.logger, 'confirm')
.spread(function(e) {
expect(e.type).to.be('confirm');
expect(e.message).to.be('Registering a package will make it installable via the registry (https://bower.herokuapp.com), continue?');
expect(e.default).to.be(true);
});
});
it('should skip confirming when forcing', function () {
package.prepare();
var register = registerFactory(package.path, package.meta());
return helpers.run(register,
['some-name', 'git://fake-url.git',
{ interactive: true, force: true }
]
);
});
});

View File

@@ -1,44 +0,0 @@
var Q = require('q');
var expect = require('expect.js');
var helpers = require('../helpers');
var search = helpers.command('search');
describe('bower search', function () {
it('correctly reads arguments', function() {
expect(search.readOptions(['jquery']))
.to.eql(['jquery']);
});
it('searches for single repository', function () {
return Q.Promise(function(resolve) {
var search = helpers.command('search', {
'bower-registry-client': function() {
return {
search: resolve
};
}
});
helpers.run(search, ['jquery'], {});
}).then(function(query) {
expect(query).to.be('jquery');
});
});
it('lists all repositories if no query given', function () {
return Q.Promise(function(resolve) {
var search = helpers.command('search', {
'bower-registry-client': function() {
return {
list: resolve
};
}
});
helpers.run(search, [], {});
});
});
});

View File

@@ -3,7 +3,7 @@ var expect = require('expect.js');
var fs = require('fs');
var helpers = require('../helpers');
var uninstall = helpers.command('uninstall');
var bower = helpers.require('lib/index');
describe('bower uninstall', function () {
@@ -31,24 +31,20 @@ describe('bower uninstall', function () {
interactive: true
};
it('correctly reads arguments', function() {
expect(uninstall.readOptions(['jquery', '-S', '-D']))
.to.eql([['jquery'], { save: true, saveDev: true }]);
});
it('correctly reads long arguments', function() {
expect(uninstall.readOptions(['jquery', '--save', '--save-dev']))
.to.eql([['jquery'], { save: true, saveDev: true }]);
});
it('does not remove anything from dependencies by default', function () {
return helpers.run(uninstall, [['underscore'], undefined, config]).then(function () {
var logger = bower.commands.uninstall(['underscore'], undefined, config);
return helpers.expectEvent(logger, 'end')
.then(function () {
expect(bowerJson().dependencies).to.eql({ 'underscore': '*' });
});
});
it('removes dependency from bower.json if --save flag is used', function () {
return helpers.run(uninstall, [['underscore'], {save: true}, config]).then(function () {
var logger = bower.commands.uninstall(['underscore'], {save: true}, config);
return helpers.expectEvent(logger, 'end')
.then(function () {
expect(bowerJson().dependencies).to.eql({});
});
});

View File

@@ -1,246 +0,0 @@
var expect = require('expect.js');
var object = require('mout').object;
var helpers = require('../helpers');
var updateCmd = helpers.command('update');
var commands = helpers.require('lib/index').commands;
describe('bower update', function () {
var tempDir = new helpers.TempDir();
var gitPackage = new helpers.TempDir();
gitPackage.prepareGit({
'1.0.0': {
'bower.json': {
name: 'package'
},
'version.txt': '1.0.0'
},
'1.0.1': {
'bower.json': {
name: 'package'
},
'version.txt': '1.0.1'
}
});
var package = new helpers.TempDir({
'bower.json': {
name: 'package'
}
}).prepare();
var updateLogger = function(packages, options, config) {
config = object.merge(config || {}, {
cwd: tempDir.path
});
return commands.update(packages, options, config);
};
var update = function(packages, options, config) {
var logger = updateLogger(packages, options, config);
return helpers.expectEvent(logger, 'end');
};
var install = function(packages, options, config) {
config = object.merge(config || {}, {
cwd: tempDir.path
});
var logger = commands.install(
packages, options, config
);
return helpers.expectEvent(logger, 'end');
};
it('correctly reads arguments', function() {
expect(updateCmd.readOptions(['jquery', '-F', '-p']))
.to.eql([['jquery'], { forceLatest: true, production: true }]);
});
it('install missing packages', function () {
package.prepare();
tempDir.prepare({
'bower.json': {
name: 'test',
dependencies: {
package: package.path
}
}
});
return update().then(function() {
expect(tempDir.exists('bower_components/package/bower.json')).to.equal(true);
expect(tempDir.read('bower_components/package/bower.json')).to.contain('"name": "package"');
});
});
it('runs preinstall hook when installing missing package', function () {
package.prepare();
tempDir.prepare({
'bower.json': {
name: 'test',
dependencies: {
package: package.path
}
},
'.bowerrc': {
scripts: {
preinstall: 'node -e \'require("fs").writeFileSync("preinstall.txt", "%")\''
}
}
});
return update().then(function() {
expect(tempDir.read('preinstall.txt')).to.be('package');
});
});
it('runs postinstall hook when installing missing package', function () {
package.prepare();
tempDir.prepare({
'bower.json': {
name: 'test',
dependencies: {
package: package.path
}
},
'.bowerrc': {
scripts: {
postinstall: 'node -e \'require("fs").writeFileSync("postinstall.txt", "%")\''
}
}
});
return update().then(function() {
expect(tempDir.read('postinstall.txt')).to.be('package');
});
});
it('doesn\'t runs postinstall when no package is update', function () {
package.prepare();
tempDir.prepare({
'bower.json': {
name: 'test',
dependencies: {
package: package.path
}
},
'.bowerrc': {
scripts: {
postinstall: 'node -e \'require("fs").writeFileSync("postinstall.txt", "%")\''
}
}
});
return install().then(function() {
tempDir.prepare();
return update().then(function() {
expect(tempDir.exists('postinstall.txt')).to.be(false);
});
});
});
it('updates a package', function () {
tempDir.prepare({
'bower.json': {
name: 'test',
dependencies: {
package: gitPackage.path + '#1.0.0'
}
}
});
return install().then(function() {
expect(tempDir.read('bower_components/package/version.txt')).to.contain('1.0.0');
tempDir.prepare({
'bower.json': {
name: 'test',
dependencies: {
package: gitPackage.path + '#1.0.1'
}
}
});
return update().then(function() {
expect(tempDir.read('bower_components/package/version.txt')).to.contain('1.0.1');
});
});
});
it('runs preinstall hook when updating a package', function () {
tempDir.prepare({
'bower.json': {
name: 'test',
dependencies: {
package: gitPackage.path + '#1.0.0'
}
},
'.bowerrc': {
scripts: {
preinstall: 'node -e \'require("fs").writeFileSync("preinstall.txt", "%")\''
}
}
});
return install().then(function() {
tempDir.prepare({
'bower.json': {
name: 'test',
dependencies: {
package: gitPackage.path + '#1.0.1'
}
}
});
expect(tempDir.exists('preinstall.txt')).to.be(false);
return update().then(function() {
expect(tempDir.read('preinstall.txt')).to.be('package');
});
});
});
it('runs postinstall hook when updating a package', function () {
tempDir.prepare({
'bower.json': {
name: 'test',
dependencies: {
package: gitPackage.path + '#1.0.0'
}
},
'.bowerrc': {
scripts: {
preinstall: 'node -e \'require("fs").writeFileSync("preinstall.txt", "%")\'',
postinstall: 'node -e \'require("fs").writeFileSync("postinstall.txt", "%")\''
}
}
});
return install().then(function() {
tempDir.prepare({
'bower.json': {
name: 'test',
dependencies: {
package: gitPackage.path + '#1.0.1'
}
}
});
expect(tempDir.exists('postinstall.txt')).to.be(false);
return update().then(function() {
expect(tempDir.read('postinstall.txt')).to.be('package');
});
});
});
});

View File

@@ -1,91 +0,0 @@
var expect = require('expect.js');
var helpers = require('../helpers');
var version = helpers.require('lib/commands').version;
describe('bower list', function () {
var package = new helpers.TempDir({
'bower.json': {
name: 'foobar',
version: '0.0.0'
}
});
var gitPackage = new helpers.TempDir({
'v0.0.0': {
'bower.json': {
name: 'foobar',
version: '0.0.0'
}
}
});
it('bumps patch version', function() {
package.prepare();
return helpers.run(version, ['patch', {}, { cwd: package.path }]).then(function() {
expect(package.readJson('bower.json').version).to.be('0.0.1');
});
});
it('bumps minor version', function() {
package.prepare();
return helpers.run(version, ['minor', {}, { cwd: package.path }]).then(function() {
expect(package.readJson('bower.json').version).to.be('0.1.0');
});
});
it('bumps major version', function() {
package.prepare();
return helpers.run(version, ['major', {}, { cwd: package.path }]).then(function() {
expect(package.readJson('bower.json').version).to.be('1.0.0');
});
});
it('changes version', function() {
package.prepare();
return helpers.run(version, ['1.2.3', {}, { cwd: package.path }]).then(function() {
expect(package.readJson('bower.json').version).to.be('1.2.3');
});
});
it('bumps patch version, create commit, and tag', function() {
return gitPackage.prepareGit().then(function() {
return helpers.run(version, ['patch', {}, { cwd: gitPackage.path }]).then(function() {
expect(gitPackage.readJson('bower.json').version).to.be('0.0.1');
return gitPackage.git('tag').spread(function(result) {
expect(result).to.be('v0.0.0\nv0.0.1\n');
return gitPackage.git('log', '--pretty=format:%s', '-n1').spread(function(result) {
expect(result).to.be('v0.0.1');
});
});
});
});
});
it('bumps with custom commit message', function() {
return gitPackage.prepareGit().then(function() {
return helpers.run(version, ['patch', { message: 'Bumping %s, because what'}, { cwd: gitPackage.path }]).then(function() {
expect(gitPackage.readJson('bower.json').version).to.be('0.0.1');
return gitPackage.git('tag').spread(function(result) {
expect(result).to.be('v0.0.0\nv0.0.1\n');
return gitPackage.git('log', '--pretty=format:%s', '-n1').spread(function(result) {
expect(result).to.be('Bumping 0.0.1, because what');
});
});
});
});
});
});

View File

@@ -11,7 +11,6 @@ var defaultConfig = require('../../lib/config');
var ResolveCache = require('../../lib/core/ResolveCache');
var resolvers = require('../../lib/core/resolvers');
var copy = require('../../lib/util/copy');
var helpers = require('../helpers');
describe('PackageRepository', function () {
var packageRepository;
@@ -22,8 +21,7 @@ describe('PackageRepository', function () {
var tempPackage = path.resolve(__dirname, '../tmp/temp-package');
var packagesCacheDir = path.join(__dirname, '../tmp/temp-resolve-cache');
var registryCacheDir = path.join(__dirname, '../tmp/temp-registry-cache');
var mockSource = helpers.localSource(testPackage);
var mockSource = 'file://' + testPackage;
var forceCaching = true;
after(function () {
@@ -67,7 +65,7 @@ describe('PackageRepository', function () {
return Q.resolve(resolver);
}
resolverFactory.getConstructor = function () {
return Q.resolve([resolvers.GitRemote, helpers.localSource(testPackage), false]);
return Q.resolve([resolvers.GitRemote, 'file://' + testPackage, false]);
};
resolverFactory.clearRuntimeCache = function () {
resolverFactoryClearHook();
@@ -184,7 +182,7 @@ describe('PackageRepository', function () {
return originalRetrieve.apply(this, arguments);
};
packageRepository.fetch({ name: '', source: helpers.localSource(testPackage), target: '~0.1.0' })
packageRepository.fetch({ name: '', source: testPackage, target: '~0.1.0' })
.spread(function (canonicalDir, pkgMeta) {
expect(called).to.be(false);
expect(fs.existsSync(canonicalDir)).to.be(true);

View File

@@ -908,6 +908,7 @@ describe('ResolveCache', function () {
expect(entries).to.be.an('array');
expectedJson = fs.readFileSync(path.join(__dirname, '../assets/resolve-cache/list-json-1.json'));
expectedJson = expectedJson.toString().trim();
mout.object.forOwn(entries, function (entry) {
// Trim absolute bower path from json
@@ -916,7 +917,8 @@ describe('ResolveCache', function () {
entry.canonicalDir = entry.canonicalDir.replace(/\\/g, '/');
});
expect(entries).to.eql(JSON.parse(expectedJson));
json = JSON.stringify(entries, null, ' ');
expect(json).to.equal(expectedJson);
next();
})

View File

@@ -10,7 +10,6 @@ var Logger = require('bower-logger');
var resolverFactory = require('../../lib/core/resolverFactory');
var resolvers = require('../../lib/core/resolvers');
var defaultConfig = require('../../lib/config');
var helpers = require('../helpers');
describe('resolverFactory', function () {
var tempSource;
@@ -31,7 +30,7 @@ describe('resolverFactory', function () {
});
after(function (next) {
rimraf('pure', next);
rimraf('dejavu', next);
});
function callFactory(decEndpoint, config) {
@@ -340,9 +339,7 @@ describe('resolverFactory', function () {
.done();
});
if (!helpers.hasSvn())
describe.skip('should recognize svn remote endpoints correctly', function() {});
else it('should recognize svn remote endpoints correctly', function (next) {
it('should recognize svn remote endpoints correctly', function (next) {
var promise = Q.resolve();
var endpoints;
@@ -527,31 +524,31 @@ describe('resolverFactory', function () {
});
it('should recognize registry endpoints correctly', function (next) {
// Create a 'pure' file at the root to prevent regressions of #666
fs.writeFileSync('pure', 'foo');
// Create a 'dejavu' file at the root to prevent regressions of #666
fs.writeFileSync('dejavu', 'foo');
callFactory({ source: 'pure' })
callFactory({ source: 'dejavu' })
.then(function (resolver) {
expect(resolver).to.be.a(resolvers.GitRemote);
expect(resolver.getSource()).to.equal('git://github.com/yui/pure-release.git');
expect(resolver.getSource()).to.equal('git://github.com/IndigoUnited/dejavu.git');
expect(resolver.getTarget()).to.equal('*');
})
.then(function () {
// Test with name
return callFactory({ source: 'pure', name: 'foo' })
return callFactory({ source: 'dejavu', name: 'foo' })
.then(function (resolver) {
expect(resolver).to.be.a(resolvers.GitRemote);
expect(resolver.getSource()).to.equal('git://github.com/yui/pure-release.git');
expect(resolver.getSource()).to.equal('git://github.com/IndigoUnited/dejavu.git');
expect(resolver.getName()).to.equal('foo');
expect(resolver.getTarget()).to.equal('*');
});
})
.then(function () {
// Test with target
return callFactory({ source: 'pure', target: '~0.4.0' })
return callFactory({ source: 'dejavu', target: '~2.0.0' })
.then(function (resolver) {
expect(resolver).to.be.a(resolvers.GitRemote);
expect(resolver.getTarget()).to.equal('~0.4.0');
expect(resolver.getTarget()).to.equal('~2.0.0');
next();
});
@@ -574,7 +571,7 @@ describe('resolverFactory', function () {
});
it('should set registry to true on the decomposed endpoint if fetched from the registry', function (next) {
var decEndpoint = { source: 'pure' };
var decEndpoint = { source: 'dejavu' };
callFactory(decEndpoint)
.then(function () {

View File

@@ -9,13 +9,11 @@ var mout = require('mout');
var Logger = require('bower-logger');
var SvnResolver = require('../../../lib/core/resolvers/SvnResolver');
var defaultConfig = require('../../../lib/config');
var helpers = require('../../helpers');
if (!helpers.hasSvn()) describe.skip('SvnResolver', function() {});
else describe('SvnResolver', function () {
describe('SvnResolver', function () {
var tempDir = path.resolve(__dirname, '../../tmp/tmp');
var testPackage = path.resolve(__dirname, '../../assets/package-svn/repo');
// var testPackageAdmin = path.resolve(__dirname, '../../assets/package-svn/admin');
var testPackageAdmin = path.resolve(__dirname, '../../assets/package-svn/admin');
var originaltags = SvnResolver.tags;
var logger;
@@ -1002,7 +1000,7 @@ else describe('SvnResolver', function () {
it('should guess the name from the path', function () {
var resolver;
resolver = create(helpers.localSource(testPackage));
resolver = create('file://' + testPackage);
expect(resolver.getName()).to.equal('repo');
resolver = create('svn+http://yii.googlecode.com/svn');
@@ -1013,7 +1011,7 @@ else describe('SvnResolver', function () {
describe('.resolve', function () {
it('should export correctly if resolution is a tag', function (next) {
var resolver = create({ source: testPackage, target: '0.0.1' });
var resolver = create({ source: 'file://' + testPackageAdmin, target: '0.0.1' });
resolver.resolve()
.then(function (dir) {
@@ -1029,7 +1027,7 @@ else describe('SvnResolver', function () {
});
it('should export correctly if resolution is a commit', function (next) {
var resolver = create({ source: testPackage, target: 'r1' });
var resolver = create({ source: 'file://' + testPackageAdmin, target: 'r1' });
resolver.resolve()
.then(function (dir) {

View File

@@ -12,22 +12,12 @@ describe('scripts', function () {
var packageName = 'package-zip';
var packageDir = path.join(__dirname, '../assets/' + packageName + '.zip');
// We cannot use pure touch, because Windows
var touch = function (file) {
return 'node -e "var fs = require(\'fs\'); fs.closeSync(fs.openSync(\'' + file + '\', \'w\'));"';
};
// We cannot use pure touch, because Windows
var touchWithPid = function (file) {
return 'node -e "var fs = require(\'fs\'); fs.closeSync(fs.openSync(process.env.BOWER_PID + \'' + file + '\', \'w\'));"';
};
var config = {
cwd: tempDir,
scripts: {
preinstall: touch('preinstall_%'),
postinstall: touch('postinstall_%'),
preuninstall: touch('preuninstall_%')
preinstall: 'touch preinstall_%',
postinstall: 'touch postinstall_%',
preuninstall: 'touch preuninstall_%'
}
};
@@ -122,7 +112,7 @@ describe('scripts', function () {
it('should process scripts with quotes and vars in the cmd properly.', function (next) {
config.scripts.preinstall = touchWithPid(' %');
config.scripts.preinstall = 'touch "$BOWER_PID %"';
bower.commands
.install([packageDir], undefined, config)

View File

@@ -1,5 +1,3 @@
require('chalk').enabled = false;
var Q = require('q');
var path = require('path');
var mkdirp = require('mkdirp');
@@ -7,41 +5,11 @@ var rimraf = require('rimraf');
var uuid = require('node-uuid');
var object = require('mout/object');
var fs = require('fs');
var glob = require('glob');
var os = require('os');
var which = require('which');
var path = require('path');
var proxyquire = require('proxyquire').noCallThru().noPreserveCache();
var cmd = require('../lib/util/cmd');
var object = require('mout/object');
var config = require('../lib/config');
// For better promise errors
Q.longStackSupport = true;
// Those are needed for Travis or not configured git environment
var env = {
'GIT_AUTHOR_DATE': 'Sun Apr 7 22:13:13 2013 +0000',
'GIT_AUTHOR_NAME': 'André Cruz',
'GIT_AUTHOR_EMAIL': 'amdfcruz@gmail.com',
'GIT_COMMITTER_DATE': 'Sun Apr 7 22:13:13 2013 +0000',
'GIT_COMMITTER_NAME': 'André Cruz',
'GIT_COMMITTER_EMAIL': 'amdfcruz@gmail.com',
};
object.mixIn(process.env, env);
var tmpLocation = path.join(
os.tmpdir ? os.tmpdir() : os.tmpDir(),
'bower-tests',
uuid.v4().slice(0, 8)
);
exports.require = function (name, stubs) {
if (stubs) {
return proxyquire(path.join(__dirname, '../', name), stubs);
} else {
return require(path.join(__dirname, '../', name));
}
exports.require = function (name) {
return require(path.join(__dirname, '../', name));
};
// We need to reset cache because tests are reusing temp directories
@@ -50,28 +18,23 @@ beforeEach(function () {
});
after(function () {
rimraf.sync(tmpLocation);
rimraf.sync(path.join(__dirname, 'tmp'));
});
exports.TempDir = (function() {
function TempDir (defaults) {
this.path = path.join(tmpLocation, uuid.v4());
this.defaults = defaults;
function TempDir (defaultFiles) {
this.path = path.join(__dirname, 'tmp/' + uuid.v4());
this.defaultFiles = defaultFiles;
}
TempDir.prototype.create = function (files, defaults) {
TempDir.prototype.prepare = function (files) {
var that = this;
defaults = defaults || this.defaults || {};
files = object.merge(files || {}, defaults);
files = object.merge(files || {}, this.defaultFiles);
this.meta = function(tag) {
if (tag) {
return files[tag]['bower.json'];
} else {
return files['bower.json'];
}
};
rimraf.sync(that.path);
mkdirp.sync(that.path);
if (files) {
object.forOwn(files, function (contents, filepath) {
@@ -88,72 +51,8 @@ exports.TempDir = (function() {
return this;
};
TempDir.prototype.prepare = function (files) {
rimraf.sync(this.path);
mkdirp.sync(this.path);
this.create(files);
return this;
};
// TODO: Rewrite to synchronous form
TempDir.prototype.prepareGit = function (revisions) {
var that = this;
revisions = object.merge(revisions || {}, this.defaults);
rimraf.sync(that.path);
mkdirp.sync(that.path);
var promise = new Q();
object.forOwn(revisions, function (files, tag) {
promise = promise.then(function () {
return that.git('init');
}).then(function () {
that.glob('./!(.git)').map(function (removePath) {
var fullPath = path.join(that.path, removePath);
rimraf.sync(fullPath);
});
that.create(files, {});
}).then(function () {
return that.git('add', '-A');
}).then(function () {
return that.git('commit', '-m"commit"');
}).then(function () {
return that.git('tag', tag);
});
});
return promise;
};
TempDir.prototype.glob = function (pattern) {
return glob.sync(pattern, {
cwd: this.path,
dot: true
});
};
TempDir.prototype.getPath = function (name) {
return path.join(this.path, name);
};
TempDir.prototype.read = function (name) {
return fs.readFileSync(this.getPath(name), 'utf8');
};
TempDir.prototype.readJson = function (name) {
return JSON.parse(this.read(name));
};
TempDir.prototype.git = function () {
var args = Array.prototype.slice.call(arguments);
return cmd('git', args, { cwd: this.path, env: env });
return fs.readFileSync(path.join(this.path, name), 'utf8');
};
TempDir.prototype.exists = function (name) {
@@ -163,139 +62,12 @@ exports.TempDir = (function() {
return TempDir;
})();
exports.expectEvent = function expectEvent(emitter, eventName) {
exports.expectEvent = function (emitter, eventName) {
var deferred = Q.defer();
emitter.once(eventName, function () {
deferred.resolve(arguments);
});
emitter.once('error', function (reason) {
deferred.reject(reason);
});
return deferred.promise;
};
exports.command = function (command, stubs) {
var rawCommand;
var commandStubs = {};
stubs = stubs || {};
var cwd = stubs.cwd;
delete stubs.cwd;
rawCommand = exports.require(
'lib/commands/' + command, stubs
);
commandStubs['./' + command] = function () {
var args = [].slice.call(arguments);
args[rawCommand.length - 1] = object.merge({ cwd: cwd }, args[rawCommand.length - 1] || {});
return rawCommand.apply(null, args);
};
var instance = exports.require(
'lib/commands/index', commandStubs
);
var commandParts = command.split('/');
while (commandParts.length > 0) {
instance = instance[commandParts.shift()];
}
if (!instance) {
throw new Error('Unknown command: ' + command);
}
// TODO: refactor tests, so they can use readOptions directly
instance.readOptions = function (argv) {
argv = ['node', 'bower'].concat(argv);
argv = command.split('/').concat(argv);
return rawCommand.readOptions(argv);
};
return instance;
};
exports.run = function (command, args) {
var logger = command.apply(command, args || []);
// Hack so we can intercept prompring for data
logger.prompt = function(data) {
logger.emit('confirm', data);
};
var promise = exports.expectEvent(logger, 'end');
promise.logger = logger;
return promise;
};
// Captures all stdout and stderr
exports.capture = function(callback) {
var oldStdout = process.stdout.write;
var oldStderr = process.stderr.write;
var stdout = '';
var stderr = '';
process.stdout.write = function(text) {
stdout += text;
};
process.stderr.write = function(text) {
stderr += text;
};
return Q.fcall(callback).then(function() {
process.stdout.write = oldStdout;
process.stderr.write = oldStderr;
return [stdout, stderr];
}).fail(function(e) {
process.stdout.write = oldStdout;
process.stderr.write = oldStderr;
throw e;
});
};
exports.hasSvn = function() {
try {
which.sync('svn');
return true;
} catch (ex) {
return false;
}
};
exports.isWin = function() {
return process.platform === 'win32';
};
exports.localSource = function (localPath) {
localPath = path.normalize(localPath);
if (!exports.isWin()) {
localPath = 'file://' + localPath;
}
return localPath;
};
// Used for example by "svn checkout" and "svn export"
exports.localUrl = function (localPath) {
localPath = path.normalize(localPath);
if (!exports.isWin()) {
localPath = 'file://' + localPath;
} else {
localPath = 'file:///' + localPath;
}
return localPath;
};

View File

@@ -10,23 +10,6 @@ var cmd = require('../lib/util/cmd');
var packages = require('./packages-svn.json');
var nopt = require('nopt');
var isWin = function() {
return process.platform === 'win32';
};
var pathToUrl = function (localPath) {
localPath = path.normalize(localPath);
if (!isWin()) {
localPath = 'file://' + localPath;
} else {
localPath = 'file:///' + localPath;
}
return localPath;
};
var options = nopt({
'force': Boolean
}, {
@@ -39,22 +22,15 @@ var env = {};
mout.object.mixIn(env, process.env);
function ensurePackage(admin, dir) {
var promise = new Q();
var promise;
// If force is specified, delete folder
if (options.force) {
promise = promise.then(function () {
return Q.nfcall(rimraf, admin);
});
promise = promise.then(function () {
return Q.nfcall(rimraf, dir);
});
promise = promise.then(function () {
promise = Q.nfcall(rimraf, dir)
.then(function () {
throw new Error();
});
// Otherwise check if .git is already created
// Otherwise check if .svn is already created
} else {
promise = Q.nfcall(fs.stat, path.join(dir, '.svn'));
}
@@ -64,9 +40,9 @@ function ensurePackage(admin, dir) {
// Create dir
return Q.nfcall(mkdirp, dir)
// Init svn repo
.then(cmd.bind(null, 'svnadmin', ['create', admin], {}))
.then(cmd.bind(null, 'svnadmin', ['create', admin]))
// checkout the repo
.then(cmd.bind(null, 'svn', ['checkout', pathToUrl(admin), dir], {}))
.then(cmd.bind(null, 'svn', ['checkout', 'file://' + admin, dir]))
// create directory structure
.then(cmd.bind(null, 'svn', ['mkdir', 'trunk'], { cwd: dir }))
.then(cmd.bind(null, 'svn', ['mkdir', 'tags'], { cwd: dir }))
@@ -105,7 +81,7 @@ function checkRelease(dir, release) {
function createRelease(admin, dir, release, files) {
// checkout the repo
return cmd('svn', ['checkout', pathToUrl(admin), dir])
return cmd('svn', ['checkout', 'file://' + admin, dir])
// Attempt to delete branch, ignoring the error
.then(function () {
return cmd('svn', ['delete', dir + '/branches/' + release], { cwd: dir })

View File

@@ -1,104 +0,0 @@
var expect = require('chai').expect;
var helpers = require('../helpers');
var multiline = require('multiline').stripIndent;
var JsonRenderer = helpers.require('lib/renderers/JsonRenderer');
var jsonRendererWithPrompt = function (stubs) {
return helpers.require('lib/renderers/JsonRenderer', {
promptly: stubs
});
};
// When cloning on Windows it's possible carrets are used
var normalize = function (string) {
return string.replace(/\r\n|\r/g, '\n');
};
describe('JsonRenderer', function () {
it('logs simple message to stderr', function () {
return helpers.capture(function() {
var renderer = new JsonRenderer();
renderer.log({
id: 'foobar',
message: 'hello world'
});
renderer.end();
}).spread(function(stdout, stderr) {
expect(stderr).to.eq(normalize(multiline(function(){/*
[{
"id": "foobar",
"message": "hello world"
}]
*/})));
});
});
it('logs error message to stderr', function () {
return helpers.capture(function() {
var renderer = new JsonRenderer();
renderer.error({
id: 'foobar',
message: 'hello world',
data: {
foo: 'bar'
},
stacktrace: [
'./foo:23',
'./bar:23'
]
});
}).spread(function(stdout, stderr) {
expect(stderr).to.eq(normalize(multiline(function(){/*
[{
"id": "error",
"data": {
"foo": "bar"
},
"stacktrace": "N/A",
"level": "error",
"message": "hello world"
}]
*/})));
});
});
it('prompts for answer', function () {
var JsonRenderer = jsonRendererWithPrompt({
prompt: function(name, opts, callback) {
callback(null, 'something2');
}
});
var renderer = new JsonRenderer();
return helpers.capture(function() {
return renderer.prompt([
{
type: 'input',
name: 'field',
message: 'Please enter something',
default: 'something'
}
]).then(function(response) {
expect(response.field).to.eq('something2');
renderer.end();
});
}).spread(function(stdout, stderr) {
expect(stderr).to.eq(normalize(multiline(function(){/*
[{
"type": "input",
"name": "field",
"message": "Please enter something",
"default": "something",
"level": "prompt"
}]
*/})));
});
});
});

View File

@@ -1,801 +0,0 @@
// Simulate wide terminal
process.stdout.columns = 130;
var expect = require('chai').expect;
var helpers = require('../helpers');
var multiline = require('multiline').stripIndent;
var StandardRenderer = helpers.require('lib/renderers/StandardRenderer');
describe('StandardRenderer', function () {
it('logs generic simple message', function () {
return helpers.capture(function() {
var renderer = new StandardRenderer();
renderer.log({
id: 'foobar',
message: 'hello world'
});
}).spread(function(stdout, stderr) {
expect(stdout).to.eq(multiline(function(){/*
bower foobar hello world
*/}));
});
});
it('logs simple error', function () {
return helpers.capture(function() {
var renderer = new StandardRenderer();
renderer.error({
code: 'EFOOBAR',
message: 'Hello error'
});
}).spread(function(stdout, stderr) {
expect(stderr).to.eq(multiline(function(){/*
bower EFOOBAR Hello error
*/}));
});
});
it('logs error with details', function () {
return helpers.capture(function() {
var renderer = new StandardRenderer();
renderer.error({
code: 'EFOOBAR',
message: 'Hello error',
details: ' Some awesome details\nMultiline! '
});
}).spread(function(stdout, stderr) {
expect(stderr).to.eq(multiline(function(){/*
bower EFOOBAR Hello error
Additional error details:
Some awesome details
Multiline!
*/}));
});
});
it('logs system details in verbose mode', function () {
return helpers.capture(function() {
var renderer = new StandardRenderer(undefined, { verbose: true });
renderer.error({
code: 'EFOOBAR',
message: 'Hello error',
details: ' Some awesome details\nMultiline! '
});
}).spread(function(stdout, stderr) {
expect(stderr).to.match(new RegExp(multiline(function(){/*
System info:
Bower version: [^\r\n]+
Node version: [^\r\n]+
OS: [^\r\n]+
*/})));
});
});
it('logs stack trace in verbose mode', function () {
return helpers.capture(function() {
var renderer = new StandardRenderer(undefined, { verbose: true });
renderer.error({
code: 'EFOOBAR',
message: 'Hello error',
details: ' Some awesome details\nMultiline! ',
stack: [
'./one.js:1',
'./two.js:2'
]
});
}).spread(function(stdout, stderr) {
expect(stderr).to.string(multiline(function(){/*
Stack trace:
./one.js:1
./two.js:2
*/}));
});
});
it('logs console trace in verbose mode', function () {
return helpers.capture(function() {
var renderer = new StandardRenderer(undefined, { verbose: true });
renderer.error({
code: 'EFOOBAR',
message: 'Hello error',
details: ' Some awesome details\nMultiline! '
});
}).spread(function(stdout, stderr) {
expect(stderr).to.match(new RegExp(multiline(function(){/*
Console trace:
Error
at StandardRenderer.error \(.+?\)
*/})));
});
});
it('outputs checkout command log', function() {
return helpers.capture(function() {
var renderer = new StandardRenderer();
renderer.log({
id: 'checkout',
origin: 'jquery#master',
message: 'foobar'
});
}).spread(function(stdout, stderr) {
expect(stdout).to.equal(multiline(function(){/*
bower checkout jquery#foobar
*/}));
});
});
it('outputs full progress for wide command', function() {
return helpers.capture(function() {
var renderer = new StandardRenderer('install');
renderer.log({
id: 'progress',
origin: 'jquery#master',
message: 'foobar'
});
}).spread(function(stdout, stderr) {
expect(stdout).to.equal(multiline(function(){/*
bower jquery#master progress foobar
*/}));
});
});
it('outputs full progress for narrow command', function() {
return helpers.capture(function() {
var renderer = new StandardRenderer('help');
renderer.log({
id: 'progress',
origin: 'jquery#master',
message: 'foobar'
});
}).spread(function(stdout, stderr) {
expect(stdout).to.equal(multiline(function(){/*
bower progress jquery#master foobar
*/}));
});
});
it('outputs extract log just as progress log', function() {
return helpers.capture(function() {
var renderer = new StandardRenderer('install');
renderer.log({
id: 'extract',
origin: 'jquery#master',
message: 'foobar'
});
}).spread(function(stdout, stderr) {
expect(stdout).to.equal(multiline(function(){/*
bower jquery#master extract foobar
*/}));
});
});
it('outputs incompatible log with suitable package', function() {
return helpers.capture(function() {
var renderer = new StandardRenderer();
renderer.log({
id: 'incompatible',
data: {
resolution: '~0.1.1',
suitable: {
pkgMeta: {
_release: '0.1.2'
},
endpoint: {
name: 'foobar'
}
},
picks: [
{
pkgMeta: {
_release: '0.0.0'
},
endpoint: {
name: 'fizfuz',
target: '~0.0.0'
},
dependants: [
{
pkgMeta: {
_release: 'release1'
},
endpoint: {
name: 'dependant1'
}
},
{
pkgMeta: {
_release: 'release2'
},
endpoint: {
name: 'dependant2'
}
}
]
},
{
endpoint: {
name: 'fizfuz2'
},
dependants: [
{
pkgMeta: {
// no release
},
endpoint: {
name: 'jquery2'
}
}
]
}
]
}
});
}).spread(function(stdout, stderr) {
expect(stdout).to.equal(multiline(function(){/*
Please note that,
dependant1#release1, dependant2#release2 depends on fizfuz#~0.0.0 which resolved to fizfuz#0.0.0
jquery2 depends on fizfuz2#
Resort to using foobar#~0.1.1 which resolved to foobar#0.1.2
Code incompatibilities may occur.
*/}));
});
});
it('outputs solver log without suitable package', function() {
return helpers.capture(function() {
var renderer = new StandardRenderer();
renderer.log({
id: 'solved',
data: {
resolution: '~0.1.1',
picks: [
{
pkgMeta: {
_release: '0.0.0'
},
endpoint: {
name: 'fizfuz',
target: '~0.0.0'
},
dependants: [
{
pkgMeta: {
_release: 'release1'
},
endpoint: {
name: 'dependant1'
}
},
{
pkgMeta: {
_release: 'release2'
},
endpoint: {
name: 'dependant2'
}
}
]
},
{
endpoint: {
name: 'fizfuz2'
},
dependants: [
{
pkgMeta: {
// no release
},
endpoint: {
name: 'jquery2'
}
}
]
}
]
}
});
}).spread(function(stdout, stderr) {
expect(stdout).to.equal(multiline(function(){/*
Unable to find a suitable version for , please choose one:
1) fizfuz#~0.0.0 which resolved to 0.0.0 and is required by dependant1#release1, dependant2#release2
2) fizfuz2# and is required by jquery2
Prefix the choice with ! to persist it to bower.json
*/}));
});
});
it('outputs json log', function() {
return helpers.capture(function() {
var renderer = new StandardRenderer();
renderer.log({
id: 'json',
data: {
json: {
foo: 'bar',
fiz: {
fuz: 'faz'
}
}
}
});
}).spread(function(stdout, stderr) {
expect(stdout).to.equal(multiline(function(){/*
{
foo: 'bar',
fiz: {
fuz: 'faz'
}
}
*/}));
});
});
it('outputs cached entry log', function() {
return helpers.capture(function() {
var renderer = new StandardRenderer('install');
renderer.log({
id: 'cached-entry',
origin: 'origin',
message: 'message'
});
}).spread(function(stdout, stderr) {
expect(stdout).to.equal(multiline(function(){/*
bower origin cached message
*/}));
});
});
it('adjusts whitespace when package id too long', function() {
return helpers.capture(function() {
var renderer = new StandardRenderer('install', {});
renderer.log({
id: 'generic',
origin: 'short-origin',
message: 'message'
});
renderer.log({
id: 'generic',
origin: 'very-very-long-origin-string',
message: 'message'
});
renderer.log({
id: 'generic',
origin: 'short-origin',
message: 'message'
});
}).spread(function(stdout, stderr) {
expect(stdout).to.equal(multiline(function(){/*
bower short-origin generic message
bower very-very-long-origin-string generic message
bower short-origin generic message
*/}));
});
});
it('outputs install command log', function() {
return helpers.capture(function() {
var renderer = new StandardRenderer('install', {
cwd: '/tmp'
});
renderer.end([
{
canonicalDir: '/tmp/components/jquery',
pkgMeta: {
_release: '0.1.2'
},
endpoint: {
name: 'jquery'
}
},
{
canonicalDir: '/tmp/components/jquery',
pkgMeta: {
version: '0.1.2'
},
endpoint: {
name: 'jquery'
}
},
{
canonicalDir: '/tmp/components/jquery',
pkgMeta: {
_release: '0.1.2'
},
endpoint: {
name: 'jquery'
},
missing: true
},
{
canonicalDir: '/tmp/components/jquery',
pkgMeta: {
_release: '0.1.2'
},
endpoint: {
name: 'jquery'
},
different: true
},
{
canonicalDir: '/tmp/components/jquery',
pkgMeta: {
_release: '0.1.2'
},
endpoint: {
name: 'jquery'
},
linked: true
},
{
canonicalDir: '/tmp/components/jquery',
pkgMeta: {
_release: '0.1.2'
},
endpoint: {
name: 'jquery',
target: '~0.1.2'
},
incompatible: true
},
{
canonicalDir: '/tmp/components/jquery',
pkgMeta: {
_release: '0.1.2'
},
endpoint: {
name: 'jquery',
target: '~0.1.2'
},
extraneous: true
},
{
canonicalDir: '/tmp/components/jquery',
pkgMeta: {
_release: '0.1.2'
},
endpoint: {
name: 'jquery',
target: '~0.1.2'
},
update: {
target: '0.1.5',
latest: '0.2.0'
}
},
{
canonicalDir: '/tmp/components/jquery',
pkgMeta: {
_release: '0.1.2'
},
endpoint: {
name: 'jquery'
},
dependencies: {
angular: {
canonicalDir: '/tmp/components/angular',
pkgMeta: {
_release: '0.1.3'
},
endpoint: {
name: 'angular'
}
},
ember: {
canonicalDir: '/tmp/components/ember',
pkgMeta: {
_release: '0.2.3'
},
endpoint: {
name: 'ember'
},
dependencies: {
// Should be ingored (only one level)
react: {
canonicalDir: '/tmp/components/react',
pkgMeta: {
_release: '0.2.3'
},
endpoint: {
name: 'react'
}
}
}
}
}
}
]);
}).spread(function(stdout, stderr) {
if (helpers.isWin()) {
expect(stdout).to.equal(multiline(function(){/*
jquery#0.1.2 components\jquery
jquery#0.1.2 components\jquery
jquery components\jquery not installed
jquery#0.1.2 components\jquery different
jquery#0.1.2 components\jquery linked
jquery#0.1.2 components\jquery incompatible with ~0.1.2
jquery#0.1.2 components\jquery extraneous
jquery#0.1.2 components\jquery (0.1.5 available, latest is 0.2.0)
jquery#0.1.2 components\jquery
├── angular#0.1.3
└── ember#0.2.3
*/}));
} else {
expect(stdout).to.equal(multiline(function(){/*
jquery#0.1.2 components/jquery
jquery#0.1.2 components/jquery
jquery components/jquery not installed
jquery#0.1.2 components/jquery different
jquery#0.1.2 components/jquery linked
jquery#0.1.2 components/jquery incompatible with ~0.1.2
jquery#0.1.2 components/jquery extraneous
jquery#0.1.2 components/jquery (0.1.5 available, latest is 0.2.0)
jquery#0.1.2 components/jquery
├── angular#0.1.3
└── ember#0.2.3
*/}));
}
});
});
it('outputs short info command log', function() {
return helpers.capture(function() {
var renderer = new StandardRenderer('info', {});
renderer.end({
version: '1.2.3'
});
}).spread(function(stdout, stderr) {
expect(stdout).to.equal(multiline(function(){/*
{
version: '1.2.3'
}
*/}));
});
});
it('outputs full info command log', function() {
return helpers.capture(function() {
var renderer = new StandardRenderer('info', {});
renderer.end({
name: 'foo',
latest: {
version: '1.2.3'
},
versions: [
'1.2.0',
'1.2.1',
'1.2.2'
]
});
}).spread(function(stdout, stderr) {
expect(stdout).to.equal(multiline(function(){/*
{
version: '1.2.3'
}
Available versions:
- 1.2.0
- 1.2.1
- 1.2.2
You can request info for a specific version with 'bower info foo#<version>'
*/}));
});
});
it('outputs lookup command log', function() {
return helpers.capture(function() {
var renderer = new StandardRenderer('lookup', {});
renderer.end({
name: 'bower',
url: 'http://bower.io'
});
renderer.end({
name: 'bower'
});
}).spread(function(stdout, stderr) {
expect(stdout).to.equal(multiline(function(){/*
bower http://bower.io
Package not found.
*/}));
});
});
it('outputs link command log', function() {
return helpers.capture(function() {
var renderer = new StandardRenderer('link', { cwd: '/tmp' });
renderer.end({
src: './foo',
dst: './bar',
installed: [{
canonicalDir: '/tmp/components/jquery',
pkgMeta: {
_release: '0.1.2'
},
endpoint: {
name: 'jquery'
}
}]
});
}).spread(function(stdout, stderr) {
if (helpers.isWin()) {
expect(stdout).to.equal(multiline(function(){/*
bower link ./bar > ./foo
jquery#0.1.2 components\jquery
*/}));
} else {
expect(stdout).to.equal(multiline(function(){/*
bower link ./bar > ./foo
jquery#0.1.2 components/jquery
*/}));
}
});
});
it('outputs search command log', function() {
return helpers.capture(function() {
var renderer = new StandardRenderer('search');
renderer.end([
{
name: 'jquery',
url: 'http://jquery.io'
},
{
name: 'bower',
url: 'http://bower.io'
}
]);
}).spread(function(stdout, stderr) {
expect(stdout).to.equal(multiline(function(){/*
Search results:
jquery http://jquery.io
bower http://bower.io
*/}));
});
});
it('outputs register command log', function() {
return helpers.capture(function() {
var renderer = new StandardRenderer('register');
renderer.end({
name: 'jquery',
url: 'http://jquery.io'
});
}).spread(function(stdout, stderr) {
expect(stdout).to.equal(multiline(function(){/*
Package jquery registered successfully!
All valid semver tags on http://jquery.io will be available as versions.
To publish a new version, just release a valid semver tag.
Run bower info jquery to list the available versions.
*/}));
});
});
it('outputs cache list command log', function() {
return helpers.capture(function() {
var renderer = new StandardRenderer('cache list');
renderer.end([
{
pkgMeta: {
name: 'awesome-jquery',
_target: '0.1.1',
_source: 'jquery'
}
}
]);
}).spread(function(stdout, stderr) {
expect(stdout).to.equal(multiline(function(){/*
awesome-jquery=jquery#0.1.1
*/}));
});
});
it('outputs help command log', function() {
return helpers.capture(function() {
var renderer = new StandardRenderer('help');
renderer.end({
'command': 'uninstall',
'description': 'Uninstalls a package locally from your bower_components directory',
'usage': [
'uninstall <name> [<name> ..] [<options>]'
],
'options': [
{
'shorthand': '-h',
'flag': '--help',
'description': 'Show this help message'
},
{
'shorthand': '-S',
'flag': '--save',
'description': 'Remove uninstalled packages from the project\'s bower.json dependencies'
},
{
'shorthand': '-D',
'flag': '--save-dev',
'description': 'Remove uninstalled packages from the project\'s bower.json devDependencies'
}
]
});
}).spread(function(stdout, stderr) {
expect(stdout).to.equal(multiline(function(){/*
Usage:
bower uninstall <name> [<name> ..] [<options>]
Options:
-h, --help Show this help message
-S, --save Remove uninstalled packages from the project's bower.json dependencies
-D, --save-dev Remove uninstalled packages from the project's bower.json devDependencies
Additionally all global options listed in 'bower help' are available
Description:
Uninstalls a package locally from your bower_components directory
*/}));
});
});
});

View File

@@ -1,11 +1,3 @@
var helpers = require('./helpers');
if (!helpers.hasSvn()) {
console.warn('#######################################################');
console.warn('It is recommended you install svn for complete testing!');
console.warn('#######################################################');
}
// Cleanup the uncaughtException added by the tmp module
// It messes with the mocha uncaughtException event to caught errors
// Please note that is the Resolver that calls tmp.setGracefulCleanup()
@@ -26,7 +18,5 @@ require('./core/resolveCache');
require('./core/packageRepository');
require('./core/scripts');
require('./core/Manager');
require('./renderers/StandardRenderer.js');
require('./renderers/JsonRenderer.js');
require('./commands/index.js');
require('./util/index.js');

View File

@@ -0,0 +1,3 @@
{
"name": "package"
}

View File

@@ -0,0 +1 @@
1.0.0

View File

@@ -0,0 +1,3 @@
{
"name": "package"
}

View File

@@ -0,0 +1 @@
1.0.1

View File

@@ -0,0 +1,3 @@
{
"name": "package"
}

View File

@@ -0,0 +1 @@
1.0.0

View File

@@ -1,124 +0,0 @@
var expect = require('expect.js');
var proxyquire = require('proxyquire');
var object = require('mout').object;
describe('analytics', function () {
var mockAnalytics = function(stubs, promptResponse) {
return proxyquire('../../lib/util/analytics', {
insight: function () {
return object.merge(stubs || {}, {
askPermission: function (message, callback) {
callback(undefined, promptResponse);
}
});
}
});
};
describe('#setup', function () {
it('leaves analytics enabled if provided', function () {
return mockAnalytics()
.setup({ analytics: true })
.then(function (enabled) {
expect(enabled).to.be(true);
});
});
it('leaves analytics disabled if provided', function () {
return mockAnalytics()
.setup({ analytics: false })
.then(function (enabled) {
expect(enabled).to.be(false);
});
});
it('disables analytics for non-interactive mode', function () {
return mockAnalytics()
.setup({ interactive: false })
.then(function (enabled) {
expect(enabled).to.be(false);
});
});
it('disables if insight.optOut is true and interactive', function () {
return mockAnalytics({ optOut: true })
.setup({ interactive: true })
.then(function (enabled) {
expect(enabled).to.be(false);
});
});
it('enables if insight.optOut is false and interactive', function () {
return mockAnalytics({ optOut: false })
.setup({ interactive: true })
.then(function (enabled) {
expect(enabled).to.be(true);
});
});
it('disables if insight.optOut is false and non-interactive', function () {
return mockAnalytics({ optOut: false })
.setup({ interactive: false })
.then(function (enabled) {
expect(enabled).to.be(false);
});
});
it('enables if interactive insights return true from prompt', function () {
return mockAnalytics({ optOut: undefined }, true)
.setup({ interactive: true })
.then(function (enabled) {
expect(enabled).to.be(true);
});
});
it('disables if interactive insights return false from prompt', function () {
return mockAnalytics({ optOut: undefined }, false)
.setup({ interactive: true })
.then(function (enabled) {
expect(enabled).to.be(false);
});
});
});
describe('Tracker', function (next) {
it('tracks if analytics = true', function(next) {
var analytics = mockAnalytics({
track: function (arg) {
expect(arg).to.be('foo');
next();
}
});
new analytics.Tracker({ analytics: true }).track('foo');
});
it('does not track if analytics = false', function () {
var analytics = mockAnalytics({
track: function (arg) {
throw new Error();
}
});
expect(function () {
new analytics.Tracker({ analytics: false }).track('foo');
}).to.not.throwError();
});
it('tracks if analytics = undefined and setup returns true', function(next) {
var analytics = mockAnalytics({
track: function (arg) {
expect(arg).to.be('foo');
next();
}
});
analytics
.setup({ analytics: true })
.then(function () {
new analytics.Tracker({}).track('foo');
});
});
});
});

View File

@@ -1,4 +1,3 @@
describe('util', function () {
require('./removeIgnores');
require('./analytics');
});