Permalink
Browse files

Merged patch with new 1.0-wip

  • Loading branch information...
2 parents 906ee4c + 897aa0a commit d0bafe70b7f0d560ba26fa6c6176559be8aab5cb @download13 committed May 14, 2012
View
@@ -16,7 +16,6 @@
, "sub": true
, "white": false
, "indent": 2
- , "whitespace": true
, "asi": true
, "laxbreak": true
, "eqnull": true
@@ -26,4 +25,5 @@
, "proto": true
, "expr": true
, "es5": true
+ , "strict": false
}
View
@@ -4,8 +4,7 @@ node_js:
branches:
only:
- master
+ - 1.0-wip
notifications:
email:
- - dustin@dustindiaz.com
- rod@vagg.org
- - jacob@twitter.com
View
@@ -1,50 +0,0 @@
-/*!
- * 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.
- */
-
-
-/******************************************************************************
- * Wrapper for parsed package.json data. We use __defineGetter__ so you can't
- * change anything but it also allows us to override certain root properties
- * with properties contained within the "ender" object, where they exist.
- */
-
-var overrides = 'ender name dependencies main'.split(' ')
-
- , PackageDescriptor = {
- init: function (json) {
- Object.keys(json).forEach(function(k) {
- this.__defineGetter__(k, overrides.indexOf(k) != -1
- ? function () {
- return typeof json.ender == 'object' ? json.ender[k] : json[k]
- }
- : function () { return json[k] }
- )
- }.bind(this))
- return this
- }
- }
-
-module.exports.create = function (json) {
- return Object.create(PackageDescriptor).init(json)
-}
View
@@ -31,6 +31,10 @@
* expect from this module.
*/
+//TODO: there's a bit too much state being passed around during dep tree
+// construction, probably means it's time to turn it into an object that
+// can hold state within itself, instantiated during each dep tree call.
+
var async = require('async')
, path = require('path')
, packageUtil = require('./package-util')
@@ -124,8 +128,6 @@ var uniquePackages = function (packages) {
)
}
- //TODO: because this is async we can still easily process the same tree part mutliple times
- // need to memoize or something
if (tree[name]) return callback() // already done this part of the tree
async.parallel(
@@ -138,10 +140,10 @@ var uniquePackages = function (packages) {
}
// recursive function, called for each node
- , constructDependencyTreePart = function (parents, tree, packages, callback) {
+ , constructDependencyTreePart = function (memoizedProcessor, parents, tree, packages, callback) {
async.forEach(
packages
- , processPackage.bind(null, parents, tree, constructDependencyTreePart)
+ , memoizedProcessor.bind(null, parents, tree, constructDependencyTreePart.bind(null, memoizedProcessor))
, callback
)
}
@@ -151,14 +153,31 @@ var uniquePackages = function (packages) {
// forEach*() methods below
, constructDependencyTree = function (packages, callback) {
var tree = {}
+
+ // This bit of unfortunate complexity needs some explaination: we have 2 paths in our
+ // dep tree construction, we search ./node_modules/* and we individually search through
+ // the `packages` list--this leads to duplication of directory & package.json reads.
+ // Even though this doesn't lead to a corrupt dep tree, the duplication is overhead
+ // we can do without. The cleanest way is to memoize the processPackage() function and
+ // make sure duplicate calls to it with the same `parents` and `pkg` arguments are
+ // only handled once. This memoized function is passed around, it's only useful for
+ // individual calls to `constructDependencyTree()`.
+ , memoizedProcessor = async.memoize(
+ processPackage
+ , function (parents, _t, _p, pkg) {
+ // just a hash string to match duplicate `parents` and `pkg` arguments
+ return [''].concat(parents.concat([pkg, ''])).join('$$')
+ }
+ )
+
// a special case of the CWD, in case we are in a package to be included, if we
// didn't do this then a plain `ender build` wouldn't work.
// even though this will result in a double-scan of node_modules, processPackage()
// won't allow duplicate scans below that.
, scanRootDirectory = function (callback) {
packageUtil.getDependenciesFromDirectory([], '.', function (err, dependencies) {
if (err) return callback(err) // wrapped in package-utils.js
- constructDependencyTreePart([], tree, dependencies, callback)
+ constructDependencyTreePart(memoizedProcessor, [], tree, dependencies, callback)
})
}
, collectTreeParts = function (part, store) {
@@ -188,7 +207,7 @@ var uniquePackages = function (packages) {
}
async.parallel(
- [ scanRootDirectory, constructDependencyTreePart.bind(null, [], tree, packages) ]
+ [ scanRootDirectory, constructDependencyTreePart.bind(null, memoizedProcessor, [], tree, packages) ]
, function (err) {
if (err) return callback(err) // wrapped in package-util.js
completeTree()
View
@@ -0,0 +1,70 @@
+/*!
+ * 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.
+ */
+
+
+/******************************************************************************
+ * Wrapper for parsed package.json data. Makes a copy of package.json but will
+ * replace root properties where they are duplicated in an "ender" sub-object
+ * or an "overlay->ender" sub-object (as per Packages/1.1)
+ */
+
+var overrides = 'name main ender dependencies devDependencies'.split(' ')
+
+ , isOverride = function (key) {
+ return overrides.indexOf(key) > -1
+ }
+
+ , translate = function (json, newJson, key) {
+ if (typeof newJson[key] != 'undefined') return
+
+ if (isOverride(key)
+ && typeof json.ender == 'object'
+ && typeof json.ender[key] != 'undefined') {
+ newJson[key] = json.ender[key]
+ } else if (isOverride(key)
+ && typeof json.overlay == 'object'
+ && typeof json.overlay.ender == 'object'
+ && typeof json.overlay.ender[key] != 'undefined') {
+ newJson[key] = json.overlay.ender[key]
+ } else {
+ newJson[key] = json[key]
+ }
+ }
+
+ , create = function (json) {
+ var newJson = {}
+ , _trans = translate.bind(null, json, newJson)
+
+ Object.keys(json).forEach(_trans)
+ if (typeof json.ender == 'object') {
+ Object.keys(json.ender).forEach(_trans)
+ }
+ if (typeof json.overlay == 'object' && typeof json.overlay.ender == 'object') {
+ Object.keys(json.overlay.ender).forEach(_trans)
+ }
+
+ return newJson
+ }
+
+module.exports.create = create
View
@@ -33,7 +33,7 @@
var fs = require('fs')
, path = require('path')
, util = require('./util')
- , PackageDescriptor = require('./PackageDescriptor')
+ , PackageDescriptor = require('./package-descriptor')
, JSONParseError = require('./errors').JSONParseError
, FilesystemError = require('./errors').FilesystemError
@@ -113,9 +113,12 @@ var fs = require('fs')
path.exists(dir, function (exists) {
if (!exists) return callback(null, [])
- fs.readdir(dir, function (err) {
+ fs.readdir(dir, function (err, files) {
if (err) return callback(new FilesystemError(err))
- callback.apply(null, arguments)
+ files = files.filter(function(file) {
+ return file !== '.bin'
+ });
+ callback.call(null, err, files)
})
})
}
View
@@ -0,0 +1,80 @@
+/*!
+ * 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.
+ */
+
+/******************************************************************************
+ * Utility functions for source-package.js
+ */
+
+var fs = require('fs')
+ , path = require('path')
+ , async = require('async')
+ , glob = require('glob')
+ , packageUtil = require('./package-util')
+ , FilesystemError = require('./errors').FilesystemError
+
+ , collectFiles = function (root, files, callback) {
+ async.map(
+ files
+ , function (file, callback) {
+ // use glob.Glob because it's easier to stub for tests
+ new glob.Glob(file, { cwd: root, root: root, nomount: true }, function (err, files) {
+ if (err) return callback(new FilesystemError(err))
+ files.sort()
+ callback(null, files)
+ })
+ }
+ , function (err, files) {
+ if (err) return callback(err)
+ // flatten files array
+ files = files.reduce(function (p, c) { return p.concat(c) }, [])
+ callback(null, files)
+ }
+ )
+ }
+
+ // utility to read multiple files in order and append them
+ , loadFiles = function (root, files, callback) {
+ if (!Array.isArray(files)) files = [ files ]
+ if (!files.length || (files.length == 1 && files[0] == 'noop')) return callback()
+
+ collectFiles(root, files, function (err, files) {
+ // read each source file in parallel and assemble them together
+ // in order, async.map() FTW!
+ async.map(
+ files
+ , function (file, callback) {
+ file = path.join(root, file).replace(/(\.js)?$/, '.js')
+ fs.readFile(file, 'utf-8', function (err, contents) {
+ if (err) return callback(new FilesystemError(err))
+ callback(null, { file: file, contents: contents })
+ })
+ }
+ , callback
+ )
+ })
+ }
+
+module.exports = {
+ loadFiles: loadFiles
+}
Oops, something went wrong.

0 comments on commit d0bafe7

Please sign in to comment.