Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with HTTPS or Subversion.

Download ZIP
Browse files

--force-install, use it for `refresh`, update docs

  • Loading branch information...
commit 52be15fb188cc342494201f3d734fa66f01c562f 1 parent 376a44c
@rvagg rvagg authored
View
3  lib/args-parse.js
@@ -82,6 +82,7 @@ var UnknownMainError = require('./errors').UnknownMainError
add('client-lib' , String)
add('level' , String)
add('quiet' , Boolean)
+ add('force-install' , Boolean)
return arr
}())
@@ -92,7 +93,7 @@ var UnknownMainError = require('./errors').UnknownMainError
, 'build' : 'build'
, 'add' : 'add'
, 'set' : 'add'
- , 'refresh' : 'add'
+ , 'refresh' : 'refresh'
, 'remove' : 'remove'
, 'rm' : 'remove'
, 'info' : 'info'
View
24 lib/install.js
@@ -86,7 +86,7 @@ var async = require('async')
})
}
- , recurse = function () {
+ , completeDependenciesInstall = function () {
// keep running installRest() until we have nothing else to install, in theory installedPackages[]
// should stop us from going forever even if npm doesn't do the installing we want
async.whilst(
@@ -102,6 +102,24 @@ var async = require('async')
)
}
+ // if --force-install then explicitly install the root packages whether they exist in
+ // node_modules or not, also used by 'refresh'
+ , installRootPackages = function () {
+ if (options['force-install'] || options['_force-install']) {
+ // 'refresh' uses '_force-install' to signal that it doesn't want a trace left
+ // in the 'Build:' header
+ if (options['_force-install']) delete options['_force-install']
+ repository.install(filteredPackages, function (err, result) {
+ if (err) return callback(err) // wrapped in repository.js
+ results.push(result)
+
+ completeDependenciesInstall()
+ })
+ } else {
+ completeDependenciesInstall()
+ }
+ }
+
// must treat '.' as a special case, partly because of npm (see
// https://github.com/isaacs/npm/commit/8b7bf5ab0c214b739b5fd6af07003cac9e5fc712), and
// partly because of what we need to do with it
@@ -109,7 +127,7 @@ var async = require('async')
repository.install([ '.' ], function (err, result) {
if (err) return callback(err) // wrapped in repository.js
results.push(result)
- recurse()
+ installRootPackages()
})
}
@@ -119,7 +137,7 @@ var async = require('async')
repository.setup(function (err) {
if (err) return callback(err) // wrapped in repository.js
- filteredPackages.length != packages.length ? installCwd() : recurse()
+ filteredPackages.length != packages.length ? installCwd() : installRootPackages()
})
})
}
View
51 lib/main-refresh.js
@@ -0,0 +1,51 @@
+/*!
+ * ENDER - The open module JavaScript framework
+ *
+ * Copyright (c) 2011-2012 @ded, @fat, @rvagg 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 the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is furnished
+ * to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in all
+ * copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ */
+
+
+/******************************************************************************
+ * 'Refresh' executable module, for `ender refresh [--use <file>]`.
+ * This module first parses the build command in the ender.js file in CWD or
+ * the file or the file provided on the --use option.
+ * The build command from the ender.js build is then passed to the Build
+ * module which does all the hard work.
+ */
+
+var util = require('./util')
+ , argsParse = require('./args-parse')
+ , mainBuild = require('./main-build')
+ , mainInfoUtil = require('./main-info-util')
+
+ , exec = function (options, out, callback) {
+ var filename = util.getInputFilenameFromOptions(options)
+ ; delete options.use // don't want --use showing up in the 'Build:' context string
+ mainInfoUtil.parseContext(filename, function (err, context) {
+ if (err) return callback(err) // err wrapped in SourceBuild.parseContext()
+
+ // set --force-install but don't leave a trace in the 'Build:' context string
+ context.options['_force-install'] = true
+ mainBuild.exec(context.options, out, callback)
+ })
+ }
+
+module.exports.exec = exec
View
37 lib/output/main-refresh-output.js
@@ -0,0 +1,37 @@
+/*!
+ * ENDER - The open module JavaScript framework
+ *
+ * Copyright (c) 2011-2012 @ded, @fat, @rvagg 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 the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is furnished
+ * to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in all
+ * copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ */
+
+
+var extend = require('../util').extend
+ , BuildOutput = require('./main-build-output')
+
+ , RefreshOutput = extend(BuildOutput, { // inherit from BuildOutput
+
+ create: function (out, debug, quiet) {
+ return Object.create(this).init(out, debug, quiet)
+ }
+
+ })
+
+module.exports = RefreshOutput
View
7 resources/help/add.tmpl
@@ -1,6 +1,7 @@
{yellow}- add:{/yellow}
- + adds a package to the current ender build
+ + adds a package to the current Ender build
+ example: {cyan}$ ender add underscore backbone{/cyan}
{red}+ options:{/red}
- - {yellow}--use{/yellow} (or {yellow}-u{/yellow}) target a specific ender package (without use, ender defaults to local ender.js or ender.min.js)
- + example: {cyan}$ ender add -u ../public/js/mootools.js{/cyan}
+ - {yellow}--use{/yellow} (or {yellow}-u{/yellow}) target a specific Ender package (without use, Ender defaults to local ender.js or ender.min.js)
+ + example: {cyan}$ ender add -u ../public/js/mootools.js{/cyan}
+ - {yellow}--quiet{/yellow} suppress printing of non-error or warning messages to stdout
View
8 resources/help/build.tmpl
@@ -1,12 +1,14 @@
{yellow}- build:{/yellow}
- + accepts multiple npm packages to build into ender library
+ + accepts multiple npm packages to build into Ender library
+ example: {cyan} $ender build domready qwery bean{/cyan}
+ note: alternatively you can specify the -b flag
{red}+ options:{/red}
- - {yellow}--sandbox{/yellow} Prevents global leakage of ender lib variables. Passing additional arguments will define the specified packages directly on the window.
+ - {yellow}--sandbox{/yellow} prevent global leakage of Ender lib variables, passing additional arguments will define the specified packages directly on the window
+ example: {cyan}$ ender build jeesh backbone --sandbox backbone{/cyan}
- {yellow}--noop{/yellow} (or {yellow}-x{/yellow}) build without the ender-js client library
+ example: {cyan}$ ender build mootools-class --noop{/cyan}
- - {yellow}--output{/yellow} (or {yellow}-o{/yellow}) out ender library to path with custom name
+ - {yellow}--output{/yellow} (or {yellow}-o{/yellow}) write Ender library to path with custom name
+ example: {cyan}$ ender build mootools-class --output ../public/js/mootools.js{/cyan}
+ (above example would generate a mootools.js file as well as a mootools.min.js file in the ../public/js/ dir.)
+ - {yellow}--force-install{/yellow} force a reinstall of packages that may already exist in node_modules, normally Ender will skip install for remote packages that are already in node_modules (packages specified by path are always reinstalled)
+ - {yellow}--quiet{/yellow} suppress printing of non-error or warning messages to stdout
View
7 resources/help/compile.tmpl
@@ -1,14 +1,15 @@
{yellow}- compile:{/yellow}
- + compiles your application with your ender build using the Google Closure Compiler
+ + compiles your application with your Ender build using the Google Closure Compiler
+ supply any additional JavaScript files to be included in the compilation, your ender.js file will also be included
+ your compiled application will be written to ender-app.js
+ example: {cyan}$ ender compile header.js footer.js app.js{/cyan}
{red}+ options:{/red}
- - {yellow}--use{/yellow} (or {yellow}-u{/yellow}) target a specific ender package (without use, ender defaults to local ender.js)
+ - {yellow}--use{/yellow} (or {yellow}-u{/yellow}) target a specific Ender package (without use, Ender defaults to local ender.js)
+ example: {cyan}$ ender compile app.js -u myenderbuild.js{/cyan}
- {yellow}--output{/yellow} (or {yellow}-o{/yellow}) write the compiled file to somewhere other than ender-app.js
+ example: {cyan}$ ender compile app.js -o myapp.js{/cyan}
- {yellow}--externs <file1> [file2...]{/yellow} pass through any externs files to Closure Compiler
+ example: {cyan}$ ender compile header.js footer.js app.js --externs externs1.js externs2.js{/cyan}
- {yellow}--level <simple|advanced|whitespace>{/yellow} pick an optimization level for Closure Compiler (defaults to {yellow}advanced{/yellow})
- + example: {cyan}$ ender compile app.js --level simple{/cyan}
+ + example: {cyan}$ ender compile app.js --level simple{/cyan}
+ - {yellow}--quiet{/yellow} suppress printing of non-error or warning messages to stdout
View
4 resources/help/info.tmpl
@@ -1,7 +1,7 @@
{yellow}- info:{/yellow}
- + gives you the status of the current ender build (including files size and package list)
+ + gives you the status of the current Ender build (including files size and package list)
+ example: {cyan}$ ender info{/cyan}
+ note: alternatively you can specify the {yellow}-i{/yellow} flag ({cyan}$ ender -i underscore backbone{/cyan})
{red}+ options:{/red}
- - {yellow}--use{/yellow} (or {yellow}-u{/yellow}) target a specific ender package (without use, ender defaults to local ender.js or ender.min.js)
+ - {yellow}--use{/yellow} (or {yellow}-u{/yellow}) target a specific Ender package (without use, Ender defaults to local ender.js or ender.min.js)
+ example {cyan}$ ender info -u ../public/js/mootools.js{/cyan}
View
16 resources/help/main.tmpl
@@ -2,29 +2,31 @@
{red}Methods{/red} - for more info on any one method run {cyan}$ ender help method{/cyan}
----------------------------------------------------------------------
{yellow}- build:{/yellow}
- + accepts multiple npm packages to build into ender library
+ + accepts multiple npm packages to build into Ender library
+ example: {cyan}$ ender build domready qwery bean{/cyan}
{yellow}- refresh:{/yellow}
+ refreshes the current build (reinstalls all packages)
+ example: {cyan}$ ender refresh{/cyan}
{yellow}- add:{/yellow}
- + adds a package to the current ender build
+ + adds a package to the current Ender build
+ example: {cyan}$ ender add underscore backbone{/cyan}
{yellow}- remove:{/yellow}
- + removes a package from the current ender build
+ + removes a package from the current Ender build
+ example: {cyan}$ ender remove underscore backbone{/cyan}
{yellow}- info:{/yellow}
- + gives you the status of the current ender build (including files size and package list)
+ + gives you the status of the current Ender build (including files size and package list)
+ example: {cyan}$ ender info{/cyan}
{yellow}- search:{/yellow}
- + searches NPM registry for provided keywords -- bubbles up ender compatible modules
+ + searches NPM registry for provided keywords -- bubbles up Ender compatible modules
+ example: {cyan}$ ender search selector engine{/cyan}
{yellow}- compile:{/yellow}
- + Allows you to compile your application along-side your ender installation using the Google Closure Compiler
+ + Allows you to compile your application along-side your Ender installation using the Google Closure Compiler
+ example: {cyan}$ ender compile header.js app.js footer.js{/cyan}
{red}General Help{/red}
------------
If you get stuck please visit {yellow}http://github.com/ender-js/Ender{/yellow} and file an issue.
-You may also want to consider @messaging {yellow}@ded{/yellow}, {yellow}@rvagg{/yellow} or {yellow}@fat{/yellow} on Twitter directly
+Support can sometimes be found on the #enderjs channel on Freenode IRC.
+
+You may also want to consider @messaging {yellow}@Ender{/yellow} on Twitter.
View
3  resources/help/refresh.tmpl
@@ -3,4 +3,5 @@
+ example: {cyan}$ ender refresh{/cyan}
{red}+ options:{/red}
- {yellow}--use{/yellow} (or {yellow}-u{/yellow}) target a specific ender package (without use, ender defaults to local ender.js or ender.min.js)
- + example: {cyan}$ ender refresh -u ../public/js/mootools.js{/cyan}
+ + example: {cyan}$ ender refresh -u ../public/js/mootools.js{/cyan}
+ - {yellow}--quiet{/yellow} suppress printing of non-error or warning messages to stdout
View
3  resources/help/remove.tmpl
@@ -4,4 +4,5 @@
+ note: alternatively you can specify the {yellow}-d{/yellow} flag ({cyan}$ ender -d underscore backbone{/cyan})
{red}+ options:{/red}
- {yellow}--use{/yellow} (or {yellow}-u{/yellow}) target a specific ender package (without use, ender defaults to local ender.js or ender.min.js)
- + example: {cyan}$ ender remove -u ../public/js/mootools.js{/cyan}
+ + example: {cyan}$ ender remove -u ../public/js/mootools.js{/cyan}
+ - {yellow}--quiet{/yellow} suppress printing of non-error or warning messages to stdout
View
29 test/functional/refresh-test.js
@@ -35,8 +35,9 @@ testCase('Functional: refresh', {
this.timeout = 30000
assert.match.message = '${2}'
- this.runTest = function (use, done) {
+ this.runTest = function (use, rmdir, done) {
var files = [ (use || 'ender') + '.js', (use || 'ender') + '.min.js' ]
+ , firstQweryTs
, testBuild = function (callback, err, dir, fileContents, stdout, stderr) {
refute(err)
refute(stderr)
@@ -80,7 +81,15 @@ testCase('Functional: refresh', {
)
}
, function (dir, callback) {
- rimraf(path.join(dir, 'node_modules'), callback.bind(null, dir))
+ fs.stat(path.join(dir, 'node_modules', 'qwery', 'qwery.js' ), function (err, stat) {
+ if (err) return callback(err)
+ firstQweryTs = stat.ctime
+ callback(null, dir)
+ })
+ }
+ , function (dir, callback) {
+ if (rmdir) rimraf(path.join(dir, 'node_modules'), callback.bind(null, dir))
+ else callback(null, dir)
}
, function (dir, callback) {
functionalCommon.runEnder(
@@ -90,16 +99,28 @@ testCase('Functional: refresh', {
, testBuild.bind(null, callback)
)
}
+ , function (dir, callback) {
+ fs.stat(path.join(dir, 'node_modules', 'qwery', 'qwery.js' ), function (err, stat) {
+ if (err) return callback(err)
+ assert(stat.ctime.getTime() > firstQweryTs.getTime(), 'qwery was reinstalled')
+ callback(null)
+ })
+ }
], done
)
}
}
, '`ender build qwery bean; ender refresh`': function (done) {
- this.runTest(false, done)
+ this.runTest(false, true, done)
}
, '`ender build qwery bean --output foobar; ender refresh --use foobar`': function (done) {
- this.runTest('foobar', done)
+ this.runTest('foobar', true, done)
+ }
+
+ , '`ender build qwery bean; ender refresh` (don\'t clear node_modules)': function (done) {
+ // this is to test that --force-install is used
+ this.runTest(false, false, done)
}
})
View
10 test/unit/args-parse-test.js
@@ -109,7 +109,7 @@ buster.testCase('Args parser', {
, 'test parse returns expected object (-- long form)': function () {
var actual = argsParse.parse(buildargs(
- 'build fee fie foe fum --output foobar --use yeehaw --max 10 --sandbox foo bar --noop --silent --help --sans --debug --externs what tha --client-lib BOOM'
+ 'build fee fie foe fum --output foobar --use yeehaw --max 10 --sandbox foo bar --noop --silent --help --sans --debug --externs what tha --client-lib BOOM --quiet --force-install'
))
assert.equals(
actual
@@ -127,6 +127,8 @@ buster.testCase('Args parser', {
, debug: true
, externs: [ 'what', 'tha' ]
, 'client-lib': 'BOOM'
+ , quiet: true
+ , 'force-install': true
}
)
}
@@ -282,10 +284,10 @@ buster.testCase('Args parser', {
var ctx = argsParse.toContextString(
argsParse.parse(
buildargs(
- 'build fee fie foe fum --output foobar --use yeehaw --max 10 --sandbox foo bar --noop --silent --help --sans --debug --externs what tha --client-lib BOOM'
+ 'build fee fie foe fum --output foobar --use yeehaw --max 10 --sandbox foo bar --noop --silent --help --sans --debug --externs what tha --client-lib BOOM --quiet --force-install'
)))
assert(ctx)
- assert.equals(ctx.split(' ').length, 24)
+ assert.equals(ctx.split(' ').length, 26)
ctx += ' ' // for convenience so we can match spaces around each element, even at the end
assert.match(ctx, /^build fee fie foe fum /)
assert.match(ctx, / --output foobar /)
@@ -299,6 +301,8 @@ buster.testCase('Args parser', {
assert.match(ctx, / --debug /)
assert.match(ctx, / --externs what tha /)
assert.match(ctx, / --client-lib BOOM /)
+ assert.match(ctx, / --quiet /)
+ assert.match(ctx, / --force-install /)
}
}
})
View
50 test/unit/install-test.js
@@ -38,7 +38,7 @@ testCase('Install', {
this.mockDependencyTree = this.mock(DependencyTree)
this.optionsArg = { options: 1 }
- this.packagesArg = { packages: 1, length: 1 }
+ this.packagesArg = [ 'yee', 'haw' ] // length 2
this.mockUtil.expects('mkdir').once().withArgs('node_modules').callsArg(1)
this.mockRepository.expects('setup').once().callsArg(0)
@@ -86,7 +86,7 @@ testCase('Install', {
}
, 'test basic one package install, already available': function (done) {
- var filteredPackagesArg = { filteredPackages: 1, length: 1 }
+ var filteredPackagesArg = { filteredPackages: 1, length: this.packagesArg.length }
, filteredMissingPackagesArg = [] // length 0, nothing to install
, dependencyTreeArg = { dependencyArg : 1 }
, missingDependenciesArg = [ 'missing' ]
@@ -107,7 +107,7 @@ testCase('Install', {
}
, 'test one package install, not available': function (done) {
- var filteredPackagesArg = { filteredPackages: 1, length: 1 }
+ var filteredPackagesArg = { filteredPackages: 1, length: this.packagesArg.length }
, dependencyTreeArg = { dependencyArg : 1 }
, missingDependenciesArg = [ 'missing1' ]
, pathDependenciesArg = [ 'path1' ]
@@ -139,7 +139,7 @@ testCase('Install', {
}
, 'test multi package install, multi install loops required': function (done) {
- var filteredPackagesArg = { filteredPackages: 1, length: 1 }
+ var filteredPackagesArg = { filteredPackages: 1, length: this.packagesArg.length }
, dependencyTreeArg = { dependencyArg : 1 }
, missingDependenciesArg = [ 'missing1' ]
, pathDependenciesArg = [ 'path1' ]
@@ -193,7 +193,7 @@ testCase('Install', {
}
, 'test multi package install, should only install the same package once': function (done) {
- var filteredPackagesArg = { filteredPackages: 1, length: 1 }
+ var filteredPackagesArg = { filteredPackages: 1, length: this.packagesArg.length }
, dependencyTreeArg = { dependencyArg : 1 }
, missingDependenciesArg = [ 'missing1' ]
, pathDependenciesArg = [ 'path1' ]
@@ -248,4 +248,44 @@ testCase('Install', {
done()
})
}
+
+
+ , 'test force-install': function (done) {
+ var filteredPackagesArg = [ 'yee', 'haw' ]
+ , resultArg = { result: 1 }
+ , dependencyTreeArg = { dependencyArg : 1 }
+ , missingDependenciesArg = [ 'missing1' ]
+ , pathDependenciesArg = [ 'path1' ]
+ , filteredMissingPackagesArg = [ 'foo' ] // length 1, install 1 package
+ , resultArg2 = { result: 2 }
+ , dependencyTreeArg2 = { dependencyArg2 : 1 }
+ , missingDependenciesArg2 = [ 'missing2' ]
+ , pathDependenciesArg2 = [ 'path2' ]
+ , filteredMissingPackagesArg2 = [] // length 0, nothing to install
+
+ this.optionsArg = { 'force-install': true }
+ this.packagesArg = [ 'yee', 'haw' ]
+
+ this.expectFilterPackagesWithoutCwd(this.packagesArg, filteredPackagesArg)
+ this.expectRepositoryInstall(filteredPackagesArg, resultArg)
+
+ this.expectGenerate(dependencyTreeArg)
+ this.expectFindMissingDependencies(dependencyTreeArg, missingDependenciesArg)
+ this.expectFindPathDependencies(dependencyTreeArg, pathDependenciesArg)
+ this.expectFilterPackagesWithoutCwd(missingDependenciesArg.concat(pathDependenciesArg), filteredMissingPackagesArg)
+ this.expectRepositoryInstall(filteredMissingPackagesArg, resultArg2)
+
+ this.expectGenerate(dependencyTreeArg2)
+ this.expectFindMissingDependencies(dependencyTreeArg2, missingDependenciesArg2)
+ this.expectFindPathDependencies(dependencyTreeArg2, pathDependenciesArg2)
+ this.expectFilterPackagesWithoutCwd(missingDependenciesArg2.concat(pathDependenciesArg2), filteredMissingPackagesArg2)
+
+ install.installPackages(this.optionsArg, this.packagesArg, function (err, results, dependencyTree) {
+ refute(err)
+ assert.equals(results, [ resultArg, resultArg2 ])
+ assert.same(dependencyTree, dependencyTreeArg2)
+ done()
+ })
+ }
+
})
Please sign in to comment.
Something went wrong with that request. Please try again.