From ff4cd83bf388f4275d51bea3477101702e57f31f Mon Sep 17 00:00:00 2001 From: Josh David Miller Date: Sun, 5 Jan 2014 01:00:03 -0800 Subject: [PATCH 1/2] feat(cli): ngbp-cli is a thin wrapper for ngbp Most of the code here (and all of the logic) has been moved to ngbp proper. The ngbp-cli binary is now only responsible for ensuring that ngbp is installed locally and for calling it. All other logic is upstream to prevent needing to update this very frequently. More information at ngbp@40f3a8fcedd4723447ac9544d115eaffb4aca290. --- bin/ngbp | 294 ++++++++++++++++----------------------------------- package.json | 6 +- 2 files changed, 97 insertions(+), 203 deletions(-) diff --git a/bin/ngbp b/bin/ngbp index 5c6969f..e8f6e85 100755 --- a/bin/ngbp +++ b/bin/ngbp @@ -2,229 +2,121 @@ process.title = 'ngbp'; -var nopt = require('nopt'); -var resolve = require( 'resolve' ).sync; -var path = require( 'path' ); -var fs = require( 'fs' ); -var pkg = require( '../package.json' ); -var spawn = require( 'child_process' ).spawn; - -var basedir = process.cwd(); -var ngbpPath, gruntPath, grunt; - -var optlist = { - help: { - short: 'h', - info: 'Display this help text.', - type: Boolean - }, - version: { - short: 'V', - info: 'Print the grunt version. Combine with --verbose for more info.', - type: Boolean - } -}; - -// Parse `optlist` into a form that nopt can handle. -var aliases = {}; -var known = {}; - -Object.keys(optlist).forEach(function(key) { - var short = optlist[key].short; - if (short) { - aliases[short] = '--' + key; - } - known[key] = optlist[key].type; -}); +// Node.js libs +var READLINE = require( 'readline' ); +var SPAWN = require( 'child_process' ).spawn; -var options = nopt( known, aliases, process.argv, 2 ); -var tasks = options.argv.remain; -delete options.argv; +// 3rd Party Modules +var Q = require( 'q' ); +var COLORS = require( 'colors' ); +var FINDUP = require('findup-sync'); +var RESOLVE = require('resolve').sync; -function version () { - console.log( "ngbp-cli version " + pkg.version ); - process.exit(); -} +// Local libs +var PKG = require( './../package.json' ); -function help () { - console.log( "ngbp-cli help not yet implemented." ); - process.exit(); +function log ( msg ) { + console.log( "[ngbp] " + msg ); } -function fatal ( msg, code ) { +function writeln ( msg ) { console.log( msg ); - process.exit( code || 1 ); } -function init () { - if ( tasks.length <= 1 ) { - fatal( 'You must provide a name for your project.', 91 ); - } +function error ( msg, fatal ) { + msg = "[ngbp] " + msg; + console.log( msg.red ); - if ( fs.existsSync( './Gruntfile.js' ) ) { - fatal( "You already have a gruntfile. This isn't supported yet, so you'll have to modify it manually.", 92 ); + if ( fatal ) { + process.exit( 1 ); } +} - var name = tasks[1]; - console.log( "Creating project '" + name + "'..." ); +function header ( msg ) { + msg = "[ngbp] " + msg; + console.log( msg.underline.magenta ); +} - if ( fs.existsSync( './package.json' ) ) { - var pkg = JSON.parse( fs.readFileSync( './package.json' ) ); - if ( ! pkg.ngbpModules || ! pkg.ngbpModules.length ) { - pkg.ngbpModules = [ "ngbp-contrib-core" ] - } +function installNgbpIfNeeded () { + var deferred = Q.defer(); - if ( ! pkg.devDependencies ) { - pkg.devDependencies = { "ngbp": "~0.4" }; + /** + * Ensure there is a local installation of ngbp. + */ + try { + ngbpPath = RESOLVE( 'ngbp', { basedir: process.cwd() } ); + deferred.resolve( true ); + } catch ( e ) { + error( "Encountered error: " + e ); + ngbpPath = FINDUP( 'lib/ngbp.js' ); + + // No ngbp install found! + if ( ngbpPath ) { + deferred.resolve( true ); } else { - var found = false; - Object.keys( pkg.devDependencies ).forEach( function ( mod ) { - if ( mod === "ngbp" ) { - found = true; - } - }); - - if ( ! found ) { - pkg.devDependencies["ngbp"] = "~0.4"; - } - } + header( "Local ngbp not installed." ); - fs.writeFileSync( './package.json', JSON.stringify( pkg, undefined, " " ) ); - } else { - var pkgfile = [ - '{', - ' "name": "' + name + '",', - ' "version": "0.0.1",', - ' "author": "' + process.env['USER'] + '",', - ' "devDependencies": {', - ' "ngbp": "~0.4",', - ' "ngbp-contrib-clean": "~0.0.1",', - ' "ngbp-contrib-copy": "~0.0.1",', - ' "ngbp-contrib-tpl": "~0.0.1",', - ' "ngbp-contrib-lintjs": "~0.0.1",', - ' "ngbp-contrib-lintcss": "~0.0.1",', - ' "ngbp-contrib-mincss": "~0.0.1",', - ' "ngbp-contrib-minjs": "~0.0.1"', - ' }', - '}' - ].join( "\n" ); - - fs.writeFileSync( './package.json', pkgfile ); - } + // Ensure the user is okay with installing it here. + var rl = READLINE.createInterface({ + input: process.stdin, + output: process.stdout + }); - if ( ! fs.existsSync( './bower.json' ) ) { - var bowerfile = [ - '{', - ' "name": "' + name + '",', - ' "version": "0.0.1",', - '}' - ].join( "\n" ); + rl.question( "Install ngbp in the current directory? [Yn] ", function ( answer ) { + rl.close(); - fs.writeFileSync( './bower.json', bowerfile ); - } + if ( answer && [ 'y', 'Y', 'yes', 'Yes', 'YES' ].indexOf( answer ) === -1 ) { + deferred.reject( "I can't function without a local ngbp installation." ); + return; + } - var change_vendor_dir = false; - if ( fs.existsSync( './.bowerrc' ) ) { - var bower = JSON.parse( fs.readFileSync( './.bowerrc' ) ); - if ( ! bower.directory ) { - change_vendor_dir = 'bower_components'; - } else if ( bower.directory !== 'vendor' ) { - change_vendor_dir = bower.directory; + /** + * This will install ngbp and its dependencies locally, and if there is a `package.json` + * file it will save the requirement to the `devDependencies` array. + */ + var npm = SPAWN( 'npm', [ 'install', '--save-dev', 'ngbp' ], { + cwd: process.cwd() + }); + + npm.stderr.on( 'data', function ( data ) { + if (/^execvp\(\)/.test( data ) ) { + deferred.reject( "Could not start NPM." ); + } + }); + + npm.stdout.pipe( process.stdout ); + npm.stderr.pipe( process.stderr ); + + npm.on( 'close', function ( code ) { + if ( code === 0 ) { + deferred.resolve( true ); + } else { + deferred.reject( "NPM exited with status " + code + "." ); + } + }); + }); } - } else { - change_vendor_dir = 'bower_components'; } - var gruntfile = [ - 'var grunt = require( "grunt" );', - '', - 'module.exports = function ( grunt ) {', - ' grunt.config.init({', - ' pkg: grunt.file.readJSON( "./package.json" )' + ( change_vendor_dir ? ',' : '' ), - '' + ( change_vendor_dir ? ' ngbp: { paths: { vendor: "' + change_vendor_dir + '" } }' : '' ), - ' });', - '', - ' grunt.loadNpmTasks( "ngbp" );', - '};' - ].join( "\n" ); - - fs.writeFileSync( './Gruntfile.js', gruntfile ); - - if ( ! fs.existsSync( './src' ) ) { - fs.mkdirSync( './src' ); - } - - if ( ! fs.existsSync( './src/index.html' ) ) { - var index = [ - '', - '', - ' ', - ' ngbp', - '', - ' <% ngbp.styles.forEach( function ( file ) { %>', - ' <% }); %>', - '', - ' <% ngbp.scripts.forEach( function ( file ) { %>', - ' <% }); %>', - ' ', - ' ', - '

ngbp generated me!

', - ' ', - '' - ].join( "\n" ); - - fs.writeFileSync( './src/index.html', index ); - } - - // run npm install - var npm = spawn( 'npm', [ 'install' ], { - cwd: process.cwd() - }); - - npm.stdout.pipe( process.stdout ); - npm.stderr.pipe( process.stderr ); - - npm.on('close', function ( code ) { - console.log( "New ngbp project created successfully. Happy coding!" ); - process.exit(); - }); + return deferred.promise; } -// Do stuff based on CLI options. -if ( options.version ) { - version(); -} else if ( options.help || tasks.indexOf( 'help' ) >= 0 ) { - help(); -} else if ( tasks.indexOf( 'init' ) >= 0 ) { - init(); -} else { - /** - * Ensure there is a local installation of ngbp. - */ - try { - ngbpPath = resolve( 'ngbp', { basedir: basedir } ); - } catch ( ex ) { - fatal( 'Unable to find local ngbp. Have you run `ngbp init` yet?', 99 ); - } - - /** - * Ensure there is a local installation of grunt, since we'll pass most commands to it. - */ - try { - gruntPath = resolve( 'grunt', { basedir: basedir } ); - grunt = require( gruntPath ); - } catch ( ex ) { - fatal( 'Unable to find local grunt. Have you run `ngbp init` yet?', 99 ); - } - - if ( ! tasks.length ) { - console.log( 'You must provide some command for me to run. Here\'s some help:' ); - help(); - } - - /** - * Just pass the whatever tasks onto grunt, prefixing all of them with 'ngbp:'. - */ - grunt.tasks( tasks.map( function ( t ) { return 'ngbp-'+t; } ), options ); +/** + * Print out the version, if necessary. + */ +if( process.argv.indexOf( '--version' ) !== -1 || process.argv.indexOf( '-V' ) !== -1 ) { + writeln( "ngbp-cli v" + PKG.version ); } +/** + * Ensure that NGBP is installed, then load the CLI. + */ +installNgbpIfNeeded() +.then( function () { + return require( ngbpPath ).cli(); +}) +.catch( function ( err ) { + console.log( err.stack ); + error( "Well, shoot-darn. " + err + " Exiting...", true ); +}); + diff --git a/package.json b/package.json index 3e5ff62..0b09c08 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "ngbp-cli", - "version": "0.0.1-1", + "version": "0.0.1-2", "description": "Command-line interface to ngbp", "homepage": "https://github.com/ngbp/ngbp-cli", "author": { @@ -29,7 +29,9 @@ "peerDependencies": {}, "dependencies": { "resolve": "~0.6.1", - "nopt": "~2.1.2" + "colors": "~0.6.2", + "findup-sync": "~0.1.2", + "q": "~0.9.7" }, "preferGlobal": true, "bin": { From 76f2d49cabc8f56b9074a66b802291790a0fbe0c Mon Sep 17 00:00:00 2001 From: Josh David Miller Date: Wed, 16 Apr 2014 22:45:44 -0700 Subject: [PATCH 2/2] chore(*): Renamed ngbp to warlock --- bin/{ngbp => warlock} | 57 ++++++++++++++++++++++++------------------- package.json | 24 ++++++++---------- 2 files changed, 42 insertions(+), 39 deletions(-) rename bin/{ngbp => warlock} (57%) diff --git a/bin/ngbp b/bin/warlock similarity index 57% rename from bin/ngbp rename to bin/warlock index e8f6e85..f44fbd2 100755 --- a/bin/ngbp +++ b/bin/warlock @@ -1,6 +1,6 @@ #!/usr/bin/env node -process.title = 'ngbp'; +process.title = 'warlock'; // Node.js libs var READLINE = require( 'readline' ); @@ -16,7 +16,7 @@ var RESOLVE = require('resolve').sync; var PKG = require( './../package.json' ); function log ( msg ) { - console.log( "[ngbp] " + msg ); + console.log( "[warlock] " + msg ); } function writeln ( msg ) { @@ -24,7 +24,7 @@ function writeln ( msg ) { } function error ( msg, fatal ) { - msg = "[ngbp] " + msg; + msg = "[warlock] " + msg; console.log( msg.red ); if ( fatal ) { @@ -33,28 +33,28 @@ function error ( msg, fatal ) { } function header ( msg ) { - msg = "[ngbp] " + msg; + msg = "[warlock] " + msg; console.log( msg.underline.magenta ); } -function installNgbpIfNeeded () { +function installWarlockIfNeeded () { var deferred = Q.defer(); /** - * Ensure there is a local installation of ngbp. + * Ensure there is a local installation of warlock. */ try { - ngbpPath = RESOLVE( 'ngbp', { basedir: process.cwd() } ); - deferred.resolve( true ); + warlockPath = RESOLVE( 'warlock', { basedir: process.cwd() } ); + deferred.resolve( warlockPath ); } catch ( e ) { error( "Encountered error: " + e ); - ngbpPath = FINDUP( 'lib/ngbp.js' ); + warlockPath = FINDUP( 'lib/warlock.js' ); - // No ngbp install found! - if ( ngbpPath ) { - deferred.resolve( true ); + // No warlock install found! + if ( warlockPath ) { + deferred.resolve( warlockPath ); } else { - header( "Local ngbp not installed." ); + header( "Local warlock not installed." ); // Ensure the user is okay with installing it here. var rl = READLINE.createInterface({ @@ -62,19 +62,20 @@ function installNgbpIfNeeded () { output: process.stdout }); - rl.question( "Install ngbp in the current directory? [Yn] ", function ( answer ) { + rl.question( "Install warlock in the current directory? [Yn] ", function ( answer ) { rl.close(); if ( answer && [ 'y', 'Y', 'yes', 'Yes', 'YES' ].indexOf( answer ) === -1 ) { - deferred.reject( "I can't function without a local ngbp installation." ); + deferred.reject( "I can't function without a local warlock installation." ); return; } /** - * This will install ngbp and its dependencies locally, and if there is a `package.json` + * This will install warlock and its dependencies locally, and if there is a `package.json` * file it will save the requirement to the `devDependencies` array. */ - var npm = SPAWN( 'npm', [ 'install', '--save-dev', 'ngbp' ], { + var npm = SPAWN( 'npm', [ 'link', '--save-dev', 'warlock' ], { + // var npm = SPAWN( 'npm', [ 'install', '--save-dev', 'warlock' ], { cwd: process.cwd() }); @@ -89,7 +90,7 @@ function installNgbpIfNeeded () { npm.on( 'close', function ( code ) { if ( code === 0 ) { - deferred.resolve( true ); + deferred.resolve( RESOLVE( 'warlock', { basedir: process.cwd() } ) ); } else { deferred.reject( "NPM exited with status " + code + "." ); } @@ -105,18 +106,24 @@ function installNgbpIfNeeded () { * Print out the version, if necessary. */ if( process.argv.indexOf( '--version' ) !== -1 || process.argv.indexOf( '-V' ) !== -1 ) { - writeln( "ngbp-cli v" + PKG.version ); + writeln( "warlock-cli v" + PKG.version ); } /** - * Ensure that NGBP is installed, then load the CLI. + * Ensure that warlock is installed, then load the CLI. */ -installNgbpIfNeeded() -.then( function () { - return require( ngbpPath ).cli(); +installWarlockIfNeeded() +.then( function ( warlockPath ) { + return require( warlockPath ).cli(); }) -.catch( function ( err ) { - console.log( err.stack ); +.done( function () { + // FIXME(jdm): I'm almost certain this shouldn't be necessary... + process.exit(); +}, function ( err ) { + if ( err.stack ) { + console.log( err.stack ); + } + error( "Well, shoot-darn. " + err + " Exiting...", true ); }); diff --git a/package.json b/package.json index 0b09c08..3fd1283 100644 --- a/package.json +++ b/package.json @@ -1,32 +1,28 @@ { - "name": "ngbp-cli", - "version": "0.0.1-2", - "description": "Command-line interface to ngbp", - "homepage": "https://github.com/ngbp/ngbp-cli", + "name": "warlock-cli", + "version": "1.0.0-alpha.1", + "description": "Command-line interface to warlock", + "homepage": "https://github.com/ngbp/warlock-cli", "author": { - "name": "NGBP Team", - "url": "http://ngbp.org" + "name": "Warlock Team", + "url": "http://getwarlock.com" }, "repository": { "type": "git", - "url": "git://github.com/ngbp/ngbp-cli.git" + "url": "git://github.com/ngbp/warlock-cli.git" }, "bugs": { - "url": "https://github.com/ngbp/ngbp-cli" + "url": "https://github.com/ngbp/warlock-cli" }, "licenses": [ { "type": "MIT", - "url": "https://github.com/ngbp/ngbp-cli/blob/master/LICENSE" + "url": "https://github.com/ngbp/warlock-cli/blob/master/LICENSE" } ], "engines": { "node": ">= 0.8.0" }, - "devDependencies": { - "grunt": "*" - }, - "peerDependencies": {}, "dependencies": { "resolve": "~0.6.1", "colors": "~0.6.2", @@ -35,6 +31,6 @@ }, "preferGlobal": true, "bin": { - "ngbp": "bin/ngbp" + "warlock": "bin/warlock" } }