diff options
Diffstat (limited to 'deps/npm/node_modules')
81 files changed, 3263 insertions, 418 deletions
diff --git a/deps/npm/node_modules/glob/glob.js b/deps/npm/node_modules/glob/glob.js index 7903be18f..f646c4483 100644 --- a/deps/npm/node_modules/glob/glob.js +++ b/deps/npm/node_modules/glob/glob.js @@ -76,6 +76,7 @@ function globSync (pattern, options) { return glob(pattern, options) } +this._processingEmitQueue = false glob.Glob = Glob inherits(Glob, EE) @@ -98,9 +99,13 @@ function Glob (pattern, options, cb) { options = options || {} + this._endEmitted = false this.EOF = {} this._emitQueue = [] + this.paused = false + this._processingEmitQueue = false + this.maxDepth = options.maxDepth || 1000 this.maxLength = options.maxLength || Infinity this.cache = options.cache || {} @@ -216,19 +221,7 @@ Glob.prototype._finish = function () { if (this.mark) { // at *some* point we statted all of these - all = all.map(function (m) { - var sc = this.cache[m] - if (!sc) - return m - var isDir = (Array.isArray(sc) || sc === 2) - if (isDir && m.slice(-1) !== "/") { - return m + "/" - } - if (!isDir && m.slice(-1) === "/") { - return m.replace(/\/+$/, "") - } - return m - }, this) + all = all.map(this._mark, this) } this.log("emitting end", all) @@ -247,6 +240,27 @@ function alphasort (a, b) { return a > b ? 1 : a < b ? -1 : 0 } +Glob.prototype._mark = function (p) { + var c = this.cache[p] + var m = p + if (c) { + var isDir = c === 2 || Array.isArray(c) + var slash = p.slice(-1) === '/' + + if (isDir && !slash) + m += '/' + else if (!isDir && slash) + m = m.slice(0, -1) + + if (m !== p) { + this.statCache[m] = this.statCache[p] + this.cache[m] = this.cache[p] + } + } + + return m +} + Glob.prototype.abort = function () { this.aborted = true this.emit("abort") @@ -271,34 +285,68 @@ Glob.prototype.resume = function () { } Glob.prototype.emitMatch = function (m) { - if (!this.stat || this.statCache[m] || m === this.EOF) { - this._emitQueue.push(m) - this._processEmitQueue() - } else { - this._stat(m, function(exists, isDir) { - if (exists) { - this._emitQueue.push(m) - this._processEmitQueue() - } - }) - } + this.log('emitMatch', m) + this._emitQueue.push(m) + this._processEmitQueue() } Glob.prototype._processEmitQueue = function (m) { + this.log("pEQ paused=%j processing=%j m=%j", this.paused, + this._processingEmitQueue, m) + var done = false while (!this._processingEmitQueue && !this.paused) { this._processingEmitQueue = true var m = this._emitQueue.shift() + this.log(">processEmitQueue", m === this.EOF ? ":EOF:" : m) if (!m) { + this.log(">processEmitQueue, falsey m") this._processingEmitQueue = false break } - this.log('emit!', m === this.EOF ? "end" : "match") + if (m === this.EOF || !(this.mark && !this.stat)) { + this.log("peq: unmarked, or eof") + next.call(this, 0, false) + } else if (this.statCache[m]) { + var sc = this.statCache[m] + var exists + if (sc) + exists = sc.isDirectory() ? 2 : 1 + this.log("peq: stat cached") + next.call(this, exists, exists === 2) + } else { + this.log("peq: _stat, then next") + this._stat(m, next) + } + + function next(exists, isDir) { + this.log("next", m, exists, isDir) + var ev = m === this.EOF ? "end" : "match" + + // "end" can only happen once. + assert(!this._endEmitted) + if (ev === "end") + this._endEmitted = true - this.emit(m === this.EOF ? "end" : "match", m) - this._processingEmitQueue = false + if (exists) { + // Doesn't mean it necessarily doesn't exist, it's possible + // we just didn't check because we don't care that much, or + // this is EOF anyway. + if (isDir && !m.match(/\/$/)) { + m = m + "/" + } else if (!isDir && m.match(/\/$/)) { + m = m.replace(/\/+$/, "") + } + } + this.log("emit", ev, m) + this.emit(ev, m) + this._processingEmitQueue = false + if (done && m !== this.EOF && !this.paused) + this._processEmitQueue() + } } + done = true } Glob.prototype._process = function (pattern, depth, index, cb_) { diff --git a/deps/npm/node_modules/glob/package.json b/deps/npm/node_modules/glob/package.json index 59b75afe3..71f32cd49 100644 --- a/deps/npm/node_modules/glob/package.json +++ b/deps/npm/node_modules/glob/package.json @@ -6,7 +6,7 @@ }, "name": "glob", "description": "a little globber", - "version": "3.2.7", + "version": "3.2.9", "repository": { "type": "git", "url": "git://github.com/isaacs/node-glob.git" @@ -25,7 +25,8 @@ "rimraf": "1" }, "scripts": { - "test": "tap test/*.js" + "test": "tap test/*.js", + "test-regen": "TEST_REGEN=1 node test/00-setup.js" }, "license": "BSD", "readme": "# Glob\n\nMatch files using the patterns the shell uses, like stars and stuff.\n\nThis is a glob implementation in JavaScript. It uses the `minimatch`\nlibrary to do its matching.\n\n## Attention: node-glob users!\n\nThe API has changed dramatically between 2.x and 3.x. This library is\nnow 100% JavaScript, and the integer flags have been replaced with an\noptions object.\n\nAlso, there's an event emitter class, proper tests, and all the other\nthings you've come to expect from node modules.\n\nAnd best of all, no compilation!\n\n## Usage\n\n```javascript\nvar glob = require(\"glob\")\n\n// options is optional\nglob(\"**/*.js\", options, function (er, files) {\n // files is an array of filenames.\n // If the `nonull` option is set, and nothing\n // was found, then files is [\"**/*.js\"]\n // er is an error object or null.\n})\n```\n\n## Features\n\nPlease see the [minimatch\ndocumentation](https://github.com/isaacs/minimatch) for more details.\n\nSupports these glob features:\n\n* Brace Expansion\n* Extended glob matching\n* \"Globstar\" `**` matching\n\nSee:\n\n* `man sh`\n* `man bash`\n* `man 3 fnmatch`\n* `man 5 gitignore`\n* [minimatch documentation](https://github.com/isaacs/minimatch)\n\n## glob(pattern, [options], cb)\n\n* `pattern` {String} Pattern to be matched\n* `options` {Object}\n* `cb` {Function}\n * `err` {Error | null}\n * `matches` {Array<String>} filenames found matching the pattern\n\nPerform an asynchronous glob search.\n\n## glob.sync(pattern, [options])\n\n* `pattern` {String} Pattern to be matched\n* `options` {Object}\n* return: {Array<String>} filenames found matching the pattern\n\nPerform a synchronous glob search.\n\n## Class: glob.Glob\n\nCreate a Glob object by instanting the `glob.Glob` class.\n\n```javascript\nvar Glob = require(\"glob\").Glob\nvar mg = new Glob(pattern, options, cb)\n```\n\nIt's an EventEmitter, and starts walking the filesystem to find matches\nimmediately.\n\n### new glob.Glob(pattern, [options], [cb])\n\n* `pattern` {String} pattern to search for\n* `options` {Object}\n* `cb` {Function} Called when an error occurs, or matches are found\n * `err` {Error | null}\n * `matches` {Array<String>} filenames found matching the pattern\n\nNote that if the `sync` flag is set in the options, then matches will\nbe immediately available on the `g.found` member.\n\n### Properties\n\n* `minimatch` The minimatch object that the glob uses.\n* `options` The options object passed in.\n* `error` The error encountered. When an error is encountered, the\n glob object is in an undefined state, and should be discarded.\n* `aborted` Boolean which is set to true when calling `abort()`. There\n is no way at this time to continue a glob search after aborting, but\n you can re-use the statCache to avoid having to duplicate syscalls.\n* `statCache` Collection of all the stat results the glob search\n performed.\n* `cache` Convenience object. Each field has the following possible\n values:\n * `false` - Path does not exist\n * `true` - Path exists\n * `1` - Path exists, and is not a directory\n * `2` - Path exists, and is a directory\n * `[file, entries, ...]` - Path exists, is a directory, and the\n array value is the results of `fs.readdir`\n\n### Events\n\n* `end` When the matching is finished, this is emitted with all the\n matches found. If the `nonull` option is set, and no match was found,\n then the `matches` list contains the original pattern. The matches\n are sorted, unless the `nosort` flag is set.\n* `match` Every time a match is found, this is emitted with the matched.\n* `error` Emitted when an unexpected error is encountered, or whenever\n any fs error occurs if `options.strict` is set.\n* `abort` When `abort()` is called, this event is raised.\n\n### Methods\n\n* `abort` Stop the search.\n\n### Options\n\nAll the options that can be passed to Minimatch can also be passed to\nGlob to change pattern matching behavior. Also, some have been added,\nor have glob-specific ramifications.\n\nAll options are false by default, unless otherwise noted.\n\nAll options are added to the glob object, as well.\n\n* `cwd` The current working directory in which to search. Defaults\n to `process.cwd()`.\n* `root` The place where patterns starting with `/` will be mounted\n onto. Defaults to `path.resolve(options.cwd, \"/\")` (`/` on Unix\n systems, and `C:\\` or some such on Windows.)\n* `dot` Include `.dot` files in normal matches and `globstar` matches.\n Note that an explicit dot in a portion of the pattern will always\n match dot files.\n* `nomount` By default, a pattern starting with a forward-slash will be\n \"mounted\" onto the root setting, so that a valid filesystem path is\n returned. Set this flag to disable that behavior.\n* `mark` Add a `/` character to directory matches. Note that this\n requires additional stat calls.\n* `nosort` Don't sort the results.\n* `stat` Set to true to stat *all* results. This reduces performance\n somewhat, and is completely unnecessary, unless `readdir` is presumed\n to be an untrustworthy indicator of file existence. It will cause\n ELOOP to be triggered one level sooner in the case of cyclical\n symbolic links.\n* `silent` When an unusual error is encountered\n when attempting to read a directory, a warning will be printed to\n stderr. Set the `silent` option to true to suppress these warnings.\n* `strict` When an unusual error is encountered\n when attempting to read a directory, the process will just continue on\n in search of other matches. Set the `strict` option to raise an error\n in these cases.\n* `cache` See `cache` property above. Pass in a previously generated\n cache object to save some fs calls.\n* `statCache` A cache of results of filesystem information, to prevent\n unnecessary stat calls. While it should not normally be necessary to\n set this, you may pass the statCache from one glob() call to the\n options object of another, if you know that the filesystem will not\n change between calls. (See \"Race Conditions\" below.)\n* `sync` Perform a synchronous glob search.\n* `nounique` In some cases, brace-expanded patterns can result in the\n same file showing up multiple times in the result set. By default,\n this implementation prevents duplicates in the result set.\n Set this flag to disable that behavior.\n* `nonull` Set to never return an empty set, instead returning a set\n containing the pattern itself. This is the default in glob(3).\n* `nocase` Perform a case-insensitive match. Note that case-insensitive\n filesystems will sometimes result in glob returning results that are\n case-insensitively matched anyway, since readdir and stat will not\n raise an error.\n* `debug` Set to enable debug logging in minimatch and glob.\n* `globDebug` Set to enable debug logging in glob, but not minimatch.\n\n## Comparisons to other fnmatch/glob implementations\n\nWhile strict compliance with the existing standards is a worthwhile\ngoal, some discrepancies exist between node-glob and other\nimplementations, and are intentional.\n\nIf the pattern starts with a `!` character, then it is negated. Set the\n`nonegate` flag to suppress this behavior, and treat leading `!`\ncharacters normally. This is perhaps relevant if you wish to start the\npattern with a negative extglob pattern like `!(a|B)`. Multiple `!`\ncharacters at the start of a pattern will negate the pattern multiple\ntimes.\n\nIf a pattern starts with `#`, then it is treated as a comment, and\nwill not match anything. Use `\\#` to match a literal `#` at the\nstart of a line, or set the `nocomment` flag to suppress this behavior.\n\nThe double-star character `**` is supported by default, unless the\n`noglobstar` flag is set. This is supported in the manner of bsdglob\nand bash 4.1, where `**` only has special significance if it is the only\nthing in a path part. That is, `a/**/b` will match `a/x/y/b`, but\n`a/**b` will not.\n\nIf an escaped pattern has no matches, and the `nonull` flag is set,\nthen glob returns the pattern as-provided, rather than\ninterpreting the character escapes. For example,\n`glob.match([], \"\\\\*a\\\\?\")` will return `\"\\\\*a\\\\?\"` rather than\n`\"*a?\"`. This is akin to setting the `nullglob` option in bash, except\nthat it does not resolve escaped pattern characters.\n\nIf brace expansion is not disabled, then it is performed before any\nother interpretation of the glob pattern. Thus, a pattern like\n`+(a|{b),c)}`, which would not be valid in bash or zsh, is expanded\n**first** into the set of `+(a|b)` and `+(a|c)`, and those patterns are\nchecked for validity. Since those two are valid, matching proceeds.\n\n## Windows\n\n**Please only use forward-slashes in glob expressions.**\n\nThough windows uses either `/` or `\\` as its path separator, only `/`\ncharacters are used by this glob implementation. You must use\nforward-slashes **only** in glob expressions. Back-slashes will always\nbe interpreted as escape characters, not path separators.\n\nResults from absolute patterns such as `/foo/*` are mounted onto the\nroot setting using `path.join`. On windows, this will by default result\nin `/foo/*` matching `C:\\foo\\bar.txt`.\n\n## Race Conditions\n\nGlob searching, by its very nature, is susceptible to race conditions,\nsince it relies on directory walking and such.\n\nAs a result, it is possible that a file that exists when glob looks for\nit may have been deleted or modified by the time it returns the result.\n\nAs part of its internal implementation, this program caches all stat\nand readdir calls that it makes, in order to cut down on system\noverhead. However, this also makes it even more susceptible to races,\nespecially if the cache or statCache objects are reused between glob\ncalls.\n\nUsers are thus advised not to use a glob result as a guarantee of\nfilesystem state in the face of rapid changes. For the vast majority\nof operations, this is never a problem.\n", @@ -34,6 +35,6 @@ "url": "https://github.com/isaacs/node-glob/issues" }, "homepage": "https://github.com/isaacs/node-glob", - "_id": "glob@3.2.7", - "_from": "glob@3.2.7" + "_id": "glob@3.2.9", + "_from": "glob@latest" } diff --git a/deps/npm/node_modules/glob/test/bash-results.json b/deps/npm/node_modules/glob/test/bash-results.json index 593215cd9..8051c7238 100644 --- a/deps/npm/node_modules/glob/test/bash-results.json +++ b/deps/npm/node_modules/glob/test/bash-results.json @@ -298,6 +298,7 @@ "./test/new-glob-optional-options.js", "./test/nocase-nomagic.js", "./test/pause-resume.js", + "./test/readme-issue.js", "./test/root-nomount.js", "./test/root.js", "./test/stat.js", diff --git a/deps/npm/node_modules/glob/test/mark.js b/deps/npm/node_modules/glob/test/mark.js index ed68a335c..bf411c0e5 100644 --- a/deps/npm/node_modules/glob/test/mark.js +++ b/deps/npm/node_modules/glob/test/mark.js @@ -2,6 +2,42 @@ var test = require("tap").test var glob = require('../') process.chdir(__dirname) +// expose timing issues +var lag = 5 +glob.Glob.prototype._stat = function(o) { return function(f, cb) { + var args = arguments + setTimeout(function() { + o.call(this, f, cb) + }.bind(this), lag += 5) +}}(glob.Glob.prototype._stat) + + +test("mark, with **", function (t) { + glob("a/*b*/**", {mark: true}, function (er, results) { + if (er) + throw er + var expect = + [ 'a/abcdef/', + 'a/abcdef/g/', + 'a/abcdef/g/h', + 'a/abcfed/', + 'a/abcfed/g/', + 'a/abcfed/g/h', + 'a/b/', + 'a/b/c/', + 'a/b/c/d', + 'a/bc/', + 'a/bc/e/', + 'a/bc/e/f', + 'a/cb/', + 'a/cb/e/', + 'a/cb/e/f' ] + + t.same(results, expect) + t.end() + }) +}) + test("mark, no / on pattern", function (t) { glob("a/*", {mark: true}, function (er, results) { if (er) @@ -18,6 +54,8 @@ test("mark, no / on pattern", function (t) { t.same(results, expect) t.end() + }).on('match', function(m) { + t.similar(m, /\/$/) }) }) @@ -36,6 +74,8 @@ test("mark=false, no / on pattern", function (t) { expect.push('a/symlink') t.same(results, expect) t.end() + }).on('match', function(m) { + t.similar(m, /[^\/]$/) }) }) @@ -53,6 +93,8 @@ test("mark=true, / on pattern", function (t) { expect.push('a/symlink/') t.same(results, expect) t.end() + }).on('match', function(m) { + t.similar(m, /\/$/) }) }) @@ -70,5 +112,7 @@ test("mark=false, / on pattern", function (t) { expect.push('a/symlink/') t.same(results, expect) t.end() + }).on('match', function(m) { + t.similar(m, /\/$/) }) }) diff --git a/deps/npm/node_modules/glob/test/readme-issue.js b/deps/npm/node_modules/glob/test/readme-issue.js new file mode 100644 index 000000000..0b4e0be29 --- /dev/null +++ b/deps/npm/node_modules/glob/test/readme-issue.js @@ -0,0 +1,36 @@ +var test = require("tap").test +var glob = require("../") + +var mkdirp = require("mkdirp") +var fs = require("fs") +var rimraf = require("rimraf") +var dir = __dirname + "/package" + +test("setup", function (t) { + mkdirp.sync(dir) + fs.writeFileSync(dir + "/package.json", "{}", "ascii") + fs.writeFileSync(dir + "/README", "x", "ascii") + t.pass("setup done") + t.end() +}) + +test("glob", function (t) { + var opt = { + cwd: dir, + nocase: true, + mark: true + } + + glob("README?(.*)", opt, function (er, files) { + if (er) + throw er + t.same(files, ["README"]) + t.end() + }) +}) + +test("cleanup", function (t) { + rimraf.sync(dir) + t.pass("clean") + t.end() +}) diff --git a/deps/npm/node_modules/init-package-json/LICENSE b/deps/npm/node_modules/init-package-json/LICENSE new file mode 100644 index 000000000..05eeeb88c --- /dev/null +++ b/deps/npm/node_modules/init-package-json/LICENSE @@ -0,0 +1,15 @@ +The ISC License + +Copyright (c) Isaac Z. Schlueter + +Permission to use, copy, modify, and/or distribute this software for any +purpose with or without fee is hereby granted, provided that the above +copyright notice and this permission notice appear in all copies. + +THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES +WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF +MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR +ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES +WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN +ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR +IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. diff --git a/deps/npm/node_modules/init-package-json/default-input.js b/deps/npm/node_modules/init-package-json/default-input.js index b4c01a2dc..d61a33d23 100644 --- a/deps/npm/node_modules/init-package-json/default-input.js +++ b/deps/npm/node_modules/init-package-json/default-input.js @@ -28,7 +28,7 @@ function readDeps (test) { return function (cb) { try { p = JSON.parse(p) } catch (e) { return next() } if (!p.version) return next() - deps[d] = '~' + p.version + deps[d] = '^' + p.version return next() }) }) diff --git a/deps/npm/node_modules/init-package-json/node_modules/promzard/package.json b/deps/npm/node_modules/init-package-json/node_modules/promzard/package.json index 24560a076..17ed9a1f9 100644 --- a/deps/npm/node_modules/init-package-json/node_modules/promzard/package.json +++ b/deps/npm/node_modules/init-package-json/node_modules/promzard/package.json @@ -28,5 +28,9 @@ }, "homepage": "https://github.com/isaacs/promzard", "_id": "promzard@0.2.1", - "_from": "promzard@~0.2.0" + "dist": { + "shasum": "c4c7cbe5182465c13b43540be9daf47098b4e75b" + }, + "_from": "promzard@~0.2.0", + "_resolved": "https://registry.npmjs.org/promzard/-/promzard-0.2.1.tgz" } diff --git a/deps/npm/node_modules/init-package-json/package.json b/deps/npm/node_modules/init-package-json/package.json index bde89be59..95099e09d 100644 --- a/deps/npm/node_modules/init-package-json/package.json +++ b/deps/npm/node_modules/init-package-json/package.json @@ -1,6 +1,6 @@ { "name": "init-package-json", - "version": "0.0.14", + "version": "0.0.15", "main": "init-package-json.js", "scripts": { "test": "tap test/*.js" @@ -14,7 +14,7 @@ "email": "i@izs.me", "url": "http://blog.izs.me/" }, - "license": "BSD", + "license": "ISC", "description": "A node module to get your node module started", "dependencies": { "promzard": "~0.2.0", @@ -43,6 +43,10 @@ "url": "https://github.com/isaacs/init-package-json/issues" }, "homepage": "https://github.com/isaacs/init-package-json", - "_id": "init-package-json@0.0.14", - "_from": "init-package-json@latest" + "_id": "init-package-json@0.0.15", + "dist": { + "shasum": "d40f0201e4de6aa2b3fdc4208ae162766703ebed" + }, + "_from": "init-package-json@latest", + "_resolved": "https://registry.npmjs.org/init-package-json/-/init-package-json-0.0.15.tgz" } diff --git a/deps/npm/node_modules/node-gyp/addon.gypi b/deps/npm/node_modules/node-gyp/addon.gypi index 6b9e20e20..0b81fab20 100644 --- a/deps/npm/node_modules/node-gyp/addon.gypi +++ b/deps/npm/node_modules/node-gyp/addon.gypi @@ -42,7 +42,7 @@ '-luuid.lib', '-lodbc32.lib', '-lDelayImp.lib', - '-l<(node_root_dir)/$(Configuration)/node.lib' + '-l"<(node_root_dir)/$(ConfigurationName)/node.lib"' ], # warning C4251: 'node::ObjectWrap::handle_' : class 'v8::Persistent<T>' # needs to have dll-interface to be used by clients of class 'node::ObjectWrap' diff --git a/deps/npm/node_modules/node-gyp/gyp/AUTHORS b/deps/npm/node_modules/node-gyp/gyp/AUTHORS index 234e1483f..9389ca0a2 100644 --- a/deps/npm/node_modules/node-gyp/gyp/AUTHORS +++ b/deps/npm/node_modules/node-gyp/gyp/AUTHORS @@ -7,4 +7,5 @@ Yandex LLC Steven Knight <knight@baldmt.com> Ryan Norton <rnorton10@gmail.com> +David J. Sankel <david@sankelsoftware.com> Eric N. Vander Weele <ericvw@gmail.com> diff --git a/deps/npm/node_modules/node-gyp/gyp/PRESUBMIT.py b/deps/npm/node_modules/node-gyp/gyp/PRESUBMIT.py index 5567b88bd..9c474eb2b 100644 --- a/deps/npm/node_modules/node-gyp/gyp/PRESUBMIT.py +++ b/deps/npm/node_modules/node-gyp/gyp/PRESUBMIT.py @@ -97,14 +97,19 @@ def CheckChangeOnCommit(input_api, output_api): 'http://gyp-status.appspot.com/status', 'http://gyp-status.appspot.com/current')) + import os import sys old_sys_path = sys.path try: sys.path = ['pylib', 'test/lib'] + sys.path + blacklist = PYLINT_BLACKLIST + if sys.platform == 'win32': + blacklist = [os.path.normpath(x).replace('\\', '\\\\') + for x in PYLINT_BLACKLIST] report.extend(input_api.canned_checks.RunPylint( input_api, output_api, - black_list=PYLINT_BLACKLIST, + black_list=blacklist, disabled_warnings=PYLINT_DISABLED_WARNINGS)) finally: sys.path = old_sys_path diff --git a/deps/npm/node_modules/node-gyp/gyp/buildbot/buildbot_run.py b/deps/npm/node_modules/node-gyp/gyp/buildbot/buildbot_run.py index 398eb87a8..979073c77 100755 --- a/deps/npm/node_modules/node-gyp/gyp/buildbot/buildbot_run.py +++ b/deps/npm/node_modules/node-gyp/gyp/buildbot/buildbot_run.py @@ -23,6 +23,8 @@ BUILDBOT_DIR = os.path.dirname(os.path.abspath(__file__)) TRUNK_DIR = os.path.dirname(BUILDBOT_DIR) ROOT_DIR = os.path.dirname(TRUNK_DIR) ANDROID_DIR = os.path.join(ROOT_DIR, 'android') +CMAKE_DIR = os.path.join(ROOT_DIR, 'cmake') +CMAKE_BIN_DIR = os.path.join(CMAKE_DIR, 'bin') OUT_DIR = os.path.join(TRUNK_DIR, 'out') @@ -34,6 +36,43 @@ def CallSubProcess(*args, **kwargs): sys.exit(1) +def PrepareCmake(): + """Build CMake 2.8.8 since the version in Precise is 2.8.7.""" + if os.environ['BUILDBOT_CLOBBER'] == '1': + print '@@@BUILD_STEP Clobber CMake checkout@@@' + shutil.rmtree(CMAKE_DIR) + + # We always build CMake 2.8.8, so no need to do anything + # if the directory already exists. + if os.path.isdir(CMAKE_DIR): + return + + print '@@@BUILD_STEP Initialize CMake checkout@@@' + os.mkdir(CMAKE_DIR) + CallSubProcess(['git', 'config', '--global', 'user.name', 'trybot']) + CallSubProcess(['git', 'config', '--global', + 'user.email', 'chrome-bot@google.com']) + CallSubProcess(['git', 'config', '--global', 'color.ui', 'false']) + + print '@@@BUILD_STEP Sync CMake@@@' + CallSubProcess( + ['git', 'clone', + '--depth', '1', + '--single-branch', + '--branch', 'v2.8.8', + '--', + 'git://cmake.org/cmake.git', + CMAKE_DIR], + cwd=CMAKE_DIR) + + print '@@@BUILD_STEP Build CMake@@@' + CallSubProcess( + ['/bin/bash', 'bootstrap', '--prefix=%s' % CMAKE_DIR], + cwd=CMAKE_DIR) + + CallSubProcess( ['make', 'cmake'], cwd=CMAKE_DIR) + + def PrepareAndroidTree(): """Prepare an Android tree to run 'android' format tests.""" if os.environ['BUILDBOT_CLOBBER'] == '1': @@ -91,6 +130,7 @@ def GypTestFormat(title, format=None, msvs_version=None): '--all', '--passed', '--format', format, + '--path', CMAKE_BIN_DIR, '--chdir', 'trunk']) if format == 'android': # gyptest needs the environment setup from envsetup/lunch in order to build @@ -124,6 +164,8 @@ def GypBuild(): elif sys.platform.startswith('linux'): retcode += GypTestFormat('ninja') retcode += GypTestFormat('make') + PrepareCmake() + retcode += GypTestFormat('cmake') elif sys.platform == 'darwin': retcode += GypTestFormat('ninja') retcode += GypTestFormat('xcode') diff --git a/deps/npm/node_modules/node-gyp/gyp/gyp b/deps/npm/node_modules/node-gyp/gyp/gyp index a157f3495..b53a6dde8 100755 --- a/deps/npm/node_modules/node-gyp/gyp/gyp +++ b/deps/npm/node_modules/node-gyp/gyp/gyp @@ -3,5 +3,6 @@ # Use of this source code is governed by a BSD-style license that can be # found in the LICENSE file. -BASE=`dirname $0` -python $BASE/gyp_main.py "$@" +set -e +base=$(dirname "$0") +exec python "${base}/gyp_main.py" "$@" diff --git a/deps/npm/node_modules/node-gyp/gyp/gyptest.py b/deps/npm/node_modules/node-gyp/gyp/gyptest.py index a80dfbf2d..8f3ee0ffb 100755 --- a/deps/npm/node_modules/node-gyp/gyp/gyptest.py +++ b/deps/npm/node_modules/node-gyp/gyp/gyptest.py @@ -176,7 +176,7 @@ def main(argv=None): if opts.path: extra_path = [os.path.abspath(p) for p in opts.path] extra_path = os.pathsep.join(extra_path) - os.environ['PATH'] += os.pathsep + extra_path + os.environ['PATH'] = extra_path + os.pathsep + os.environ['PATH'] if not args: if not opts.all: diff --git a/deps/npm/node_modules/node-gyp/gyp/pylib/gyp/MSVSSettings.py b/deps/npm/node_modules/node-gyp/gyp/pylib/gyp/MSVSSettings.py index e8be38628..0c9532d8e 100644 --- a/deps/npm/node_modules/node-gyp/gyp/pylib/gyp/MSVSSettings.py +++ b/deps/npm/node_modules/node-gyp/gyp/pylib/gyp/MSVSSettings.py @@ -812,6 +812,8 @@ _Same(_link, 'UACExecutionLevel', _Enumeration(['AsInvoker', # /level='asInvoker' 'HighestAvailable', # /level='highestAvailable' 'RequireAdministrator'])) # /level='requireAdministrator' +_Same(_link, 'MinimumRequiredVersion', _string) +_Same(_link, 'TreatLinkerWarningAsErrors', _boolean) # /WX # Options found in MSVS that have been renamed in MSBuild. @@ -850,8 +852,6 @@ _MSBuildOnly(_link, 'LinkStatus', _boolean) # /LTCG:STATUS _MSBuildOnly(_link, 'PreventDllBinding', _boolean) # /ALLOWBIND _MSBuildOnly(_link, 'SupportNobindOfDelayLoadedDLL', _boolean) # /DELAY:NOBIND _MSBuildOnly(_link, 'TrackerLogDirectory', _folder_name) -_MSBuildOnly(_link, 'TreatLinkerWarningAsErrors', _boolean) # /WX -_MSBuildOnly(_link, 'MinimumRequiredVersion', _string) _MSBuildOnly(_link, 'MSDOSStubFileName', _file_name) # /STUB Visible='false' _MSBuildOnly(_link, 'SectionAlignment', _integer) # /ALIGN _MSBuildOnly(_link, 'SpecifySectionAttributes', _string) # /SECTION @@ -985,6 +985,7 @@ _Same(_lib, 'OutputFile', _file_name) # /OUT _Same(_lib, 'SuppressStartupBanner', _boolean) # /NOLOGO _Same(_lib, 'UseUnicodeResponseFiles', _boolean) _Same(_lib, 'LinkTimeCodeGeneration', _boolean) # /LTCG +_Same(_lib, 'TargetMachine', _target_machine_enumeration) # TODO(jeanluc) _link defines the same value that gets moved to # ProjectReference. We may want to validate that they are consistent. @@ -1003,7 +1004,6 @@ _MSBuildOnly(_lib, 'MinimumRequiredVersion', _string) _MSBuildOnly(_lib, 'Name', _file_name) # /NAME _MSBuildOnly(_lib, 'RemoveObjects', _file_list) # /REMOVE _MSBuildOnly(_lib, 'SubSystem', _subsystem_enumeration) -_MSBuildOnly(_lib, 'TargetMachine', _target_machine_enumeration) _MSBuildOnly(_lib, 'TrackerLogDirectory', _folder_name) _MSBuildOnly(_lib, 'TreatLibWarningAsErrors', _boolean) # /WX _MSBuildOnly(_lib, 'Verbose', _boolean) diff --git a/deps/npm/node_modules/node-gyp/gyp/pylib/gyp/MSVSVersion.py b/deps/npm/node_modules/node-gyp/gyp/pylib/gyp/MSVSVersion.py index bb30a7ba0..03b6d8ad4 100644 --- a/deps/npm/node_modules/node-gyp/gyp/pylib/gyp/MSVSVersion.py +++ b/deps/npm/node_modules/node-gyp/gyp/pylib/gyp/MSVSVersion.py @@ -96,9 +96,11 @@ class VisualStudioVersion(object): else: assert target_arch == 'x64' arg = 'x86_amd64' - if (os.environ.get('PROCESSOR_ARCHITECTURE') == 'AMD64' or + # Use the 64-on-64 compiler if we're not using an express + # edition and we're running on a 64bit OS. + if self.short_name[-1] != 'e' and ( + os.environ.get('PROCESSOR_ARCHITECTURE') == 'AMD64' or os.environ.get('PROCESSOR_ARCHITEW6432') == 'AMD64'): - # Use the 64-on-64 compiler if we can. arg = 'amd64' return [os.path.normpath( os.path.join(self.path, 'VC/vcvarsall.bat')), arg] diff --git a/deps/npm/node_modules/node-gyp/gyp/pylib/gyp/common.py b/deps/npm/node_modules/node-gyp/gyp/pylib/gyp/common.py index b9d2abef0..f9c6c6f3a 100644 --- a/deps/npm/node_modules/node-gyp/gyp/pylib/gyp/common.py +++ b/deps/npm/node_modules/node-gyp/gyp/pylib/gyp/common.py @@ -391,6 +391,14 @@ def WriteOnDiff(filename): return Writer() +def EnsureDirExists(path): + """Make sure the directory for |path| exists.""" + try: + os.makedirs(os.path.dirname(path)) + except OSError: + pass + + def GetFlavor(params): """Returns |params.flavor| if it's set, the system's default flavor else.""" flavors = { diff --git a/deps/npm/node_modules/node-gyp/gyp/pylib/gyp/generator/android.py b/deps/npm/node_modules/node-gyp/gyp/pylib/gyp/generator/android.py index 9476a1df6..41346e2b1 100644 --- a/deps/npm/node_modules/node-gyp/gyp/pylib/gyp/generator/android.py +++ b/deps/npm/node_modules/node-gyp/gyp/pylib/gyp/generator/android.py @@ -145,7 +145,7 @@ class AndroidMkWriter(object): spec, configs: gyp info part_of_all: flag indicating this target is part of 'all' """ - make.ensure_directory_exists(output_filename) + gyp.common.EnsureDirExists(output_filename) self.fp = open(output_filename, 'w') @@ -452,7 +452,7 @@ class AndroidMkWriter(object): (output, path)) self.WriteLn('\t@echo Copying: $@') self.WriteLn('\t$(hide) mkdir -p $(dir $@)') - self.WriteLn('\t$(hide) $(ACP) -r $< $@') + self.WriteLn('\t$(hide) $(ACP) -rpf $< $@') self.WriteLn() outputs.append(output) self.WriteLn('%s = %s' % (variable, @@ -983,7 +983,7 @@ def GenerateOutput(target_list, target_dicts, data, params): makefile_path = os.path.join(options.toplevel_dir, makefile_name) assert not options.generator_output, ( 'The Android backend does not support options.generator_output.') - make.ensure_directory_exists(makefile_path) + gyp.common.EnsureDirExists(makefile_path) root_makefile = open(makefile_path, 'w') root_makefile.write(header) diff --git a/deps/npm/node_modules/node-gyp/gyp/pylib/gyp/generator/cmake.py b/deps/npm/node_modules/node-gyp/gyp/pylib/gyp/generator/cmake.py new file mode 100644 index 000000000..10d015ee8 --- /dev/null +++ b/deps/npm/node_modules/node-gyp/gyp/pylib/gyp/generator/cmake.py @@ -0,0 +1,1143 @@ +# Copyright (c) 2013 Google Inc. All rights reserved. +# Use of this source code is governed by a BSD-style license that can be +# found in the LICENSE file. + +"""cmake output module + +This module is under development and should be considered experimental. + +This module produces cmake (2.8.8+) input as its output. One CMakeLists.txt is +created for each configuration. + +This module's original purpose was to support editing in IDEs like KDevelop +which use CMake for project management. It is also possible to use CMake to +generate projects for other IDEs such as eclipse cdt and code::blocks. QtCreator +will convert the CMakeLists.txt to a code::blocks cbp for the editor to read, +but build using CMake. As a result QtCreator editor is unaware of compiler +defines. The generated CMakeLists.txt can also be used to build on Linux. There +is currently no support for building on platforms other than Linux. + +The generated CMakeLists.txt should properly compile all projects. However, +there is a mismatch between gyp and cmake with regard to linking. All attempts +are made to work around this, but CMake sometimes sees -Wl,--start-group as a +library and incorrectly repeats it. As a result the output of this generator +should not be relied on for building. + +When using with kdevelop, use version 4.4+. Previous versions of kdevelop will +not be able to find the header file directories described in the generated +CMakeLists.txt file. +""" + +import multiprocessing +import os +import signal +import string +import subprocess +import gyp.common + +generator_default_variables = { + 'EXECUTABLE_PREFIX': '', + 'EXECUTABLE_SUFFIX': '', + 'STATIC_LIB_PREFIX': 'lib', + 'STATIC_LIB_SUFFIX': '.a', + 'SHARED_LIB_PREFIX': 'lib', + 'SHARED_LIB_SUFFIX': '.so', + 'SHARED_LIB_DIR': '${builddir}/lib.${TOOLSET}', + 'LIB_DIR': '${obj}.${TOOLSET}', + 'INTERMEDIATE_DIR': '${obj}.${TOOLSET}/${TARGET}/geni', + 'SHARED_INTERMEDIATE_DIR': '${obj}/gen', + 'PRODUCT_DIR': '${builddir}', + 'RULE_INPUT_PATH': '${RULE_INPUT_PATH}', + 'RULE_INPUT_DIRNAME': '${RULE_INPUT_DIRNAME}', + 'RULE_INPUT_NAME': '${RULE_INPUT_NAME}', + 'RULE_INPUT_ROOT': '${RULE_INPUT_ROOT}', + 'RULE_INPUT_EXT': '${RULE_INPUT_EXT}', + 'CONFIGURATION_NAME': '${configuration}', +} + +FULL_PATH_VARS = ('${CMAKE_SOURCE_DIR}', '${builddir}', '${obj}') + +generator_supports_multiple_toolsets = True +generator_wants_static_library_dependencies_adjusted = True + +COMPILABLE_EXTENSIONS = { + '.c': 'cc', + '.cc': 'cxx', + '.cpp': 'cxx', + '.cxx': 'cxx', + '.s': 's', # cc + '.S': 's', # cc +} + + +def RemovePrefix(a, prefix): + """Returns 'a' without 'prefix' if it starts with 'prefix'.""" + return a[len(prefix):] if a.startswith(prefix) else a + + +def CalculateVariables(default_variables, params): + """Calculate additional variables for use in the build (called by gyp).""" + default_variables.setdefault('OS', gyp.common.GetFlavor(params)) + + +def Compilable(filename): + """Return true if the file is compilable (should be in OBJS).""" + return any(filename.endswith(e) for e in COMPILABLE_EXTENSIONS) + + +def Linkable(filename): + """Return true if the file is linkable (should be on the link line).""" + return filename.endswith('.o') + + +def NormjoinPathForceCMakeSource(base_path, rel_path): + """Resolves rel_path against base_path and returns the result. + + If rel_path is an absolute path it is returned unchanged. + Otherwise it is resolved against base_path and normalized. + If the result is a relative path, it is forced to be relative to the + CMakeLists.txt. + """ + if os.path.isabs(rel_path): + return rel_path + if any([rel_path.startswith(var) for var in FULL_PATH_VARS]): + return rel_path + # TODO: do we need to check base_path for absolute variables as well? + return os.path.join('${CMAKE_SOURCE_DIR}', + os.path.normpath(os.path.join(base_path, rel_path))) + + +def NormjoinPath(base_path, rel_path): + """Resolves rel_path against base_path and returns the result. + TODO: what is this really used for? + If rel_path begins with '$' it is returned unchanged. + Otherwise it is resolved against base_path if relative, then normalized. + """ + if rel_path.startswith('$') and not rel_path.startswith('${configuration}'): + return rel_path + return os.path.normpath(os.path.join(base_path, rel_path)) + + +def CMakeStringEscape(a): + """Escapes the string 'a' for use inside a CMake string. + + This means escaping + '\' otherwise it may be seen as modifying the next character + '"' otherwise it will end the string + ';' otherwise the string becomes a list + + The following do not need to be escaped + '#' when the lexer is in string state, this does not start a comment + + The following are yet unknown + '$' generator variables (like ${obj}) must not be escaped, + but text $ should be escaped + what is wanted is to know which $ come from generator variables + """ + return a.replace('\\', '\\\\').replace(';', '\\;').replace('"', '\\"') + + +def SetFileProperty(output, source_name, property_name, values, sep): + """Given a set of source file, sets the given property on them.""" + output.write('set_source_files_properties(') + output.write(source_name) + output.write(' PROPERTIES ') + output.write(property_name) + output.write(' "') + for value in values: + output.write(CMakeStringEscape(value)) + output.write(sep) + output.write('")\n') + + +def SetFilesProperty(output, source_names, property_name, values, sep): + """Given a set of source files, sets the given property on them.""" + output.write('set_source_files_properties(\n') + for source_name in source_names: + output.write(' ') + output.write(source_name) + output.write('\n') + output.write(' PROPERTIES\n ') + output.write(property_name) + output.write(' "') + for value in values: + output.write(CMakeStringEscape(value)) + output.write(sep) + output.write('"\n)\n') + + +def SetTargetProperty(output, target_name, property_name, values, sep=''): + """Given a target, sets the given property.""" + output.write('set_target_properties(') + output.write(target_name) + output.write(' PROPERTIES ') + output.write(property_name) + output.write(' "') + for value in values: + output.write(CMakeStringEscape(value)) + output.write(sep) + output.write('")\n') + + +def SetVariable(output, variable_name, value): + """Sets a CMake variable.""" + output.write('set(') + output.write(variable_name) + output.write(' "') + output.write(CMakeStringEscape(value)) + output.write('")\n') + + +def SetVariableList(output, variable_name, values): + """Sets a CMake variable to a list.""" + if not values: + return SetVariable(output, variable_name, "") + if len(values) == 1: + return SetVariable(output, variable_name, values[0]) + output.write('list(APPEND ') + output.write(variable_name) + output.write('\n "') + output.write('"\n "'.join([CMakeStringEscape(value) for value in values])) + output.write('")\n') + + +def UnsetVariable(output, variable_name): + """Unsets a CMake variable.""" + output.write('unset(') + output.write(variable_name) + output.write(')\n') + + +def WriteVariable(output, variable_name, prepend=None): + if prepend: + output.write(prepend) + output.write('${') + output.write(variable_name) + output.write('}') + + +class CMakeTargetType: + def __init__(self, command, modifier, property_modifier): + self.command = command + self.modifier = modifier + self.property_modifier = property_modifier + + +cmake_target_type_from_gyp_target_type = { + 'executable': CMakeTargetType('add_executable', None, 'RUNTIME'), + 'static_library': CMakeTargetType('add_library', 'STATIC', 'ARCHIVE'), + 'shared_library': CMakeTargetType('add_library', 'SHARED', 'LIBRARY'), + 'loadable_module': CMakeTargetType('add_library', 'MODULE', 'LIBRARY'), + 'none': CMakeTargetType('add_custom_target', 'SOURCES', None), +} + + +def StringToCMakeTargetName(a): + """Converts the given string 'a' to a valid CMake target name. + + All invalid characters are replaced by '_'. + Invalid for cmake: ' ', '/', '(', ')' + Invalid for make: ':' + Invalid for unknown reasons but cause failures: '.' + """ + return a.translate(string.maketrans(' /():.', '______')) + + +def WriteActions(target_name, actions, extra_sources, extra_deps, + path_to_gyp, output): + """Write CMake for the 'actions' in the target. + + Args: + target_name: the name of the CMake target being generated. + actions: the Gyp 'actions' dict for this target. + extra_sources: [(<cmake_src>, <src>)] to append with generated source files. + extra_deps: [<cmake_taget>] to append with generated targets. + path_to_gyp: relative path from CMakeLists.txt being generated to + the Gyp file in which the target being generated is defined. + """ + for action in actions: + action_name = StringToCMakeTargetName(action['action_name']) + action_target_name = '%s__%s' % (target_name, action_name) + + inputs = action['inputs'] + inputs_name = action_target_name + '__input' + SetVariableList(output, inputs_name, + [NormjoinPathForceCMakeSource(path_to_gyp, dep) for dep in inputs]) + + outputs = action['outputs'] + cmake_outputs = [NormjoinPathForceCMakeSource(path_to_gyp, out) + for out in outputs] + outputs_name = action_target_name + '__output' + SetVariableList(output, outputs_name, cmake_outputs) + + # Build up a list of outputs. + # Collect the output dirs we'll need. + dirs = set(dir for dir in (os.path.dirname(o) for o in outputs) if dir) + + if int(action.get('process_outputs_as_sources', False)): + extra_sources.extend(zip(cmake_outputs, outputs)) + + # add_custom_command + output.write('add_custom_command(OUTPUT ') + WriteVariable(output, outputs_name) + output.write('\n') + + if len(dirs) > 0: + for directory in dirs: + output.write(' COMMAND ${CMAKE_COMMAND} -E make_directory ') + output.write(directory) + output.write('\n') + + output.write(' COMMAND ') + output.write(gyp.common.EncodePOSIXShellList(action['action'])) + output.write('\n') + + output.write(' DEPENDS ') + WriteVariable(output, inputs_name) + output.write('\n') + + output.write(' WORKING_DIRECTORY ${CMAKE_SOURCE_DIR}/') + output.write(path_to_gyp) + output.write('\n') + + output.write(' COMMENT ') + if 'message' in action: + output.write(action['message']) + else: + output.write(action_target_name) + output.write('\n') + + output.write(' VERBATIM\n') + output.write(')\n') + + # add_custom_target + output.write('add_custom_target(') + output.write(action_target_name) + output.write('\n DEPENDS ') + WriteVariable(output, outputs_name) + output.write('\n SOURCES ') + WriteVariable(output, inputs_name) + output.write('\n)\n') + + extra_deps.append(action_target_name) + + +def NormjoinRulePathForceCMakeSource(base_path, rel_path, rule_source): + if rel_path.startswith(("${RULE_INPUT_PATH}","${RULE_INPUT_DIRNAME}")): + if any([rule_source.startswith(var) for var in FULL_PATH_VARS]): + return rel_path + return NormjoinPathForceCMakeSource(base_path, rel_path) + + +def WriteRules(target_name, rules, extra_sources, extra_deps, + path_to_gyp, output): + """Write CMake for the 'rules' in the target. + + Args: + target_name: the name of the CMake target being generated. + actions: the Gyp 'actions' dict for this target. + extra_sources: [(<cmake_src>, <src>)] to append with generated source files. + extra_deps: [<cmake_taget>] to append with generated targets. + path_to_gyp: relative path from CMakeLists.txt being generated to + the Gyp file in which the target being generated is defined. + """ + for rule in rules: + rule_name = StringToCMakeTargetName(target_name + '__' + rule['rule_name']) + + inputs = rule.get('inputs', []) + inputs_name = rule_name + '__input' + SetVariableList(output, inputs_name, + [NormjoinPathForceCMakeSource(path_to_gyp, dep) for dep in inputs]) + outputs = rule['outputs'] + var_outputs = [] + + for count, rule_source in enumerate(rule.get('rule_sources', [])): + action_name = rule_name + '_' + str(count) + + rule_source_dirname, rule_source_basename = os.path.split(rule_source) + rule_source_root, rule_source_ext = os.path.splitext(rule_source_basename) + + SetVariable(output, 'RULE_INPUT_PATH', rule_source) + SetVariable(output, 'RULE_INPUT_DIRNAME', rule_source_dirname) + SetVariable(output, 'RULE_INPUT_NAME', rule_source_basename) + SetVariable(output, 'RULE_INPUT_ROOT', rule_source_root) + SetVariable(output, 'RULE_INPUT_EXT', rule_source_ext) + + # Build up a list of outputs. + # Collect the output dirs we'll need. + dirs = set(dir for dir in (os.path.dirname(o) for o in outputs) if dir) + + # Create variables for the output, as 'local' variable will be unset. + these_outputs = [] + for output_index, out in enumerate(outputs): + output_name = action_name + '_' + str(output_index) + SetVariable(output, output_name, + NormjoinRulePathForceCMakeSource(path_to_gyp, out, + rule_source)) + if int(rule.get('process_outputs_as_sources', False)): + extra_sources.append(('${' + output_name + '}', out)) + these_outputs.append('${' + output_name + '}') + var_outputs.append('${' + output_name + '}') + + # add_custom_command + output.write('add_custom_command(OUTPUT\n') + for out in these_outputs: + output.write(' ') + output.write(out) + output.write('\n') + + for directory in dirs: + output.write(' COMMAND ${CMAKE_COMMAND} -E make_directory ') + output.write(directory) + output.write('\n') + + output.write(' COMMAND ') + output.write(gyp.common.EncodePOSIXShellList(rule['action'])) + output.write('\n') + + output.write(' DEPENDS ') + WriteVariable(output, inputs_name) + output.write(' ') + output.write(NormjoinPath(path_to_gyp, rule_source)) + output.write('\n') + + # CMAKE_SOURCE_DIR is where the CMakeLists.txt lives. + # The cwd is the current build directory. + output.write(' WORKING_DIRECTORY ${CMAKE_SOURCE_DIR}/') + output.write(path_to_gyp) + output.write('\n') + + output.write(' COMMENT ') + if 'message' in rule: + output.write(rule['message']) + else: + output.write(action_name) + output.write('\n') + + output.write(' VERBATIM\n') + output.write(')\n') + + UnsetVariable(output, 'RULE_INPUT_PATH') + UnsetVariable(output, 'RULE_INPUT_DIRNAME') + UnsetVariable(output, 'RULE_INPUT_NAME') + UnsetVariable(output, 'RULE_INPUT_ROOT') + UnsetVariable(output, 'RULE_INPUT_EXT') + + # add_custom_target + output.write('add_custom_target(') + output.write(rule_name) + output.write(' DEPENDS\n') + for out in var_outputs: + output.write(' ') + output.write(out) + output.write('\n') + output.write('SOURCES ') + WriteVariable(output, inputs_name) + output.write('\n') + for rule_source in rule.get('rule_sources', []): + output.write(' ') + output.write(NormjoinPath(path_to_gyp, rule_source)) + output.write('\n') + output.write(')\n') + + extra_deps.append(rule_name) + + +def WriteCopies(target_name, copies, extra_deps, path_to_gyp, output): + """Write CMake for the 'copies' in the target. + + Args: + target_name: the name of the CMake target being generated. + actions: the Gyp 'actions' dict for this target. + extra_deps: [<cmake_taget>] to append with generated targets. + path_to_gyp: relative path from CMakeLists.txt being generated to + the Gyp file in which the target being generated is defined. + """ + copy_name = target_name + '__copies' + + # CMake gets upset with custom targets with OUTPUT which specify no output. + have_copies = any(copy['files'] for copy in copies) + if not have_copies: + output.write('add_custom_target(') + output.write(copy_name) + output.write(')\n') + extra_deps.append(copy_name) + return + + class Copy: + def __init__(self, ext, command): + self.cmake_inputs = [] + self.cmake_outputs = [] + self.gyp_inputs = [] + self.gyp_outputs = [] + self.ext = ext + self.inputs_name = None + self.outputs_name = None + self.command = command + + file_copy = Copy('', 'copy') + dir_copy = Copy('_dirs', 'copy_directory') + + for copy in copies: + files = copy['files'] + destination = copy['destination'] + for src in files: + path = os.path.normpath(src) + basename = os.path.split(path)[1] + dst = os.path.join(destination, basename) + + copy = file_copy if os.path.basename(src) else dir_copy + + copy.cmake_inputs.append(NormjoinPath(path_to_gyp, src)) + copy.cmake_outputs.append(NormjoinPathForceCMakeSource(path_to_gyp, dst)) + copy.gyp_inputs.append(src) + copy.gyp_outputs.append(dst) + + for copy in (file_copy, dir_copy): + if copy.cmake_inputs: + copy.inputs_name = copy_name + '__input' + copy.ext + SetVariableList(output, copy.inputs_name, copy.cmake_inputs) + + copy.outputs_name = copy_name + '__output' + copy.ext + SetVariableList(output, copy.outputs_name, copy.cmake_outputs) + + # add_custom_command + output.write('add_custom_command(\n') + + output.write('OUTPUT') + for copy in (file_copy, dir_copy): + if copy.outputs_name: + WriteVariable(output, copy.outputs_name, ' ') + output.write('\n') + + for copy in (file_copy, dir_copy): + for src, dst in zip(copy.gyp_inputs, copy.gyp_outputs): + # 'cmake -E copy src dst' will create the 'dst' directory if needed. + output.write('COMMAND ${CMAKE_COMMAND} -E %s ' % copy.command) + output.write(src) + output.write(' ') + output.write(dst) + output.write("\n") + + output.write('DEPENDS') + for copy in (file_copy, dir_copy): + if copy.inputs_name: + WriteVariable(output, copy.inputs_name, ' ') + output.write('\n') + + output.write('WORKING_DIRECTORY ${CMAKE_SOURCE_DIR}/') + output.write(path_to_gyp) + output.write('\n') + + output.write('COMMENT Copying for ') + output.write(target_name) + output.write('\n') + + output.write('VERBATIM\n') + output.write(')\n') + + # add_custom_target + output.write('add_custom_target(') + output.write(copy_name) + output.write('\n DEPENDS') + for copy in (file_copy, dir_copy): + if copy.outputs_name: + WriteVariable(output, copy.outputs_name, ' ') + output.write('\n SOURCES') + if file_copy.inputs_name: + WriteVariable(output, file_copy.inputs_name, ' ') + output.write('\n)\n') + + extra_deps.append(copy_name) + + +def CreateCMakeTargetBaseName(qualified_target): + """This is the name we would like the target to have.""" + _, gyp_target_name, gyp_target_toolset = ( + gyp.common.ParseQualifiedTarget(qualified_target)) + cmake_target_base_name = gyp_target_name + if gyp_target_toolset and gyp_target_toolset != 'target': + cmake_target_base_name += '_' + gyp_target_toolset + return StringToCMakeTargetName(cmake_target_base_name) + + +def CreateCMakeTargetFullName(qualified_target): + """An unambiguous name for the target.""" + gyp_file, gyp_target_name, gyp_target_toolset = ( + gyp.common.ParseQualifiedTarget(qualified_target)) + cmake_target_full_name = gyp_file + ':' + gyp_target_name + if gyp_target_toolset and gyp_target_toolset != 'target': + cmake_target_full_name += '_' + gyp_target_toolset + return StringToCMakeTargetName(cmake_target_full_name) + + +class CMakeNamer(object): + """Converts Gyp target names into CMake target names. + + CMake requires that target names be globally unique. One way to ensure + this is to fully qualify the names of the targets. Unfortunatly, this + ends up with all targets looking like "chrome_chrome_gyp_chrome" instead + of just "chrome". If this generator were only interested in building, it + would be possible to fully qualify all target names, then create + unqualified target names which depend on all qualified targets which + should have had that name. This is more or less what the 'make' generator + does with aliases. However, one goal of this generator is to create CMake + files for use with IDEs, and fully qualified names are not as user + friendly. + + Since target name collision is rare, we do the above only when required. + + Toolset variants are always qualified from the base, as this is required for + building. However, it also makes sense for an IDE, as it is possible for + defines to be different. + """ + def __init__(self, target_list): + self.cmake_target_base_names_conficting = set() + + cmake_target_base_names_seen = set() + for qualified_target in target_list: + cmake_target_base_name = CreateCMakeTargetBaseName(qualified_target) + + if cmake_target_base_name not in cmake_target_base_names_seen: + cmake_target_base_names_seen.add(cmake_target_base_name) + else: + self.cmake_target_base_names_conficting.add(cmake_target_base_name) + + def CreateCMakeTargetName(self, qualified_target): + base_name = CreateCMakeTargetBaseName(qualified_target) + if base_name in self.cmake_target_base_names_conficting: + return CreateCMakeTargetFullName(qualified_target) + return base_name + + +def WriteTarget(namer, qualified_target, target_dicts, build_dir, config_to_use, + options, generator_flags, all_qualified_targets, output): + + # The make generator does this always. + # TODO: It would be nice to be able to tell CMake all dependencies. + circular_libs = generator_flags.get('circular', True) + + if not generator_flags.get('standalone', False): + output.write('\n#') + output.write(qualified_target) + output.write('\n') + + gyp_file, _, _ = gyp.common.ParseQualifiedTarget(qualified_target) + rel_gyp_file = gyp.common.RelativePath(gyp_file, options.toplevel_dir) + rel_gyp_dir = os.path.dirname(rel_gyp_file) + + # Relative path from build dir to top dir. + build_to_top = gyp.common.InvertRelativePath(build_dir, options.toplevel_dir) + # Relative path from build dir to gyp dir. + build_to_gyp = os.path.join(build_to_top, rel_gyp_dir) + + path_from_cmakelists_to_gyp = build_to_gyp + + spec = target_dicts.get(qualified_target, {}) + config = spec.get('configurations', {}).get(config_to_use, {}) + + target_name = spec.get('target_name', '<missing target name>') + target_type = spec.get('type', '<missing target type>') + target_toolset = spec.get('toolset') + + SetVariable(output, 'TARGET', target_name) + SetVariable(output, 'TOOLSET', target_toolset) + + cmake_target_name = namer.CreateCMakeTargetName(qualified_target) + + extra_sources = [] + extra_deps = [] + + # Actions must come first, since they can generate more OBJs for use below. + if 'actions' in spec: + WriteActions(cmake_target_name, spec['actions'], extra_sources, extra_deps, + path_from_cmakelists_to_gyp, output) + + # Rules must be early like actions. + if 'rules' in spec: + WriteRules(cmake_target_name, spec['rules'], extra_sources, extra_deps, + path_from_cmakelists_to_gyp, output) + + # Copies + if 'copies' in spec: + WriteCopies(cmake_target_name, spec['copies'], extra_deps, + path_from_cmakelists_to_gyp, output) + + # Target and sources + srcs = spec.get('sources', []) + + # Gyp separates the sheep from the goats based on file extensions. + def partition(l, p): + return reduce(lambda x, e: x[not p(e)].append(e) or x, l, ([], [])) + compilable_srcs, other_srcs = partition(srcs, Compilable) + + # CMake gets upset when executable targets provide no sources. + if target_type == 'executable' and not compilable_srcs and not extra_sources: + print ('Executable %s has no complilable sources, treating as "none".' % + target_name ) + target_type = 'none' + + cmake_target_type = cmake_target_type_from_gyp_target_type.get(target_type) + if cmake_target_type is None: + print ('Target %s has unknown target type %s, skipping.' % + ( target_name, target_type ) ) + return + + other_srcs_name = None + if other_srcs: + other_srcs_name = cmake_target_name + '__other_srcs' + SetVariableList(output, other_srcs_name, + [NormjoinPath(path_from_cmakelists_to_gyp, src) for src in other_srcs]) + + # CMake is opposed to setting linker directories and considers the practice + # of setting linker directories dangerous. Instead, it favors the use of + # find_library and passing absolute paths to target_link_libraries. + # However, CMake does provide the command link_directories, which adds + # link directories to targets defined after it is called. + # As a result, link_directories must come before the target definition. + # CMake unfortunately has no means of removing entries from LINK_DIRECTORIES. + library_dirs = config.get('library_dirs') + if library_dirs is not None: + output.write('link_directories(') + for library_dir in library_dirs: + output.write(' ') + output.write(NormjoinPath(path_from_cmakelists_to_gyp, library_dir)) + output.write('\n') + output.write(')\n') + + output.write(cmake_target_type.command) + output.write('(') + output.write(cmake_target_name) + + if cmake_target_type.modifier is not None: + output.write(' ') + output.write(cmake_target_type.modifier) + + if other_srcs_name: + WriteVariable(output, other_srcs_name, ' ') + + output.write('\n') + + for src in compilable_srcs: + output.write(' ') + output.write(NormjoinPath(path_from_cmakelists_to_gyp, src)) + output.write('\n') + for extra_source in extra_sources: + output.write(' ') + src, _ = extra_source + output.write(NormjoinPath(path_from_cmakelists_to_gyp, src)) + output.write('\n') + + output.write(')\n') + + # Output name and location. + if target_type != 'none': + # Mark uncompiled sources as uncompiled. + if other_srcs_name: + output.write('set_source_files_properties(') + WriteVariable(output, other_srcs_name, '') + output.write(' PROPERTIES HEADER_FILE_ONLY "TRUE")\n') + + # Output directory + target_output_directory = spec.get('product_dir') + if target_output_directory is None: + if target_type in ('executable', 'loadable_module'): + target_output_directory = generator_default_variables['PRODUCT_DIR'] + elif target_type in ('shared_library'): + target_output_directory = '${builddir}/lib.${TOOLSET}' + elif spec.get('standalone_static_library', False): + target_output_directory = generator_default_variables['PRODUCT_DIR'] + else: + base_path = gyp.common.RelativePath(os.path.dirname(gyp_file), + options.toplevel_dir) + target_output_directory = '${obj}.${TOOLSET}' + target_output_directory = ( + os.path.join(target_output_directory, base_path)) + + cmake_target_output_directory = NormjoinPathForceCMakeSource( + path_from_cmakelists_to_gyp, + target_output_directory) + SetTargetProperty(output, + cmake_target_name, + cmake_target_type.property_modifier + '_OUTPUT_DIRECTORY', + cmake_target_output_directory) + + # Output name + default_product_prefix = '' + default_product_name = target_name + default_product_ext = '' + if target_type == 'static_library': + static_library_prefix = generator_default_variables['STATIC_LIB_PREFIX'] + default_product_name = RemovePrefix(default_product_name, + static_library_prefix) + default_product_prefix = static_library_prefix + default_product_ext = generator_default_variables['STATIC_LIB_SUFFIX'] + + elif target_type in ('loadable_module', 'shared_library'): + shared_library_prefix = generator_default_variables['SHARED_LIB_PREFIX'] + default_product_name = RemovePrefix(default_product_name, + shared_library_prefix) + default_product_prefix = shared_library_prefix + default_product_ext = generator_default_variables['SHARED_LIB_SUFFIX'] + + elif target_type != 'executable': + print ('ERROR: What output file should be generated?', + 'type', target_type, 'target', target_name) + + product_prefix = spec.get('product_prefix', default_product_prefix) + product_name = spec.get('product_name', default_product_name) + product_ext = spec.get('product_extension') + if product_ext: + product_ext = '.' + product_ext + else: + product_ext = default_product_ext + + SetTargetProperty(output, cmake_target_name, 'PREFIX', product_prefix) + SetTargetProperty(output, cmake_target_name, + cmake_target_type.property_modifier + '_OUTPUT_NAME', + product_name) + SetTargetProperty(output, cmake_target_name, 'SUFFIX', product_ext) + + # Make the output of this target referenceable as a source. + cmake_target_output_basename = product_prefix + product_name + product_ext + cmake_target_output = os.path.join(cmake_target_output_directory, + cmake_target_output_basename) + SetFileProperty(output, cmake_target_output, 'GENERATED', ['TRUE'], '') + + # Let CMake know if the 'all' target should depend on this target. + exclude_from_all = ('TRUE' if qualified_target not in all_qualified_targets + else 'FALSE') + SetTargetProperty(output, cmake_target_name, + 'EXCLUDE_FROM_ALL', exclude_from_all) + for extra_target_name in extra_deps: + SetTargetProperty(output, extra_target_name, + 'EXCLUDE_FROM_ALL', exclude_from_all) + + # Includes + includes = config.get('include_dirs') + if includes: + # This (target include directories) is what requires CMake 2.8.8 + includes_name = cmake_target_name + '__include_dirs' + SetVariableList(output, includes_name, + [NormjoinPathForceCMakeSource(path_from_cmakelists_to_gyp, include) + for include in includes]) + output.write('set_property(TARGET ') + output.write(cmake_target_name) + output.write(' APPEND PROPERTY INCLUDE_DIRECTORIES ') + WriteVariable(output, includes_name, '') + output.write(')\n') + + # Defines + defines = config.get('defines') + if defines is not None: + SetTargetProperty(output, + cmake_target_name, + 'COMPILE_DEFINITIONS', + defines, + ';') + + # Compile Flags - http://www.cmake.org/Bug/view.php?id=6493 + # CMake currently does not have target C and CXX flags. + # So, instead of doing... + + # cflags_c = config.get('cflags_c') + # if cflags_c is not None: + # SetTargetProperty(output, cmake_target_name, + # 'C_COMPILE_FLAGS', cflags_c, ' ') + + # cflags_cc = config.get('cflags_cc') + # if cflags_cc is not None: + # SetTargetProperty(output, cmake_target_name, + # 'CXX_COMPILE_FLAGS', cflags_cc, ' ') + + # Instead we must... + s_sources = [] + c_sources = [] + cxx_sources = [] + for src in srcs: + _, ext = os.path.splitext(src) + src_type = COMPILABLE_EXTENSIONS.get(ext, None) + + if src_type == 's': + s_sources.append(NormjoinPath(path_from_cmakelists_to_gyp, src)) + + if src_type == 'cc': + c_sources.append(NormjoinPath(path_from_cmakelists_to_gyp, src)) + + if src_type == 'cxx': + cxx_sources.append(NormjoinPath(path_from_cmakelists_to_gyp, src)) + + for extra_source in extra_sources: + src, real_source = extra_source + _, ext = os.path.splitext(real_source) + src_type = COMPILABLE_EXTENSIONS.get(ext, None) + + if src_type == 's': + s_sources.append(NormjoinPath(path_from_cmakelists_to_gyp, src)) + + if src_type == 'cc': + c_sources.append(NormjoinPath(path_from_cmakelists_to_gyp, src)) + + if src_type == 'cxx': + cxx_sources.append(NormjoinPath(path_from_cmakelists_to_gyp, src)) + + cflags = config.get('cflags', []) + cflags_c = config.get('cflags_c', []) + cflags_cxx = config.get('cflags_cc', []) + if c_sources and not (s_sources or cxx_sources): + flags = [] + flags.extend(cflags) + flags.extend(cflags_c) + SetTargetProperty(output, cmake_target_name, 'COMPILE_FLAGS', flags, ' ') + + elif cxx_sources and not (s_sources or c_sources): + flags = [] + flags.extend(cflags) + flags.extend(cflags_cxx) + SetTargetProperty(output, cmake_target_name, 'COMPILE_FLAGS', flags, ' ') + + else: + if s_sources and cflags: + SetFilesProperty(output, s_sources, 'COMPILE_FLAGS', cflags, ' ') + + if c_sources and (cflags or cflags_c): + flags = [] + flags.extend(cflags) + flags.extend(cflags_c) + SetFilesProperty(output, c_sources, 'COMPILE_FLAGS', flags, ' ') + + if cxx_sources and (cflags or cflags_cxx): + flags = [] + flags.extend(cflags) + flags.extend(cflags_cxx) + SetFilesProperty(output, cxx_sources, 'COMPILE_FLAGS', flags, ' ') + + # Have assembly link as c if there are no other files + if not c_sources and not cxx_sources and s_sources: + SetTargetProperty(output, cmake_target_name, 'LINKER_LANGUAGE', ['C']) + + # Linker flags + ldflags = config.get('ldflags') + if ldflags is not None: + SetTargetProperty(output, cmake_target_name, 'LINK_FLAGS', ldflags, ' ') + + # Note on Dependencies and Libraries: + # CMake wants to handle link order, resolving the link line up front. + # Gyp does not retain or enforce specifying enough information to do so. + # So do as other gyp generators and use --start-group and --end-group. + # Give CMake as little information as possible so that it doesn't mess it up. + + # Dependencies + rawDeps = spec.get('dependencies', []) + + static_deps = [] + shared_deps = [] + other_deps = [] + for rawDep in rawDeps: + dep_cmake_name = namer.CreateCMakeTargetName(rawDep) + dep_spec = target_dicts.get(rawDep, {}) + dep_target_type = dep_spec.get('type', None) + + if dep_target_type == 'static_library': + static_deps.append(dep_cmake_name) + elif dep_target_type == 'shared_library': + shared_deps.append(dep_cmake_name) + else: + other_deps.append(dep_cmake_name) + + # ensure all external dependencies are complete before internal dependencies + # extra_deps currently only depend on their own deps, so otherwise run early + if static_deps or shared_deps or other_deps: + for extra_dep in extra_deps: + output.write('add_dependencies(') + output.write(extra_dep) + output.write('\n') + for deps in (static_deps, shared_deps, other_deps): + for dep in gyp.common.uniquer(deps): + output.write(' ') + output.write(dep) + output.write('\n') + output.write(')\n') + + linkable = target_type in ('executable', 'loadable_module', 'shared_library') + other_deps.extend(extra_deps) + if other_deps or (not linkable and (static_deps or shared_deps)): + output.write('add_dependencies(') + output.write(cmake_target_name) + output.write('\n') + for dep in gyp.common.uniquer(other_deps): + output.write(' ') + output.write(dep) + output.write('\n') + if not linkable: + for deps in (static_deps, shared_deps): + for lib_dep in gyp.common.uniquer(deps): + output.write(' ') + output.write(lib_dep) + output.write('\n') + output.write(')\n') + + # Libraries + if linkable: + external_libs = [lib for lib in spec.get('libraries', []) if len(lib) > 0] + if external_libs or static_deps or shared_deps: + output.write('target_link_libraries(') + output.write(cmake_target_name) + output.write('\n') + if static_deps: + write_group = circular_libs and len(static_deps) > 1 + if write_group: + output.write('-Wl,--start-group\n') + for dep in gyp.common.uniquer(static_deps): + output.write(' ') + output.write(dep) + output.write('\n') + if write_group: + output.write('-Wl,--end-group\n') + if shared_deps: + for dep in gyp.common.uniquer(shared_deps): + output.write(' ') + output.write(dep) + output.write('\n') + if external_libs: + for lib in gyp.common.uniquer(external_libs): + output.write(' ') + output.write(lib) + output.write('\n') + + output.write(')\n') + + UnsetVariable(output, 'TOOLSET') + UnsetVariable(output, 'TARGET') + + +def GenerateOutputForConfig(target_list, target_dicts, data, + params, config_to_use): + options = params['options'] + generator_flags = params['generator_flags'] + + # generator_dir: relative path from pwd to where make puts build files. + # Makes migrating from make to cmake easier, cmake doesn't put anything here. + # Each Gyp configuration creates a different CMakeLists.txt file + # to avoid incompatibilities between Gyp and CMake configurations. + generator_dir = os.path.relpath(options.generator_output or '.') + + # output_dir: relative path from generator_dir to the build directory. + output_dir = generator_flags.get('output_dir', 'out') + + # build_dir: relative path from source root to our output files. + # e.g. "out/Debug" + build_dir = os.path.normpath(os.path.join(generator_dir, + output_dir, + config_to_use)) + + toplevel_build = os.path.join(options.toplevel_dir, build_dir) + + output_file = os.path.join(toplevel_build, 'CMakeLists.txt') + gyp.common.EnsureDirExists(output_file) + + output = open(output_file, 'w') + output.write('cmake_minimum_required(VERSION 2.8.8 FATAL_ERROR)\n') + output.write('cmake_policy(VERSION 2.8.8)\n') + + _, project_target, _ = gyp.common.ParseQualifiedTarget(target_list[-1]) + output.write('project(') + output.write(project_target) + output.write(')\n') + + SetVariable(output, 'configuration', config_to_use) + + # The following appears to be as-yet undocumented. + # http://public.kitware.com/Bug/view.php?id=8392 + output.write('enable_language(ASM)\n') + # ASM-ATT does not support .S files. + # output.write('enable_language(ASM-ATT)\n') + + SetVariable(output, 'builddir', '${CMAKE_BINARY_DIR}') + SetVariable(output, 'obj', '${builddir}/obj') + output.write('\n') + + # TODO: Undocumented/unsupported (the CMake Java generator depends on it). + # CMake by default names the object resulting from foo.c to be foo.c.o. + # Gyp traditionally names the object resulting from foo.c foo.o. + # This should be irrelevant, but some targets extract .o files from .a + # and depend on the name of the extracted .o files. + output.write('set(CMAKE_C_OUTPUT_EXTENSION_REPLACE 1)\n') + output.write('set(CMAKE_CXX_OUTPUT_EXTENSION_REPLACE 1)\n') + output.write('\n') + + namer = CMakeNamer(target_list) + + # The list of targets upon which the 'all' target should depend. + # CMake has it's own implicit 'all' target, one is not created explicitly. + all_qualified_targets = set() + for build_file in params['build_files']: + for qualified_target in gyp.common.AllTargets(target_list, + target_dicts, + os.path.normpath(build_file)): + all_qualified_targets.add(qualified_target) + + for qualified_target in target_list: + WriteTarget(namer, qualified_target, target_dicts, build_dir, config_to_use, + options, generator_flags, all_qualified_targets, output) + + output.close() + + +def PerformBuild(data, configurations, params): + options = params['options'] + generator_flags = params['generator_flags'] + + # generator_dir: relative path from pwd to where make puts build files. + # Makes migrating from make to cmake easier, cmake doesn't put anything here. + generator_dir = os.path.relpath(options.generator_output or '.') + + # output_dir: relative path from generator_dir to the build directory. + output_dir = generator_flags.get('output_dir', 'out') + + for config_name in configurations: + # build_dir: relative path from source root to our output files. + # e.g. "out/Debug" + build_dir = os.path.normpath(os.path.join(generator_dir, + output_dir, + config_name)) + arguments = ['cmake', '-G', 'Ninja'] + print 'Generating [%s]: %s' % (config_name, arguments) + subprocess.check_call(arguments, cwd=build_dir) + + arguments = ['ninja', '-C', build_dir] + print 'Building [%s]: %s' % (config_name, arguments) + subprocess.check_call(arguments) + + +def CallGenerateOutputForConfig(arglist): + # Ignore the interrupt signal so that the parent process catches it and + # kills all multiprocessing children. + signal.signal(signal.SIGINT, signal.SIG_IGN) + + target_list, target_dicts, data, params, config_name = arglist + GenerateOutputForConfig(target_list, target_dicts, data, params, config_name) + + +def GenerateOutput(target_list, target_dicts, data, params): + user_config = params.get('generator_flags', {}).get('config', None) + if user_config: + GenerateOutputForConfig(target_list, target_dicts, data, + params, user_config) + else: + config_names = target_dicts[target_list[0]]['configurations'].keys() + if params['parallel']: + try: + pool = multiprocessing.Pool(len(config_names)) + arglists = [] + for config_name in config_names: + arglists.append((target_list, target_dicts, data, + params, config_name)) + pool.map(CallGenerateOutputForConfig, arglists) + except KeyboardInterrupt, e: + pool.terminate() + raise e + else: + for config_name in config_names: + GenerateOutputForConfig(target_list, target_dicts, data, + params, config_name) diff --git a/deps/npm/node_modules/node-gyp/gyp/pylib/gyp/generator/eclipse.py b/deps/npm/node_modules/node-gyp/gyp/pylib/gyp/generator/eclipse.py index a80edc892..84380b04d 100644 --- a/deps/npm/node_modules/node-gyp/gyp/pylib/gyp/generator/eclipse.py +++ b/deps/npm/node_modules/node-gyp/gyp/pylib/gyp/generator/eclipse.py @@ -270,9 +270,9 @@ def GenerateOutputForConfig(target_list, target_dicts, data, params, shared_intermediate_dirs = [os.path.join(toplevel_build, 'obj', 'gen'), os.path.join(toplevel_build, 'gen')] - if not os.path.exists(toplevel_build): - os.makedirs(toplevel_build) - out = open(os.path.join(toplevel_build, 'eclipse-cdt-settings.xml'), 'w') + out_name = os.path.join(toplevel_build, 'eclipse-cdt-settings.xml') + gyp.common.EnsureDirExists(out_name) + out = open(out_name, 'w') out.write('<?xml version="1.0" encoding="UTF-8"?>\n') out.write('<cdtprojectproperties>\n') diff --git a/deps/npm/node_modules/node-gyp/gyp/pylib/gyp/generator/make.py b/deps/npm/node_modules/node-gyp/gyp/pylib/gyp/generator/make.py index efd59bc4a..b3f8a2b77 100644 --- a/deps/npm/node_modules/node-gyp/gyp/pylib/gyp/generator/make.py +++ b/deps/npm/node_modules/node-gyp/gyp/pylib/gyp/generator/make.py @@ -57,6 +57,7 @@ generator_wants_sorted_dependencies = False generator_additional_non_configuration_keys = [] generator_additional_path_sections = [] generator_extra_sources_for_rules = [] +generator_filelist_paths = None def CalculateVariables(default_variables, params): @@ -103,11 +104,17 @@ def CalculateGeneratorInputInfo(params): global generator_wants_sorted_dependencies generator_wants_sorted_dependencies = True + output_dir = params['options'].generator_output or \ + params['options'].toplevel_dir + builddir_name = generator_flags.get('output_dir', 'out') + qualified_out_dir = os.path.normpath(os.path.join( + output_dir, builddir_name, 'gypfiles')) -def ensure_directory_exists(path): - dir = os.path.dirname(path) - if dir and not os.path.exists(dir): - os.makedirs(dir) + global generator_filelist_paths + generator_filelist_paths = { + 'toplevel': params['options'].toplevel_dir, + 'qualified_out_dir': qualified_out_dir, + } # The .d checking code below uses these functions: @@ -678,7 +685,7 @@ $(obj).$(TOOLSET)/$(TARGET)/%%.o: $(obj)/%%%s FORCE_DO_CMD spec, configs: gyp info part_of_all: flag indicating this target is part of 'all' """ - ensure_directory_exists(output_filename) + gyp.common.EnsureDirExists(output_filename) self.fp = open(output_filename, 'w') @@ -807,7 +814,7 @@ $(obj).$(TOOLSET)/$(TARGET)/%%.o: $(obj)/%%%s FORCE_DO_CMD targets: list of "all" targets for this sub-project build_dir: build output directory, relative to the sub-project """ - ensure_directory_exists(output_filename) + gyp.common.EnsureDirExists(output_filename) self.fp = open(output_filename, 'w') self.fp.write(header) # For consistency with other builders, put sub-project build output in the @@ -1946,7 +1953,8 @@ def GenerateOutput(target_list, target_dicts, data, params): # We write the file in the base_path directory. output_file = os.path.join(options.depth, base_path, base_name) if options.generator_output: - output_file = os.path.join(options.generator_output, output_file) + output_file = os.path.join( + options.depth, options.generator_output, base_path, base_name) base_path = gyp.common.RelativePath(os.path.dirname(build_file), options.toplevel_dir) return base_path, output_file @@ -1969,7 +1977,8 @@ def GenerateOutput(target_list, target_dicts, data, params): makefile_path = os.path.join(options.toplevel_dir, makefile_name) if options.generator_output: global srcdir_prefix - makefile_path = os.path.join(options.generator_output, makefile_path) + makefile_path = os.path.join( + options.toplevel_dir, options.generator_output, makefile_name) srcdir = gyp.common.RelativePath(srcdir, options.generator_output) srcdir_prefix = '$(srcdir)/' @@ -2045,8 +2054,9 @@ def GenerateOutput(target_list, target_dicts, data, params): make_global_settings += ( 'ifneq (,$(filter $(origin %s), undefined default))\n' % key) # Let gyp-time envvars win over global settings. - if key in os.environ: - value = os.environ[key] + env_key = key.replace('.', '_') # CC.host -> CC_host + if env_key in os.environ: + value = os.environ[env_key] make_global_settings += ' %s = %s\n' % (key, value) make_global_settings += 'endif\n' else: @@ -2056,7 +2066,7 @@ def GenerateOutput(target_list, target_dicts, data, params): header_params['make_global_settings'] = make_global_settings - ensure_directory_exists(makefile_path) + gyp.common.EnsureDirExists(makefile_path) root_makefile = open(makefile_path, 'w') root_makefile.write(SHARED_HEADER % header_params) # Currently any versions have the same effect, but in future the behavior @@ -2088,7 +2098,8 @@ def GenerateOutput(target_list, target_dicts, data, params): this_make_global_settings = data[build_file].get('make_global_settings', []) assert make_global_settings_array == this_make_global_settings, ( - "make_global_settings needs to be the same for all targets.") + "make_global_settings needs to be the same for all targets. %s vs. %s" % + (this_make_global_settings, make_global_settings)) build_files.add(gyp.common.RelativePath(build_file, options.toplevel_dir)) included_files = data[build_file]['included_files'] diff --git a/deps/npm/node_modules/node-gyp/gyp/pylib/gyp/generator/msvs.py b/deps/npm/node_modules/node-gyp/gyp/pylib/gyp/generator/msvs.py index 63afda914..c59aea106 100644 --- a/deps/npm/node_modules/node-gyp/gyp/pylib/gyp/generator/msvs.py +++ b/deps/npm/node_modules/node-gyp/gyp/pylib/gyp/generator/msvs.py @@ -2,6 +2,7 @@ # Use of this source code is governed by a BSD-style license that can be # found in the LICENSE file. +import collections import copy import ntpath import os @@ -21,6 +22,16 @@ import gyp.MSVSUtil as MSVSUtil import gyp.MSVSVersion as MSVSVersion from gyp.common import GypError +# TODO: Remove once bots are on 2.7, http://crbug.com/241769 +def _import_OrderedDict(): + import collections + try: + return collections.OrderedDict + except AttributeError: + import gyp.ordered_dict + return gyp.ordered_dict.OrderedDict +OrderedDict = _import_OrderedDict() + # Regular expression for validating Visual Studio GUIDs. If the GUID # contains lowercase hex letters, MSVS will be fine. However, @@ -86,6 +97,46 @@ cached_username = None cached_domain = None +# Based on http://code.activestate.com/recipes/576694/. +class OrderedSet(collections.MutableSet): + def __init__(self, iterable=None): + self.end = end = [] + end += [None, end, end] # sentinel node for doubly linked list + self.map = {} # key --> [key, prev, next] + if iterable is not None: + self |= iterable + + def __len__(self): + return len(self.map) + + def discard(self, key): + if key in self.map: + key, prev, next = self.map.pop(key) + prev[2] = next + next[1] = prev + + def __contains__(self, key): + return key in self.map + + def add(self, key): + if key not in self.map: + end = self.end + curr = end[1] + curr[2] = end[1] = self.map[key] = [key, curr, end] + + def update(self, iterable): + for i in iterable: + if i not in self: + self.add(i) + + def __iter__(self): + end = self.end + curr = end[2] + while curr is not end: + yield curr[0] + curr = curr[2] + + # TODO(gspencer): Switch the os.environ calls to be # win32api.GetDomainName() and win32api.GetUserName() once the # python version in depot_tools has been updated to work on Vista @@ -158,13 +209,14 @@ def _FixPaths(paths): def _ConvertSourcesToFilterHierarchy(sources, prefix=None, excluded=None, - list_excluded=True): + list_excluded=True, msvs_version=None): """Converts a list split source file paths into a vcproj folder hierarchy. Arguments: sources: A list of source file paths split. prefix: A list of source file path layers meant to apply to each of sources. excluded: A set of excluded files. + msvs_version: A MSVSVersion object. Returns: A hierarchy of filenames and MSVSProject.Filter objects that matches the @@ -179,7 +231,7 @@ def _ConvertSourcesToFilterHierarchy(sources, prefix=None, excluded=None, if not prefix: prefix = [] result = [] excluded_result = [] - folders = dict() + folders = OrderedDict() # Gather files into the final result, excluded, or folders. for s in sources: if len(s) == 1: @@ -188,15 +240,28 @@ def _ConvertSourcesToFilterHierarchy(sources, prefix=None, excluded=None, excluded_result.append(filename) else: result.append(filename) - else: + elif msvs_version and not msvs_version.UsesVcxproj(): + # For MSVS 2008 and earlier, we need to process all files before walking + # the sub folders. if not folders.get(s[0]): folders[s[0]] = [] folders[s[0]].append(s[1:]) + else: + contents = _ConvertSourcesToFilterHierarchy([s[1:]], prefix + [s[0]], + excluded=excluded, + list_excluded=list_excluded, + msvs_version=msvs_version) + contents = MSVSProject.Filter(s[0], contents=contents) + result.append(contents) # Add a folder for excluded files. if excluded_result and list_excluded: excluded_folder = MSVSProject.Filter('_excluded_files', contents=excluded_result) result.append(excluded_folder) + + if msvs_version and msvs_version.UsesVcxproj(): + return result + # Populate all the folders. for f in folders: contents = _ConvertSourcesToFilterHierarchy(folders[f], prefix=prefix + [f], @@ -204,7 +269,6 @@ def _ConvertSourcesToFilterHierarchy(sources, prefix=None, excluded=None, list_excluded=list_excluded) contents = MSVSProject.Filter(f, contents=contents) result.append(contents) - return result @@ -415,13 +479,13 @@ def _AddAccumulatedActionsToMSVS(p, spec, actions_dict): dicts describing the actions attached to that input file. """ for primary_input in actions_dict: - inputs = set() - outputs = set() + inputs = OrderedSet() + outputs = OrderedSet() descriptions = [] commands = [] for action in actions_dict[primary_input]: - inputs.update(set(action['inputs'])) - outputs.update(set(action['outputs'])) + inputs.update(OrderedSet(action['inputs'])) + outputs.update(OrderedSet(action['outputs'])) descriptions.append(action['description']) commands.append(action['command']) # Add the custom build step for one input file. @@ -477,8 +541,8 @@ def _RuleInputsAndOutputs(rule, trigger_file): """ raw_inputs = _FixPaths(rule.get('inputs', [])) raw_outputs = _FixPaths(rule.get('outputs', [])) - inputs = set() - outputs = set() + inputs = OrderedSet() + outputs = OrderedSet() inputs.add(trigger_file) for i in raw_inputs: inputs.add(_RuleExpandPath(i, trigger_file)) @@ -549,16 +613,16 @@ def _GenerateExternalRules(rules, output_dir, spec, mk_file.write('OutDirCygwin:=$(shell cygpath -u "$(OutDir)")\n') mk_file.write('IntDirCygwin:=$(shell cygpath -u "$(IntDir)")\n') # Gather stuff needed to emit all: target. - all_inputs = set() - all_outputs = set() - all_output_dirs = set() + all_inputs = OrderedSet() + all_outputs = OrderedSet() + all_output_dirs = OrderedSet() first_outputs = [] for rule in rules: trigger_files = _FindRuleTriggerFiles(rule, sources) for tf in trigger_files: inputs, outputs = _RuleInputsAndOutputs(rule, tf) - all_inputs.update(set(inputs)) - all_outputs.update(set(outputs)) + all_inputs.update(OrderedSet(inputs)) + all_outputs.update(OrderedSet(outputs)) # Only use one target from each rule as the dependency for # 'all' so we don't try to build each rule multiple times. first_outputs.append(list(outputs)[0]) @@ -799,8 +863,8 @@ def _AdjustSourcesForRules(spec, rules, sources, excluded_sources): trigger_files = _FindRuleTriggerFiles(rule, sources) for trigger_file in trigger_files: inputs, outputs = _RuleInputsAndOutputs(rule, trigger_file) - inputs = set(_FixPaths(inputs)) - outputs = set(_FixPaths(outputs)) + inputs = OrderedSet(_FixPaths(inputs)) + outputs = OrderedSet(_FixPaths(outputs)) inputs.remove(_FixPath(trigger_file)) sources.update(inputs) if not spec.get('msvs_external_builder'): @@ -817,7 +881,7 @@ def _FilterActionsFromExcluded(excluded_sources, actions_to_add): Returns: excluded_sources with files that have actions attached removed. """ - must_keep = set(_FixPaths(actions_to_add.keys())) + must_keep = OrderedSet(_FixPaths(actions_to_add.keys())) return [s for s in excluded_sources if s not in must_keep] @@ -900,9 +964,7 @@ def _GenerateMSVSProject(project, options, version, generator_flags): generator_flags: dict of generator-specific flags. """ spec = project.spec - vcproj_dir = os.path.dirname(project.path) - if vcproj_dir and not os.path.exists(vcproj_dir): - os.makedirs(vcproj_dir) + gyp.common.EnsureDirExists(project.path) platforms = _GetUniquePlatforms(spec) p = MSVSProject.Writer(project.path, version, spec['target_name'], @@ -929,8 +991,9 @@ def _GenerateMSVSProject(project, options, version, generator_flags): actions_to_add) list_excluded = generator_flags.get('msvs_list_excluded_files', True) sources, excluded_sources, excluded_idl = ( - _AdjustSourcesAndConvertToFilterHierarchy( - spec, options, project_dir, sources, excluded_sources, list_excluded)) + _AdjustSourcesAndConvertToFilterHierarchy(spec, options, project_dir, + sources, excluded_sources, + list_excluded, version)) # Add in files. missing_sources = _VerifySourcesExist(sources, project_dir) @@ -965,7 +1028,7 @@ def _GetUniquePlatforms(spec): The MSVSUserFile object created. """ # Gather list of unique platforms. - platforms = set() + platforms = OrderedSet() for configuration in spec['configurations']: platforms.add(_ConfigPlatform(spec['configurations'][configuration])) platforms = list(platforms) @@ -1152,7 +1215,7 @@ def _GetLibraries(spec): # in libraries that are assumed to be in the default library path). # Also remove duplicate entries, leaving only the last duplicate, while # preserving order. - found = set() + found = OrderedSet() unique_libraries_list = [] for entry in reversed(libraries): library = re.sub('^\-l', '', entry) @@ -1331,8 +1394,7 @@ def _GetMSVSAttributes(spec, config, config_type): def _AddNormalizedSources(sources_set, sources_array): - sources = [_NormalizedSource(s) for s in sources_array] - sources_set.update(set(sources)) + sources_set.update(_NormalizedSource(s) for s in sources_array) def _PrepareListOfSources(spec, generator_flags, gyp_file): @@ -1350,9 +1412,9 @@ def _PrepareListOfSources(spec, generator_flags, gyp_file): A pair of (list of sources, list of excluded sources). The sources will be relative to the gyp file. """ - sources = set() + sources = OrderedSet() _AddNormalizedSources(sources, spec.get('sources', [])) - excluded_sources = set() + excluded_sources = OrderedSet() # Add in the gyp file. if not generator_flags.get('standalone'): sources.add(gyp_file) @@ -1362,7 +1424,7 @@ def _PrepareListOfSources(spec, generator_flags, gyp_file): inputs = a['inputs'] inputs = [_NormalizedSource(i) for i in inputs] # Add all inputs to sources and excluded sources. - inputs = set(inputs) + inputs = OrderedSet(inputs) sources.update(inputs) if not spec.get('msvs_external_builder'): excluded_sources.update(inputs) @@ -1375,7 +1437,7 @@ def _PrepareListOfSources(spec, generator_flags, gyp_file): def _AdjustSourcesAndConvertToFilterHierarchy( - spec, options, gyp_dir, sources, excluded_sources, list_excluded): + spec, options, gyp_dir, sources, excluded_sources, list_excluded, version): """Adjusts the list of sources and excluded sources. Also converts the sets to lists. @@ -1386,12 +1448,13 @@ def _AdjustSourcesAndConvertToFilterHierarchy( gyp_dir: The path to the gyp file being processed. sources: A set of sources to be included for this project. excluded_sources: A set of sources to be excluded for this project. + version: A MSVSVersion object. Returns: A trio of (list of sources, list of excluded sources, path of excluded IDL file) """ # Exclude excluded sources coming into the generator. - excluded_sources.update(set(spec.get('sources_excluded', []))) + excluded_sources.update(OrderedSet(spec.get('sources_excluded', []))) # Add excluded sources into sources for good measure. sources.update(excluded_sources) # Convert to proper windows form. @@ -1410,7 +1473,13 @@ def _AdjustSourcesAndConvertToFilterHierarchy( # Convert to folders and the right slashes. sources = [i.split('\\') for i in sources] sources = _ConvertSourcesToFilterHierarchy(sources, excluded=fully_excluded, - list_excluded=list_excluded) + list_excluded=list_excluded, + msvs_version=version) + + # Prune filters with a single child to flatten ugly directory structures + # such as ../../src/modules/module1 etc. + while len(sources) == 1 and isinstance(sources[0], MSVSProject.Filter): + sources = sources[0].contents return sources, excluded_sources, excluded_idl @@ -1479,7 +1548,7 @@ def _GetExcludedFilesFromBuild(spec, excluded_sources, excluded_idl): def _AddToolFilesToMSVS(p, spec): # Add in tool files (rules). - tool_files = set() + tool_files = OrderedSet() for _, config in spec['configurations'].iteritems(): for f in config.get('msvs_tool_files', []): tool_files.add(f) @@ -3057,9 +3126,7 @@ def _GenerateMSBuildProject(project, options, version, generator_flags): spec = project.spec configurations = spec['configurations'] project_dir, project_file_name = os.path.split(project.path) - msbuildproj_dir = os.path.dirname(project.path) - if msbuildproj_dir and not os.path.exists(msbuildproj_dir): - os.makedirs(msbuildproj_dir) + gyp.common.EnsureDirExists(project.path) # Prepare list of sources and excluded sources. gyp_path = _NormalizedSource(project.build_file) relative_path_of_gyp_file = gyp.common.RelativePath(gyp_path, project_dir) @@ -3088,7 +3155,7 @@ def _GenerateMSBuildProject(project, options, version, generator_flags): _AdjustSourcesAndConvertToFilterHierarchy(spec, options, project_dir, sources, excluded_sources, - list_excluded)) + list_excluded, version)) # Don't add actions if we are using an external builder like ninja. if not spec.get('msvs_external_builder'): @@ -3208,16 +3275,16 @@ def _GenerateActionsForMSBuild(spec, actions_to_add): Returns: A pair of (action specification, the sources handled by this action). """ - sources_handled_by_action = set() + sources_handled_by_action = OrderedSet() actions_spec = [] for primary_input, actions in actions_to_add.iteritems(): - inputs = set() - outputs = set() + inputs = OrderedSet() + outputs = OrderedSet() descriptions = [] commands = [] for action in actions: - inputs.update(set(action['inputs'])) - outputs.update(set(action['outputs'])) + inputs.update(OrderedSet(action['inputs'])) + outputs.update(OrderedSet(action['outputs'])) descriptions.append(action['description']) cmd = action['command'] # For most actions, add 'call' so that actions that invoke batch files diff --git a/deps/npm/node_modules/node-gyp/gyp/pylib/gyp/generator/ninja.py b/deps/npm/node_modules/node-gyp/gyp/pylib/gyp/generator/ninja.py index 85d459e6a..c2951a4c5 100644 --- a/deps/npm/node_modules/node-gyp/gyp/pylib/gyp/generator/ninja.py +++ b/deps/npm/node_modules/node-gyp/gyp/pylib/gyp/generator/ninja.py @@ -814,15 +814,18 @@ class NinjaWriter: cflags_c = self.msvs_settings.GetCflagsC(config_name) cflags_cc = self.msvs_settings.GetCflagsCC(config_name) extra_defines = self.msvs_settings.GetComputedDefines(config_name) - pdbpath = self.msvs_settings.GetCompilerPdbName( + # See comment at cc_command for why there's two .pdb files. + pdbpath_c = pdbpath_cc = self.msvs_settings.GetCompilerPdbName( config_name, self.ExpandSpecial) - if not pdbpath: + if not pdbpath_c: obj = 'obj' if self.toolset != 'target': obj += '.' + self.toolset - pdbpath = os.path.normpath(os.path.join(obj, self.base_dir, - self.name + '.pdb')) - self.WriteVariableList(ninja_file, 'pdbname', [pdbpath]) + pdbpath = os.path.normpath(os.path.join(obj, self.base_dir, self.name)) + pdbpath_c = pdbpath + '.c.pdb' + pdbpath_cc = pdbpath + '.cc.pdb' + self.WriteVariableList(ninja_file, 'pdbname_c', [pdbpath_c]) + self.WriteVariableList(ninja_file, 'pdbname_cc', [pdbpath_cc]) self.WriteVariableList(ninja_file, 'pchprefix', [self.name]) else: cflags = config.get('cflags', []) @@ -1034,15 +1037,21 @@ class NinjaWriter: self.GypPathToNinja, arch) ldflags = env_ldflags + ldflags elif self.flavor == 'win': - manifest_name = self.GypPathToUniqueOutput( + manifest_base_name = self.GypPathToUniqueOutput( self.ComputeOutputFileName(spec)) - ldflags, manifest_files = self.msvs_settings.GetLdflags(config_name, - self.GypPathToNinja, self.ExpandSpecial, manifest_name, is_executable) + ldflags, intermediate_manifest, manifest_files = \ + self.msvs_settings.GetLdflags(config_name, self.GypPathToNinja, + self.ExpandSpecial, manifest_base_name, + output, is_executable, + self.toplevel_build) ldflags = env_ldflags + ldflags self.WriteVariableList(ninja_file, 'manifests', manifest_files) + implicit_deps = implicit_deps.union(manifest_files) + if intermediate_manifest: + self.WriteVariableList( + ninja_file, 'intermediatemanifest', [intermediate_manifest]) command_suffix = _GetWinLinkRuleNameSuffix( - self.msvs_settings.IsEmbedManifest(config_name), - self.msvs_settings.IsLinkIncremental(config_name)) + self.msvs_settings.IsEmbedManifest(config_name)) def_file = self.msvs_settings.GetDefFile(self.GypPathToNinja) if def_file: implicit_deps.add(def_file) @@ -1087,16 +1096,27 @@ class NinjaWriter: extra_bindings.append(('lib', gyp.common.EncodePOSIXShellArgument(output))) if self.flavor == 'win': - extra_bindings.append(('dll', output)) + extra_bindings.append(('binary', output)) if '/NOENTRY' not in ldflags: self.target.import_lib = output + '.lib' extra_bindings.append(('implibflag', '/IMPLIB:%s' % self.target.import_lib)) + pdbname = self.msvs_settings.GetPDBName( + config_name, self.ExpandSpecial, output + '.pdb') output = [output, self.target.import_lib] + if pdbname: + output.append(pdbname) elif not self.is_mac_bundle: output = [output, output + '.TOC'] else: command = command + '_notoc' + elif self.flavor == 'win': + extra_bindings.append(('binary', output)) + pdbname = self.msvs_settings.GetPDBName( + config_name, self.ExpandSpecial, output + '.pdb') + if pdbname: + output = [output, pdbname] + if len(solibs): extra_bindings.append(('solibs', gyp.common.EncodePOSIXShellList(solibs))) @@ -1502,10 +1522,7 @@ def CalculateGeneratorInputInfo(params): def OpenOutput(path, mode='w'): """Open |path| for writing, creating directories if necessary.""" - try: - os.makedirs(os.path.dirname(path)) - except OSError: - pass + gyp.common.EnsureDirExists(path) return open(path, mode) @@ -1540,7 +1557,10 @@ def GetDefaultConcurrentLinks(): mem_limit = max(1, stat.ullTotalPhys / (4 * (2 ** 30))) # total / 4GB hard_cap = max(1, int(os.getenv('GYP_LINK_CONCURRENCY_MAX', 2**32))) - return min(mem_limit, hard_cap) + # return min(mem_limit, hard_cap) + # TODO(scottmg): Temporary speculative fix for OOM on builders + # See http://crbug.com/333000. + return 2 elif sys.platform.startswith('linux'): with open("/proc/meminfo") as meminfo: memtotal_re = re.compile(r'^MemTotal:\s*(\d*)\s*kB') @@ -1564,81 +1584,57 @@ def GetDefaultConcurrentLinks(): return 1 -def _GetWinLinkRuleNameSuffix(embed_manifest, link_incremental): +def _GetWinLinkRuleNameSuffix(embed_manifest): """Returns the suffix used to select an appropriate linking rule depending on - whether the manifest embedding and/or incremental linking is enabled.""" - suffix = '' - if embed_manifest: - suffix += '_embed' - if link_incremental: - suffix += '_inc' - return suffix + whether the manifest embedding is enabled.""" + return '_embed' if embed_manifest else '' -def _AddWinLinkRules(master_ninja, embed_manifest, link_incremental): +def _AddWinLinkRules(master_ninja, embed_manifest): """Adds link rules for Windows platform to |master_ninja|.""" def FullLinkCommand(ldcmd, out, binary_type): - cmd = ('cmd /c %(ldcmd)s' - ' && %(python)s gyp-win-tool manifest-wrapper $arch' - ' cmd /c if exist %(out)s.manifest del %(out)s.manifest' - ' && %(python)s gyp-win-tool manifest-wrapper $arch' - ' $mt -nologo -manifest $manifests') - if embed_manifest and not link_incremental: - # Embed manifest into a binary. If incremental linking is enabled, - # embedding is postponed to the re-linking stage (see below). - cmd += ' -outputresource:%(out)s;%(resname)s' - else: - # Save manifest as an external file. - cmd += ' -out:%(out)s.manifest' - if link_incremental: - # There is no point in generating separate rule for the case when - # incremental linking is enabled, but manifest embedding is disabled. - # In that case the basic rule should be used (e.g. 'link'). - # See also implementation of _GetWinLinkRuleNameSuffix(). - assert embed_manifest - # Make .rc file out of manifest, compile it to .res file and re-link. - cmd += (' && %(python)s gyp-win-tool manifest-to-rc $arch' - ' %(out)s.manifest %(out)s.manifest.rc %(resname)s' - ' && %(python)s gyp-win-tool rc-wrapper $arch $rc' - ' %(out)s.manifest.rc' - ' && %(ldcmd)s %(out)s.manifest.res') resource_name = { 'exe': '1', 'dll': '2', }[binary_type] - return cmd % {'python': sys.executable, - 'out': out, - 'ldcmd': ldcmd, - 'resname': resource_name} - - rule_name_suffix = _GetWinLinkRuleNameSuffix(embed_manifest, link_incremental) - dlldesc = 'LINK%s(DLL) $dll' % rule_name_suffix.upper() - dllcmd = ('%s gyp-win-tool link-wrapper $arch ' - '$ld /nologo $implibflag /DLL /OUT:$dll ' - '/PDB:$dll.pdb @$dll.rsp' % sys.executable) - dllcmd = FullLinkCommand(dllcmd, '$dll', 'dll') + return '%(python)s gyp-win-tool link-with-manifests $arch %(embed)s ' \ + '%(out)s "%(ldcmd)s" %(resname)s $mt $rc "$intermediatemanifest" ' \ + '$manifests' % { + 'python': sys.executable, + 'out': out, + 'ldcmd': ldcmd, + 'resname': resource_name, + 'embed': embed_manifest } + rule_name_suffix = _GetWinLinkRuleNameSuffix(embed_manifest) + use_separate_mspdbsrv = ( + int(os.environ.get('GYP_USE_SEPARATE_MSPDBSRV', '0')) != 0) + dlldesc = 'LINK%s(DLL) $binary' % rule_name_suffix.upper() + dllcmd = ('%s gyp-win-tool link-wrapper $arch %s ' + '$ld /nologo $implibflag /DLL /OUT:$binary ' + '@$binary.rsp' % (sys.executable, use_separate_mspdbsrv)) + dllcmd = FullLinkCommand(dllcmd, '$binary', 'dll') master_ninja.rule('solink' + rule_name_suffix, description=dlldesc, command=dllcmd, - rspfile='$dll.rsp', + rspfile='$binary.rsp', rspfile_content='$libs $in_newline $ldflags', restat=True, pool='link_pool') master_ninja.rule('solink_module' + rule_name_suffix, description=dlldesc, command=dllcmd, - rspfile='$dll.rsp', + rspfile='$binary.rsp', rspfile_content='$libs $in_newline $ldflags', restat=True, pool='link_pool') # Note that ldflags goes at the end so that it has the option of # overriding default settings earlier in the command line. - exe_cmd = ('%s gyp-win-tool link-wrapper $arch ' - '$ld /nologo /OUT:$out /PDB:$out.pdb @$out.rsp' % - sys.executable) - exe_cmd = FullLinkCommand(exe_cmd, '$out', 'exe') + exe_cmd = ('%s gyp-win-tool link-wrapper $arch %s ' + '$ld /nologo /OUT:$binary @$binary.rsp' % + (sys.executable, use_separate_mspdbsrv)) + exe_cmd = FullLinkCommand(exe_cmd, '$binary', 'exe') master_ninja.rule('link' + rule_name_suffix, - description='LINK%s $out' % rule_name_suffix.upper(), + description='LINK%s $binary' % rule_name_suffix.upper(), command=exe_cmd, - rspfile='$out.rsp', + rspfile='$binary.rsp', rspfile_content='$in_newline $libs $ldflags', pool='link_pool') @@ -1656,9 +1652,8 @@ def GenerateOutputForConfig(target_list, target_dicts, data, params, toplevel_build = os.path.join(options.toplevel_dir, build_dir) - master_ninja = ninja_syntax.Writer( - OpenOutput(os.path.join(toplevel_build, 'build.ninja')), - width=120) + master_ninja_file = OpenOutput(os.path.join(toplevel_build, 'build.ninja')) + master_ninja = ninja_syntax.Writer(master_ninja_file, width=120) # Put build-time support tools in out/{config_name}. gyp.common.CopyTool(flavor, toplevel_build) @@ -1679,8 +1674,8 @@ def GenerateOutputForConfig(target_list, target_dicts, data, params, ld = 'link.exe' ld_host = '$ld' else: - cc = 'gcc' - cxx = 'g++' + cc = 'cc' + cxx = 'c++' ld = '$cc' ldxx = '$cxx' ld_host = '$cc_host' @@ -1798,14 +1793,20 @@ def GenerateOutputForConfig(target_list, target_dicts, data, params, depfile='$out.d', deps=deps) else: + # TODO(scottmg) Separate pdb names is a test to see if it works around + # http://crbug.com/142362. It seems there's a race between the creation of + # the .pdb by the precompiled header step for .cc and the compilation of + # .c files. This should be handled by mspdbsrv, but rarely errors out with + # c1xx : fatal error C1033: cannot open program database + # By making the rules target separate pdb files this might be avoided. cc_command = ('ninja -t msvc -e $arch ' + '-- ' '$cc /nologo /showIncludes /FC ' - '@$out.rsp /c $in /Fo$out /Fd$pdbname ') + '@$out.rsp /c $in /Fo$out /Fd$pdbname_c ') cxx_command = ('ninja -t msvc -e $arch ' + '-- ' '$cxx /nologo /showIncludes /FC ' - '@$out.rsp /c $in /Fo$out /Fd$pdbname ') + '@$out.rsp /c $in /Fo$out /Fd$pdbname_cc ') master_ninja.rule( 'cc', description='CC $out', @@ -1893,17 +1894,13 @@ def GenerateOutputForConfig(target_list, target_dicts, data, params, master_ninja.rule( 'alink', description='LIB $out', - command=('%s gyp-win-tool link-wrapper $arch ' + command=('%s gyp-win-tool link-wrapper $arch False ' '$ar /nologo /ignore:4221 /OUT:$out @$out.rsp' % sys.executable), rspfile='$out.rsp', rspfile_content='$in_newline $libflags') - _AddWinLinkRules(master_ninja, embed_manifest=True, link_incremental=True) - _AddWinLinkRules(master_ninja, embed_manifest=True, link_incremental=False) - _AddWinLinkRules(master_ninja, embed_manifest=False, link_incremental=False) - # Do not generate rules for embed_manifest=False and link_incremental=True - # because in that case rules for (False, False) should be used (see - # implementation of _GetWinLinkRuleNameSuffix()). + _AddWinLinkRules(master_ninja, embed_manifest=True) + _AddWinLinkRules(master_ninja, embed_manifest=False) else: master_ninja.rule( 'objc', @@ -2047,7 +2044,8 @@ def GenerateOutputForConfig(target_list, target_dicts, data, params, this_make_global_settings = data[build_file].get('make_global_settings', []) assert make_global_settings == this_make_global_settings, ( - "make_global_settings needs to be the same for all targets.") + "make_global_settings needs to be the same for all targets. %s vs. %s" % + (this_make_global_settings, make_global_settings)) spec = target_dicts[qualified_target] if flavor == 'mac': @@ -2098,6 +2096,8 @@ def GenerateOutputForConfig(target_list, target_dicts, data, params, master_ninja.build('all', 'phony', list(all_outputs)) master_ninja.default(generator_flags.get('default_target', 'all')) + master_ninja_file.close() + def PerformBuild(data, configurations, params): options = params['options'] diff --git a/deps/npm/node_modules/node-gyp/gyp/pylib/gyp/input.py b/deps/npm/node_modules/node-gyp/gyp/pylib/gyp/input.py index 45e791d14..6472912db 100644 --- a/deps/npm/node_modules/node-gyp/gyp/pylib/gyp/input.py +++ b/deps/npm/node_modules/node-gyp/gyp/pylib/gyp/input.py @@ -822,8 +822,7 @@ def ExpandVariables(input, phase, variables, build_file): rel_build_file_dir = build_file_dir qualified_out_dir = generator_filelist_paths['qualified_out_dir'] path = os.path.join(qualified_out_dir, rel_build_file_dir, replacement) - if not os.path.isdir(os.path.dirname(path)): - os.makedirs(os.path.dirname(path)) + gyp.common.EnsureDirExists(path) replacement = gyp.common.RelativePath(path, build_file_dir) f = gyp.common.WriteOnDiff(path) @@ -2278,6 +2277,7 @@ def ProcessListFiltersInDict(name, the_dict): continue if not isinstance(the_dict[list_key], list): + value = the_dict[list_key] raise ValueError, name + ' key ' + list_key + \ ' must be list, not ' + \ value.__class__.__name__ + ' when applying ' + \ diff --git a/deps/npm/node_modules/node-gyp/gyp/pylib/gyp/mac_tool.py b/deps/npm/node_modules/node-gyp/gyp/pylib/gyp/mac_tool.py index 20b3a4865..ac19b6dc8 100755 --- a/deps/npm/node_modules/node-gyp/gyp/pylib/gyp/mac_tool.py +++ b/deps/npm/node_modules/node-gyp/gyp/pylib/gyp/mac_tool.py @@ -9,6 +9,8 @@ These functions are executed via gyp-mac-tool when using the Makefile generator. """ import fcntl +import fnmatch +import glob import json import os import plistlib @@ -17,6 +19,7 @@ import shutil import string import subprocess import sys +import tempfile def main(args): @@ -259,6 +262,250 @@ class MacTool(object): os.remove(link) os.symlink(dest, link) + def ExecCodeSignBundle(self, key, resource_rules, entitlements, provisioning): + """Code sign a bundle. + + This function tries to code sign an iOS bundle, following the same + algorithm as Xcode: + 1. copy ResourceRules.plist from the user or the SDK into the bundle, + 2. pick the provisioning profile that best match the bundle identifier, + and copy it into the bundle as embedded.mobileprovision, + 3. copy Entitlements.plist from user or SDK next to the bundle, + 4. code sign the bundle. + """ + resource_rules_path = self._InstallResourceRules(resource_rules) + substitutions, overrides = self._InstallProvisioningProfile( + provisioning, self._GetCFBundleIdentifier()) + entitlements_path = self._InstallEntitlements( + entitlements, substitutions, overrides) + subprocess.check_call([ + 'codesign', '--force', '--sign', key, '--resource-rules', + resource_rules_path, '--entitlements', entitlements_path, + os.path.join( + os.environ['TARGET_BUILD_DIR'], + os.environ['FULL_PRODUCT_NAME'])]) + + def _InstallResourceRules(self, resource_rules): + """Installs ResourceRules.plist from user or SDK into the bundle. + + Args: + resource_rules: string, optional, path to the ResourceRules.plist file + to use, default to "${SDKROOT}/ResourceRules.plist" + + Returns: + Path to the copy of ResourceRules.plist into the bundle. + """ + source_path = resource_rules + target_path = os.path.join( + os.environ['BUILT_PRODUCTS_DIR'], + os.environ['CONTENTS_FOLDER_PATH'], + 'ResourceRules.plist') + if not source_path: + source_path = os.path.join( + os.environ['SDKROOT'], 'ResourceRules.plist') + shutil.copy2(source_path, target_path) + return target_path + + def _InstallProvisioningProfile(self, profile, bundle_identifier): + """Installs embedded.mobileprovision into the bundle. + + Args: + profile: string, optional, short name of the .mobileprovision file + to use, if empty or the file is missing, the best file installed + will be used + bundle_identifier: string, value of CFBundleIdentifier from Info.plist + + Returns: + A tuple containing two dictionary: variables substitutions and values + to overrides when generating the entitlements file. + """ + source_path, provisioning_data, team_id = self._FindProvisioningProfile( + profile, bundle_identifier) + target_path = os.path.join( + os.environ['BUILT_PRODUCTS_DIR'], + os.environ['CONTENTS_FOLDER_PATH'], + 'embedded.mobileprovision') + shutil.copy2(source_path, target_path) + substitutions = self._GetSubstitutions(bundle_identifier, team_id + '.') + return substitutions, provisioning_data['Entitlements'] + + def _FindProvisioningProfile(self, profile, bundle_identifier): + """Finds the .mobileprovision file to use for signing the bundle. + + Checks all the installed provisioning profiles (or if the user specified + the PROVISIONING_PROFILE variable, only consult it) and select the most + specific that correspond to the bundle identifier. + + Args: + profile: string, optional, short name of the .mobileprovision file + to use, if empty or the file is missing, the best file installed + will be used + bundle_identifier: string, value of CFBundleIdentifier from Info.plist + + Returns: + A tuple of the path to the selected provisioning profile, the data of + the embedded plist in the provisioning profile and the team identifier + to use for code signing. + + Raises: + SystemExit: if no .mobileprovision can be used to sign the bundle. + """ + profiles_dir = os.path.join( + os.environ['HOME'], 'Library', 'MobileDevice', 'Provisioning Profiles') + if not os.path.isdir(profiles_dir): + print >>sys.stderr, ( + 'cannot find mobile provisioning for %s' % bundle_identifier) + sys.exit(1) + provisioning_profiles = None + if profile: + profile_path = os.path.join(profiles_dir, profile + '.mobileprovision') + if os.path.exists(profile_path): + provisioning_profiles = [profile_path] + if not provisioning_profiles: + provisioning_profiles = glob.glob( + os.path.join(profiles_dir, '*.mobileprovision')) + valid_provisioning_profiles = {} + for profile_path in provisioning_profiles: + profile_data = self._LoadProvisioningProfile(profile_path) + app_id_pattern = profile_data.get( + 'Entitlements', {}).get('application-identifier', '') + for team_identifier in profile_data.get('TeamIdentifier', []): + app_id = '%s.%s' % (team_identifier, bundle_identifier) + if fnmatch.fnmatch(app_id, app_id_pattern): + valid_provisioning_profiles[app_id_pattern] = ( + profile_path, profile_data, team_identifier) + if not valid_provisioning_profiles: + print >>sys.stderr, ( + 'cannot find mobile provisioning for %s' % bundle_identifier) + sys.exit(1) + # If the user has multiple provisioning profiles installed that can be + # used for ${bundle_identifier}, pick the most specific one (ie. the + # provisioning profile whose pattern is the longest). + selected_key = max(valid_provisioning_profiles, key=lambda v: len(v)) + return valid_provisioning_profiles[selected_key] + + def _LoadProvisioningProfile(self, profile_path): + """Extracts the plist embedded in a provisioning profile. + + Args: + profile_path: string, path to the .mobileprovision file + + Returns: + Content of the plist embedded in the provisioning profile as a dictionary. + """ + with tempfile.NamedTemporaryFile() as temp: + subprocess.check_call([ + 'security', 'cms', '-D', '-i', profile_path, '-o', temp.name]) + return self._LoadPlistMaybeBinary(temp.name) + + def _LoadPlistMaybeBinary(self, plist_path): + """Loads into a memory a plist possibly encoded in binary format. + + This is a wrapper around plistlib.readPlist that tries to convert the + plist to the XML format if it can't be parsed (assuming that it is in + the binary format). + + Args: + plist_path: string, path to a plist file, in XML or binary format + + Returns: + Content of the plist as a dictionary. + """ + try: + # First, try to read the file using plistlib that only supports XML, + # and if an exception is raised, convert a temporary copy to XML and + # load that copy. + return plistlib.readPlist(plist_path) + except: + pass + with tempfile.NamedTemporaryFile() as temp: + shutil.copy2(plist_path, temp.name) + subprocess.check_call(['plutil', '-convert', 'xml1', temp.name]) + return plistlib.readPlist(temp.name) + + def _GetSubstitutions(self, bundle_identifier, app_identifier_prefix): + """Constructs a dictionary of variable substitutions for Entitlements.plist. + + Args: + bundle_identifier: string, value of CFBundleIdentifier from Info.plist + app_identifier_prefix: string, value for AppIdentifierPrefix + + Returns: + Dictionary of substitutions to apply when generating Entitlements.plist. + """ + return { + 'CFBundleIdentifier': bundle_identifier, + 'AppIdentifierPrefix': app_identifier_prefix, + } + + def _GetCFBundleIdentifier(self): + """Extracts CFBundleIdentifier value from Info.plist in the bundle. + + Returns: + Value of CFBundleIdentifier in the Info.plist located in the bundle. + """ + info_plist_path = os.path.join( + os.environ['TARGET_BUILD_DIR'], + os.environ['INFOPLIST_PATH']) + info_plist_data = self._LoadPlistMaybeBinary(info_plist_path) + return info_plist_data['CFBundleIdentifier'] + + def _InstallEntitlements(self, entitlements, substitutions, overrides): + """Generates and install the ${BundleName}.xcent entitlements file. + + Expands variables "$(variable)" pattern in the source entitlements file, + add extra entitlements defined in the .mobileprovision file and the copy + the generated plist to "${BundlePath}.xcent". + + Args: + entitlements: string, optional, path to the Entitlements.plist template + to use, defaults to "${SDKROOT}/Entitlements.plist" + substitutions: dictionary, variable substitutions + overrides: dictionary, values to add to the entitlements + + Returns: + Path to the generated entitlements file. + """ + source_path = entitlements + target_path = os.path.join( + os.environ['BUILT_PRODUCTS_DIR'], + os.environ['PRODUCT_NAME'] + '.xcent') + if not source_path: + source_path = os.path.join( + os.environ['SDKROOT'], + 'Entitlements.plist') + shutil.copy2(source_path, target_path) + data = self._LoadPlistMaybeBinary(target_path) + data = self._ExpandVariables(data, substitutions) + if overrides: + for key in overrides: + if key not in data: + data[key] = overrides[key] + plistlib.writePlist(data, target_path) + return target_path + + def _ExpandVariables(self, data, substitutions): + """Expands variables "$(variable)" in data. + + Args: + data: object, can be either string, list or dictionary + substitutions: dictionary, variable substitutions to perform + + Returns: + Copy of data where each references to "$(variable)" has been replaced + by the corresponding value found in substitutions, or left intact if + the key was not found. + """ + if isinstance(data, str): + for key, value in substitutions.iteritems(): + data = data.replace('$(%s)' % key, value) + return data + if isinstance(data, list): + return [self._ExpandVariables(v, substitutions) for v in data] + if isinstance(data, dict): + return dict((k, self._ExpandVariables(data[k], + substitutions)) for k in data) + return data if __name__ == '__main__': sys.exit(main(sys.argv[1:])) diff --git a/deps/npm/node_modules/node-gyp/gyp/pylib/gyp/msvs_emulation.py b/deps/npm/node_modules/node-gyp/gyp/pylib/gyp/msvs_emulation.py index 3ac153dd8..6428fced0 100644 --- a/deps/npm/node_modules/node-gyp/gyp/pylib/gyp/msvs_emulation.py +++ b/deps/npm/node_modules/node-gyp/gyp/pylib/gyp/msvs_emulation.py @@ -317,15 +317,20 @@ class MsvsSettings(object): output_file, config=config)) return output_file - def GetPDBName(self, config, expand_special): - """Gets the explicitly overridden pdb name for a target or returns None - if it's not overridden.""" + def GetPDBName(self, config, expand_special, default): + """Gets the explicitly overridden pdb name for a target or returns + default if it's not overridden, or if no pdb will be generated.""" config = self._TargetConfig(config) output_file = self._Setting(('VCLinkerTool', 'ProgramDatabaseFile'), config) - if output_file: - output_file = expand_special(self.ConvertVSMacros( - output_file, config=config)) - return output_file + generate_debug_info = self._Setting( + ('VCLinkerTool', 'GenerateDebugInformation'), config) + if generate_debug_info: + if output_file: + return expand_special(self.ConvertVSMacros(output_file, config=config)) + else: + return default + else: + return None def GetCflags(self, config): """Returns the flags that need to be added to .c and .cc compilations.""" @@ -420,6 +425,7 @@ class MsvsSettings(object): libflags.extend(self._GetAdditionalLibraryDirectories( 'VCLibrarianTool', config, gyp_to_build_path)) lib('LinkTimeCodeGeneration', map={'true': '/LTCG'}) + lib('TargetMachine', map={'1': 'X86', '17': 'X64'}, prefix='/MACHINE:') lib('AdditionalOptions') return libflags @@ -441,8 +447,19 @@ class MsvsSettings(object): if def_file: ldflags.append('/DEF:"%s"' % def_file) + def GetPGDName(self, config, expand_special): + """Gets the explicitly overridden pgd name for a target or returns None + if it's not overridden.""" + config = self._TargetConfig(config) + output_file = self._Setting( + ('VCLinkerTool', 'ProfileGuidedDatabase'), config) + if output_file: + output_file = expand_special(self.ConvertVSMacros( + output_file, config=config)) + return output_file + def GetLdflags(self, config, gyp_to_build_path, expand_special, - manifest_base_name, is_executable): + manifest_base_name, output_name, is_executable, build_dir): """Returns the flags that need to be added to link commands, and the manifest files.""" config = self._TargetConfig(config) @@ -455,28 +472,47 @@ class MsvsSettings(object): ldflags.extend(self._GetAdditionalLibraryDirectories( 'VCLinkerTool', config, gyp_to_build_path)) ld('DelayLoadDLLs', prefix='/DELAYLOAD:') + ld('TreatLinkerWarningAsErrors', prefix='/WX', + map={'true': '', 'false': ':NO'}) out = self.GetOutputName(config, expand_special) if out: ldflags.append('/OUT:' + out) - pdb = self.GetPDBName(config, expand_special) + pdb = self.GetPDBName(config, expand_special, output_name + '.pdb') if pdb: ldflags.append('/PDB:' + pdb) + pgd = self.GetPGDName(config, expand_special) + if pgd: + ldflags.append('/PGD:' + pgd) map_file = self.GetMapFileName(config, expand_special) ld('GenerateMapFile', map={'true': '/MAP:' + map_file if map_file else '/MAP'}) ld('MapExports', map={'true': '/MAPINFO:EXPORTS'}) ld('AdditionalOptions', prefix='') - ld('SubSystem', map={'1': 'CONSOLE', '2': 'WINDOWS'}, prefix='/SUBSYSTEM:') + + minimum_required_version = self._Setting( + ('VCLinkerTool', 'MinimumRequiredVersion'), config, default='') + if minimum_required_version: + minimum_required_version = ',' + minimum_required_version + ld('SubSystem', + map={'1': 'CONSOLE%s' % minimum_required_version, + '2': 'WINDOWS%s' % minimum_required_version}, + prefix='/SUBSYSTEM:') + ld('TerminalServerAware', map={'1': ':NO', '2': ''}, prefix='/TSAWARE') ld('LinkIncremental', map={'1': ':NO', '2': ''}, prefix='/INCREMENTAL') + ld('BaseAddress', prefix='/BASE:') ld('FixedBaseAddress', map={'1': ':NO', '2': ''}, prefix='/FIXED') ld('RandomizedBaseAddress', map={'1': ':NO', '2': ''}, prefix='/DYNAMICBASE') ld('DataExecutionPrevention', map={'1': ':NO', '2': ''}, prefix='/NXCOMPAT') ld('OptimizeReferences', map={'1': 'NOREF', '2': 'REF'}, prefix='/OPT:') + ld('ForceSymbolReferences', prefix='/INCLUDE:') ld('EnableCOMDATFolding', map={'1': 'NOICF', '2': 'ICF'}, prefix='/OPT:') - ld('LinkTimeCodeGeneration', map={'1': '/LTCG'}) + ld('LinkTimeCodeGeneration', + map={'1': '', '2': ':PGINSTRUMENT', '3': ':PGOPTIMIZE', + '4': ':PGUPDATE'}, + prefix='/LTCG') ld('IgnoreDefaultLibraryNames', prefix='/NODEFAULTLIB:') ld('ResourceOnlyDLL', map={'true': '/NOENTRY'}) ld('EntryPointSymbol', prefix='/ENTRY:') @@ -501,27 +537,55 @@ class MsvsSettings(object): ldflags.append('/NXCOMPAT') have_def_file = filter(lambda x: x.startswith('/DEF:'), ldflags) - manifest_flags, intermediate_manifest_file = self._GetLdManifestFlags( - config, manifest_base_name, is_executable and not have_def_file) + manifest_flags, intermediate_manifest, manifest_files = \ + self._GetLdManifestFlags(config, manifest_base_name, gyp_to_build_path, + is_executable and not have_def_file, build_dir) ldflags.extend(manifest_flags) - manifest_files = self._GetAdditionalManifestFiles(config, gyp_to_build_path) - manifest_files.append(intermediate_manifest_file) - - return ldflags, manifest_files + return ldflags, intermediate_manifest, manifest_files + + def _GetLdManifestFlags(self, config, name, gyp_to_build_path, + allow_isolation, build_dir): + """Returns a 3-tuple: + - the set of flags that need to be added to the link to generate + a default manifest + - the intermediate manifest that the linker will generate that should be + used to assert it doesn't add anything to the merged one. + - the list of all the manifest files to be merged by the manifest tool and + included into the link.""" + generate_manifest = self._Setting(('VCLinkerTool', 'GenerateManifest'), + config, + default='true') + if generate_manifest != 'true': + # This means not only that the linker should not generate the intermediate + # manifest but also that the manifest tool should do nothing even when + # additional manifests are specified. + return ['/MANIFEST:NO'], [], [] - def _GetLdManifestFlags(self, config, name, allow_isolation): - """Returns the set of flags that need to be added to the link to generate - a default manifest, as well as the name of the generated file.""" - # The manifest is generated by default. output_name = name + '.intermediate.manifest' flags = [ '/MANIFEST', '/ManifestFile:' + output_name, ] + # Instead of using the MANIFESTUAC flags, we generate a .manifest to + # include into the list of manifests. This allows us to avoid the need to + # do two passes during linking. The /MANIFEST flag and /ManifestFile are + # still used, and the intermediate manifest is used to assert that the + # final manifest we get from merging all the additional manifest files + # (plus the one we generate here) isn't modified by merging the + # intermediate into it. + + # Always NO, because we generate a manifest file that has what we want. + flags.append('/MANIFESTUAC:NO') + config = self._TargetConfig(config) enable_uac = self._Setting(('VCLinkerTool', 'EnableUAC'), config, default='true') + manifest_files = [] + generated_manifest_outer = \ +"<?xml version='1.0' encoding='UTF-8' standalone='yes'?>" \ +"<assembly xmlns='urn:schemas-microsoft-com:asm.v1' manifestVersion='1.0'>%s" \ +"</assembly>" if enable_uac == 'true': execution_level = self._Setting(('VCLinkerTool', 'UACExecutionLevel'), config, default='0') @@ -533,14 +597,38 @@ class MsvsSettings(object): ui_access = self._Setting(('VCLinkerTool', 'UACUIAccess'), config, default='false') - flags.append('''/MANIFESTUAC:"level='%s' uiAccess='%s'"''' % - (execution_level_map[execution_level], ui_access)) + + inner = ''' +<trustInfo xmlns="urn:schemas-microsoft-com:asm.v3"> + <security> + <requestedPrivileges> + <requestedExecutionLevel level='%s' uiAccess='%s' /> + </requestedPrivileges> + </security> +</trustInfo>''' % (execution_level_map[execution_level], ui_access) else: - flags.append('/MANIFESTUAC:NO') + inner = '' + + generated_manifest_contents = generated_manifest_outer % inner + generated_name = name + '.generated.manifest' + # Need to join with the build_dir here as we're writing it during + # generation time, but we return the un-joined version because the build + # will occur in that directory. We only write the file if the contents + # have changed so that simply regenerating the project files doesn't + # cause a relink. + build_dir_generated_name = os.path.join(build_dir, generated_name) + gyp.common.EnsureDirExists(build_dir_generated_name) + f = gyp.common.WriteOnDiff(build_dir_generated_name) + f.write(generated_manifest_contents) + f.close() + manifest_files = [generated_name] if allow_isolation: flags.append('/ALLOWISOLATION') - return flags, output_name + + manifest_files += self._GetAdditionalManifestFiles(config, + gyp_to_build_path) + return flags, output_name, manifest_files def _GetAdditionalManifestFiles(self, config, gyp_to_build_path): """Gets additional manifest files that are added to the default one @@ -563,7 +651,8 @@ class MsvsSettings(object): def IsEmbedManifest(self, config): """Returns whether manifest should be linked into binary.""" config = self._TargetConfig(config) - embed = self._Setting(('VCManifestTool', 'EmbedManifest'), config) + embed = self._Setting(('VCManifestTool', 'EmbedManifest'), config, + default='true') return embed == 'true' def IsLinkIncremental(self, config): diff --git a/deps/npm/node_modules/node-gyp/gyp/pylib/gyp/ordered_dict.py b/deps/npm/node_modules/node-gyp/gyp/pylib/gyp/ordered_dict.py new file mode 100644 index 000000000..a1e89f919 --- /dev/null +++ b/deps/npm/node_modules/node-gyp/gyp/pylib/gyp/ordered_dict.py @@ -0,0 +1,289 @@ +# Unmodified from http://code.activestate.com/recipes/576693/ +# other than to add MIT license header (as specified on page, but not in code). +# Linked from Python documentation here: +# http://docs.python.org/2/library/collections.html#collections.OrderedDict +# +# This should be deleted once Py2.7 is available on all bots, see +# http://crbug.com/241769. +# +# Copyright (c) 2009 Raymond Hettinger. +# +# 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. + +# Backport of OrderedDict() class that runs on Python 2.4, 2.5, 2.6, 2.7 and pypy. +# Passes Python2.7's test suite and incorporates all the latest updates. + +try: + from thread import get_ident as _get_ident +except ImportError: + from dummy_thread import get_ident as _get_ident + +try: + from _abcoll import KeysView, ValuesView, ItemsView +except ImportError: + pass + + +class OrderedDict(dict): + 'Dictionary that remembers insertion order' + # An inherited dict maps keys to values. + # The inherited dict provides __getitem__, __len__, __contains__, and get. + # The remaining methods are order-aware. + # Big-O running times for all methods are the same as for regular dictionaries. + + # The internal self.__map dictionary maps keys to links in a doubly linked list. + # The circular doubly linked list starts and ends with a sentinel element. + # The sentinel element never gets deleted (this simplifies the algorithm). + # Each link is stored as a list of length three: [PREV, NEXT, KEY]. + + def __init__(self, *args, **kwds): + '''Initialize an ordered dictionary. Signature is the same as for + regular dictionaries, but keyword arguments are not recommended + because their insertion order is arbitrary. + + ''' + if len(args) > 1: + raise TypeError('expected at most 1 arguments, got %d' % len(args)) + try: + self.__root + except AttributeError: + self.__root = root = [] # sentinel node + root[:] = [root, root, None] + self.__map = {} + self.__update(*args, **kwds) + + def __setitem__(self, key, value, dict_setitem=dict.__setitem__): + 'od.__setitem__(i, y) <==> od[i]=y' + # Setting a new item creates a new link which goes at the end of the linked + # list, and the inherited dictionary is updated with the new key/value pair. + if key not in self: + root = self.__root + last = root[0] + last[1] = root[0] = self.__map[key] = [last, root, key] + dict_setitem(self, key, value) + + def __delitem__(self, key, dict_delitem=dict.__delitem__): + 'od.__delitem__(y) <==> del od[y]' + # Deleting an existing item uses self.__map to find the link which is + # then removed by updating the links in the predecessor and successor nodes. + dict_delitem(self, key) + link_prev, link_next, key = self.__map.pop(key) + link_prev[1] = link_next + link_next[0] = link_prev + + def __iter__(self): + 'od.__iter__() <==> iter(od)' + root = self.__root + curr = root[1] + while curr is not root: + yield curr[2] + curr = curr[1] + + def __reversed__(self): + 'od.__reversed__() <==> reversed(od)' + root = self.__root + curr = root[0] + while curr is not root: + yield curr[2] + curr = curr[0] + + def clear(self): + 'od.clear() -> None. Remove all items from od.' + try: + for node in self.__map.itervalues(): + del node[:] + root = self.__root + root[:] = [root, root, None] + self.__map.clear() + except AttributeError: + pass + dict.clear(self) + + def popitem(self, last=True): + '''od.popitem() -> (k, v), return and remove a (key, value) pair. + Pairs are returned in LIFO order if last is true or FIFO order if false. + + ''' + if not self: + raise KeyError('dictionary is empty') + root = self.__root + if last: + link = root[0] + link_prev = link[0] + link_prev[1] = root + root[0] = link_prev + else: + link = root[1] + link_next = link[1] + root[1] = link_next + link_next[0] = root + key = link[2] + del self.__map[key] + value = dict.pop(self, key) + return key, value + + # -- the following methods do not depend on the internal structure -- + + def keys(self): + 'od.keys() -> list of keys in od' + return list(self) + + def values(self): + 'od.values() -> list of values in od' + return [self[key] for key in self] + + def items(self): + 'od.items() -> list of (key, value) pairs in od' + return [(key, self[key]) for key in self] + + def iterkeys(self): + 'od.iterkeys() -> an iterator over the keys in od' + return iter(self) + + def itervalues(self): + 'od.itervalues -> an iterator over the values in od' + for k in self: + yield self[k] + + def iteritems(self): + 'od.iteritems -> an iterator over the (key, value) items in od' + for k in self: + yield (k, self[k]) + + # Suppress 'OrderedDict.update: Method has no argument': + # pylint: disable=E0211 + def update(*args, **kwds): + '''od.update(E, **F) -> None. Update od from dict/iterable E and F. + + If E is a dict instance, does: for k in E: od[k] = E[k] + If E has a .keys() method, does: for k in E.keys(): od[k] = E[k] + Or if E is an iterable of items, does: for k, v in E: od[k] = v + In either case, this is followed by: for k, v in F.items(): od[k] = v + + ''' + if len(args) > 2: + raise TypeError('update() takes at most 2 positional ' + 'arguments (%d given)' % (len(args),)) + elif not args: + raise TypeError('update() takes at least 1 argument (0 given)') + self = args[0] + # Make progressively weaker assumptions about "other" + other = () + if len(args) == 2: + other = args[1] + if isinstance(other, dict): + for key in other: + self[key] = other[key] + elif hasattr(other, 'keys'): + for key in other.keys(): + self[key] = other[key] + else: + for key, value in other: + self[key] = value + for key, value in kwds.items(): + self[key] = value + + __update = update # let subclasses override update without breaking __init__ + + __marker = object() + + def pop(self, key, default=__marker): + '''od.pop(k[,d]) -> v, remove specified key and return the corresponding value. + If key is not found, d is returned if given, otherwise KeyError is raised. + + ''' + if key in self: + result = self[key] + del self[key] + return result + if default is self.__marker: + raise KeyError(key) + return default + + def setdefault(self, key, default=None): + 'od.setdefault(k[,d]) -> od.get(k,d), also set od[k]=d if k not in od' + if key in self: + return self[key] + self[key] = default + return default + + def __repr__(self, _repr_running={}): + 'od.__repr__() <==> repr(od)' + call_key = id(self), _get_ident() + if call_key in _repr_running: + return '...' + _repr_running[call_key] = 1 + try: + if not self: + return '%s()' % (self.__class__.__name__,) + return '%s(%r)' % (self.__class__.__name__, self.items()) + finally: + del _repr_running[call_key] + + def __reduce__(self): + 'Return state information for pickling' + items = [[k, self[k]] for k in self] + inst_dict = vars(self).copy() + for k in vars(OrderedDict()): + inst_dict.pop(k, None) + if inst_dict: + return (self.__class__, (items,), inst_dict) + return self.__class__, (items,) + + def copy(self): + 'od.copy() -> a shallow copy of od' + return self.__class__(self) + + @classmethod + def fromkeys(cls, iterable, value=None): + '''OD.fromkeys(S[, v]) -> New ordered dictionary with keys from S + and values equal to v (which defaults to None). + + ''' + d = cls() + for key in iterable: + d[key] = value + return d + + def __eq__(self, other): + '''od.__eq__(y) <==> od==y. Comparison to another OD is order-sensitive + while comparison to a regular mapping is order-insensitive. + + ''' + if isinstance(other, OrderedDict): + return len(self)==len(other) and self.items() == other.items() + return dict.__eq__(self, other) + + def __ne__(self, other): + return not self == other + + # -- the following methods are only used in Python 2.7 -- + + def viewkeys(self): + "od.viewkeys() -> a set-like object providing a view on od's keys" + return KeysView(self) + + def viewvalues(self): + "od.viewvalues() -> an object providing a view on od's values" + return ValuesView(self) + + def viewitems(self): + "od.viewitems() -> a set-like object providing a view on od's items" + return ItemsView(self) + diff --git a/deps/npm/node_modules/node-gyp/gyp/pylib/gyp/win_tool.py b/deps/npm/node_modules/node-gyp/gyp/pylib/gyp/win_tool.py index 3424c015d..e9d7df0bb 100755 --- a/deps/npm/node_modules/node-gyp/gyp/pylib/gyp/win_tool.py +++ b/deps/npm/node_modules/node-gyp/gyp/pylib/gyp/win_tool.py @@ -10,12 +10,17 @@ These functions are executed via gyp-win-tool when using the ninja generator. """ import os +import re import shutil import subprocess +import string import sys BASE_DIR = os.path.dirname(os.path.abspath(__file__)) +# A regex matching an argument corresponding to the output filename passed to +# link.exe. +_LINK_EXE_OUT_ARG = re.compile('/OUT:(?P<out>.+)$', re.IGNORECASE) def main(args): executor = WinTool() @@ -28,6 +33,32 @@ class WinTool(object): """This class performs all the Windows tooling steps. The methods can either be executed directly, or dispatched from an argument list.""" + def _UseSeparateMspdbsrv(self, env, args): + """Allows to use a unique instance of mspdbsrv.exe per linker instead of a + shared one.""" + if len(args) < 1: + raise Exception("Not enough arguments") + + if args[0] != 'link.exe': + return + + # Use the output filename passed to the linker to generate an endpoint name + # for mspdbsrv.exe. + endpoint_name = None + for arg in args: + m = _LINK_EXE_OUT_ARG.match(arg) + if m: + endpoint_name = '%s_%d' % (m.group('out'), os.getpid()) + break + + if endpoint_name is None: + return + + # Adds the appropriate environment variable. This will be read by link.exe + # to know which instance of mspdbsrv.exe it should connect to (if it's + # not set then the default endpoint is used). + env['_MSPDBSRV_ENDPOINT_'] = endpoint_name + def Dispatch(self, args): """Dispatches a string command to a method.""" if len(args) < 1: @@ -65,19 +96,100 @@ class WinTool(object): else: shutil.copy2(source, dest) - def ExecLinkWrapper(self, arch, *args): + def ExecLinkWrapper(self, arch, use_separate_mspdbsrv, *args): """Filter diagnostic output from link that looks like: ' Creating library ui.dll.lib and object ui.dll.exp' This happens when there are exports from the dll or exe. """ env = self._GetEnv(arch) - popen = subprocess.Popen(args, shell=True, env=env, - stdout=subprocess.PIPE, stderr=subprocess.STDOUT) - out, _ = popen.communicate() + if use_separate_mspdbsrv == 'True': + self._UseSeparateMspdbsrv(env, args) + link = subprocess.Popen(args, + shell=True, + env=env, + stdout=subprocess.PIPE, + stderr=subprocess.STDOUT) + out, _ = link.communicate() for line in out.splitlines(): if not line.startswith(' Creating library '): print line - return popen.returncode + return link.returncode + + def ExecLinkWithManifests(self, arch, embed_manifest, out, ldcmd, resname, + mt, rc, intermediate_manifest, *manifests): + """A wrapper for handling creating a manifest resource and then executing + a link command.""" + # The 'normal' way to do manifests is to have link generate a manifest + # based on gathering dependencies from the object files, then merge that + # manifest with other manifests supplied as sources, convert the merged + # manifest to a resource, and then *relink*, including the compiled + # version of the manifest resource. This breaks incremental linking, and + # is generally overly complicated. Instead, we merge all the manifests + # provided (along with one that includes what would normally be in the + # linker-generated one, see msvs_emulation.py), and include that into the + # first and only link. We still tell link to generate a manifest, but we + # only use that to assert that our simpler process did not miss anything. + variables = { + 'python': sys.executable, + 'arch': arch, + 'out': out, + 'ldcmd': ldcmd, + 'resname': resname, + 'mt': mt, + 'rc': rc, + 'intermediate_manifest': intermediate_manifest, + 'manifests': ' '.join(manifests), + } + add_to_ld = '' + if manifests: + subprocess.check_call( + '%(python)s gyp-win-tool manifest-wrapper %(arch)s %(mt)s -nologo ' + '-manifest %(manifests)s -out:%(out)s.manifest' % variables) + if embed_manifest == 'True': + subprocess.check_call( + '%(python)s gyp-win-tool manifest-to-rc %(arch)s %(out)s.manifest' + ' %(out)s.manifest.rc %(resname)s' % variables) + subprocess.check_call( + '%(python)s gyp-win-tool rc-wrapper %(arch)s %(rc)s ' + '%(out)s.manifest.rc' % variables) + add_to_ld = ' %(out)s.manifest.res' % variables + subprocess.check_call(ldcmd + add_to_ld) + + # Run mt.exe on the theoretically complete manifest we generated, merging + # it with the one the linker generated to confirm that the linker + # generated one does not add anything. This is strictly unnecessary for + # correctness, it's only to verify that e.g. /MANIFESTDEPENDENCY was not + # used in a #pragma comment. + if manifests: + # Merge the intermediate one with ours to .assert.manifest, then check + # that .assert.manifest is identical to ours. + subprocess.check_call( + '%(python)s gyp-win-tool manifest-wrapper %(arch)s %(mt)s -nologo ' + '-manifest %(out)s.manifest %(intermediate_manifest)s ' + '-out:%(out)s.assert.manifest' % variables) + assert_manifest = '%(out)s.assert.manifest' % variables + our_manifest = '%(out)s.manifest' % variables + # Load and normalize the manifests. mt.exe sometimes removes whitespace, + # and sometimes doesn't unfortunately. + with open(our_manifest, 'rb') as our_f: + with open(assert_manifest, 'rb') as assert_f: + our_data = our_f.read().translate(None, string.whitespace) + assert_data = assert_f.read().translate(None, string.whitespace) + if our_data != assert_data: + os.unlink(out) + def dump(filename): + sys.stderr.write('%s\n-----\n' % filename) + with open(filename, 'rb') as f: + sys.stderr.write(f.read() + '\n-----\n') + dump(intermediate_manifest) + dump(our_manifest) + dump(assert_manifest) + sys.stderr.write( + 'Linker generated manifest "%s" added to final manifest "%s" ' + '(result in "%s"). ' + 'Were /MANIFEST switches used in #pragma statements? ' % ( + intermediate_manifest, our_manifest, assert_manifest)) + return 1 def ExecManifestWrapper(self, arch, *args): """Run manifest tool with environment set. Strip out undesirable warning @@ -166,11 +278,14 @@ class WinTool(object): """Runs an action command line from a response file using the environment for |arch|. If |dir| is supplied, use that as the working directory.""" env = self._GetEnv(arch) + # TODO(scottmg): This is a temporary hack to get some specific variables + # through to actions that are set after gyp-time. http://crbug.com/333738. + for k, v in os.environ.iteritems(): + if k not in env: + env[k] = v args = open(rspfile).read() dir = dir[0] if dir else None - popen = subprocess.Popen(args, shell=True, env=env, cwd=dir) - popen.wait() - return popen.returncode + return subprocess.call(args, shell=True, env=env, cwd=dir) if __name__ == '__main__': sys.exit(main(sys.argv[1:])) diff --git a/deps/npm/node_modules/node-gyp/gyp/pylib/gyp/xcode_emulation.py b/deps/npm/node_modules/node-gyp/gyp/pylib/gyp/xcode_emulation.py index d50eac004..30f27d583 100644 --- a/deps/npm/node_modules/node-gyp/gyp/pylib/gyp/xcode_emulation.py +++ b/deps/npm/node_modules/node-gyp/gyp/pylib/gyp/xcode_emulation.py @@ -9,11 +9,13 @@ other build systems, such as make and ninja. import copy import gyp.common +import os import os.path import re import shlex import subprocess import sys +import tempfile from gyp.common import GypError class XcodeSettings(object): @@ -22,6 +24,7 @@ class XcodeSettings(object): # Populated lazily by _SdkPath(). Shared by all XcodeSettings, so cached # at class-level for efficiency. _sdk_path_cache = {} + _sdk_root_cache = {} # Populated lazily by GetExtraPlistItems(). Shared by all XcodeSettings, so # cached at class-level for efficiency. @@ -31,6 +34,10 @@ class XcodeSettings(object): # cached at class-level for efficiency. _codesigning_key_cache = {} + # Populated lazily by _XcodeVersion. Shared by all XcodeSettings, so cached + # at class-level for efficiency. + _xcode_version_cache = () + def __init__(self, spec): self.spec = spec @@ -262,7 +269,7 @@ class XcodeSettings(object): """Returns the architectures this target should be built for.""" # TODO: Look at VALID_ARCHS, ONLY_ACTIVE_ARCH; possibly set # CURRENT_ARCH / NATIVE_ARCH env vars? - return self.xcode_settings[configname].get('ARCHS', ['i386']) + return self.xcode_settings[configname].get('ARCHS', [self._DefaultArch()]) def _GetStdout(self, cmdlist): job = subprocess.Popen(cmdlist, stdout=subprocess.PIPE) @@ -291,9 +298,14 @@ class XcodeSettings(object): sdk_root = self._SdkRoot(configname) if sdk_root.startswith('/'): return sdk_root + return self._XcodeSdkPath(sdk_root) + + def _XcodeSdkPath(self, sdk_root): if sdk_root not in XcodeSettings._sdk_path_cache: - XcodeSettings._sdk_path_cache[sdk_root] = self._GetSdkVersionInfoItem( - sdk_root, 'Path') + sdk_path = self._GetSdkVersionInfoItem(sdk_root, 'Path') + XcodeSettings._sdk_path_cache[sdk_root] = sdk_path + if sdk_root: + XcodeSettings._sdk_root_cache[sdk_path] = sdk_root return XcodeSettings._sdk_path_cache[sdk_root] def _AppendPlatformVersionMinFlags(self, lst): @@ -318,7 +330,7 @@ class XcodeSettings(object): cflags = [] sdk_root = self._SdkPath() - if 'SDKROOT' in self._Settings(): + if 'SDKROOT' in self._Settings() and sdk_root: cflags.append('-isysroot %s' % sdk_root) if self._Test('CLANG_WARN_CONSTANT_CONVERSION', 'YES', default='NO'): @@ -384,7 +396,7 @@ class XcodeSettings(object): if arch is not None: archs = [arch] else: - archs = self._Settings().get('ARCHS', ['i386']) + archs = self._Settings().get('ARCHS', [self._DefaultArch()]) if len(archs) != 1: # TODO: Supporting fat binaries will be annoying. self._WarnUnimplemented('ARCHS') @@ -404,11 +416,14 @@ class XcodeSettings(object): cflags += self._Settings().get('WARNING_CFLAGS', []) - if 'SDKROOT' in self._Settings(): - config = self.spec['configurations'][self.configname] - framework_dirs = config.get('mac_framework_dirs', []) - for directory in framework_dirs: - cflags.append('-F' + directory.replace('$(SDKROOT)', sdk_root)) + if sdk_root: + framework_root = sdk_root + else: + framework_root = '' + config = self.spec['configurations'][self.configname] + framework_dirs = config.get('mac_framework_dirs', []) + for directory in framework_dirs: + cflags.append('-F' + directory.replace('$(SDKROOT)', framework_root)) self.configname = None return cflags @@ -624,7 +639,7 @@ class XcodeSettings(object): self._AppendPlatformVersionMinFlags(ldflags) - if 'SDKROOT' in self._Settings(): + if 'SDKROOT' in self._Settings() and self._SdkPath(): ldflags.append('-isysroot ' + self._SdkPath()) for library_path in self._Settings().get('LIBRARY_SEARCH_PATHS', []): @@ -638,7 +653,7 @@ class XcodeSettings(object): if arch is not None: archs = [arch] else: - archs = self._Settings().get('ARCHS', ['i386']) + archs = self._Settings().get('ARCHS', [self._DefaultArch()]) if len(archs) != 1: # TODO: Supporting fat binaries will be annoying. self._WarnUnimplemented('ARCHS') @@ -655,11 +670,13 @@ class XcodeSettings(object): for rpath in self._Settings().get('LD_RUNPATH_SEARCH_PATHS', []): ldflags.append('-Wl,-rpath,' + rpath) - if 'SDKROOT' in self._Settings(): - config = self.spec['configurations'][self.configname] - framework_dirs = config.get('mac_framework_dirs', []) - for directory in framework_dirs: - ldflags.append('-F' + directory.replace('$(SDKROOT)', self._SdkPath())) + sdk_root = self._SdkPath() + if not sdk_root: + sdk_root = '' + config = self.spec['configurations'][self.configname] + framework_dirs = config.get('mac_framework_dirs', []) + for directory in framework_dirs: + ldflags.append('-F' + directory.replace('$(SDKROOT)', sdk_root)) self.configname = None return ldflags @@ -789,33 +806,40 @@ class XcodeSettings(object): if not (self.isIOS and self.spec['type'] == "executable"): return [] - identity = self.xcode_settings[configname].get('CODE_SIGN_IDENTITY', '') - if identity == '': + settings = self.xcode_settings[configname] + key = self._GetIOSCodeSignIdentityKey(settings) + if not key: return [] + + # Warn for any unimplemented signing xcode keys. + unimpl = ['OTHER_CODE_SIGN_FLAGS'] + unimpl = set(unimpl) & set(self.xcode_settings[configname].keys()) + if unimpl: + print 'Warning: Some codesign keys not implemented, ignoring: %s' % ( + ', '.join(sorted(unimpl))) + + return ['%s code-sign-bundle "%s" "%s" "%s" "%s"' % ( + os.path.join('${TARGET_BUILD_DIR}', 'gyp-mac-tool'), key, + settings.get('CODE_SIGN_RESOURCE_RULES_PATH', ''), + settings.get('CODE_SIGN_ENTITLEMENTS', ''), + settings.get('PROVISIONING_PROFILE', '')) + ] + + def _GetIOSCodeSignIdentityKey(self, settings): + identity = settings.get('CODE_SIGN_IDENTITY') + if not identity: + return None if identity not in XcodeSettings._codesigning_key_cache: - proc = subprocess.Popen(['security', 'find-identity', '-p', 'codesigning', - '-v'], stdout=subprocess.PIPE) - output = proc.communicate()[0].strip() - key = None - for item in output.split("\n"): - if identity in item: - assert key == None, ( - "Multiple codesigning identities for identity: %s" % - identity) - key = item.split(' ')[1] - XcodeSettings._codesigning_key_cache[identity] = key - key = XcodeSettings._codesigning_key_cache[identity] - if key: - # Warn for any unimplemented signing xcode keys. - unimpl = ['CODE_SIGN_RESOURCE_RULES_PATH', 'OTHER_CODE_SIGN_FLAGS', - 'CODE_SIGN_ENTITLEMENTS'] - keys = set(self.xcode_settings[configname].keys()) - unimpl = set(unimpl) & keys - if unimpl: - print 'Warning: Some codesign keys not implemented, ignoring:', \ - ' '.join(unimpl) - return ['codesign --force --sign %s %s' % (key, output_binary)] - return [] + output = subprocess.check_output( + ['security', 'find-identity', '-p', 'codesigning', '-v']) + for line in output.splitlines(): + if identity in line: + fingerprint = line.split()[1] + cache = XcodeSettings._codesigning_key_cache + assert identity not in cache or fingerprint == cache[identity], ( + "Multiple codesigning fingerprints for identity: %s" % identity) + XcodeSettings._codesigning_key_cache[identity] = fingerprint + return XcodeSettings._codesigning_key_cache.get(identity, '') def AddImplicitPostbuilds(self, configname, output, output_binary, postbuilds=[], quiet=False): @@ -835,10 +859,11 @@ class XcodeSettings(object): l = '-l' + m.group(1) else: l = library - if self._SdkPath(): - return l.replace('$(SDKROOT)', self._SdkPath(config_name)) - else: - return l + + sdk_root = self._SdkPath(config_name) + if not sdk_root: + sdk_root = '' + return l.replace('$(SDKROOT)', sdk_root) def AdjustLibraries(self, libraries, config_name=None): """Transforms entries like 'Cocoa.framework' in libraries into entries like @@ -851,6 +876,27 @@ class XcodeSettings(object): def _BuildMachineOSBuild(self): return self._GetStdout(['sw_vers', '-buildVersion']) + # This method ported from the logic in Homebrew's CLT version check + def _CLTVersion(self): + # pkgutil output looks like + # package-id: com.apple.pkg.CLTools_Executables + # version: 5.0.1.0.1.1382131676 + # volume: / + # location: / + # install-time: 1382544035 + # groups: com.apple.FindSystemFiles.pkg-group com.apple.DevToolsBoth.pkg-group com.apple.DevToolsNonRelocatableShared.pkg-group + STANDALONE_PKG_ID = "com.apple.pkg.DeveloperToolsCLILeo" + FROM_XCODE_PKG_ID = "com.apple.pkg.DeveloperToolsCLI" + MAVERICKS_PKG_ID = "com.apple.pkg.CLTools_Executables" + + regex = re.compile('version: (?P<version>.+)') + for key in [MAVERICKS_PKG_ID, STANDALONE_PKG_ID, FROM_XCODE_PKG_ID]: + try: + output = self._GetStdout(['/usr/sbin/pkgutil', '--pkg-info', key]) + return re.search(regex, output).groupdict()['version'] + except: + continue + def _XcodeVersion(self): # `xcodebuild -version` output looks like # Xcode 4.6.3 @@ -860,14 +906,33 @@ class XcodeSettings(object): # Component versions: DevToolsCore-1809.0; DevToolsSupport-1806.0 # BuildVersion: 10M2518 # Convert that to '0463', '4H1503'. - version_list = self._GetStdout(['xcodebuild', '-version']).splitlines() - version = version_list[0] - build = version_list[-1] - # Be careful to convert "4.2" to "0420": - version = version.split()[-1].replace('.', '') - version = (version + '0' * (3 - len(version))).zfill(4) - build = build.split()[-1] - return version, build + if len(XcodeSettings._xcode_version_cache) == 0: + try: + version_list = self._GetStdout(['xcodebuild', '-version']).splitlines() + # In some circumstances xcodebuild exits 0 but doesn't return + # the right results; for example, a user on 10.7 or 10.8 with + # a bogus path set via xcode-select + # In that case this may be a CLT-only install so fall back to + # checking that version. + if len(version_list) < 2: + raise GypError, "xcodebuild returned unexpected results" + except: + version = self._CLTVersion() + if version: + version = re.match('(\d\.\d\.?\d*)', version).groups()[0] + else: + raise GypError, "No Xcode or CLT version detected!" + # The CLT has no build information, so we return an empty string. + version_list = [version, ''] + version = version_list[0] + build = version_list[-1] + # Be careful to convert "4.2" to "0420": + version = version.split()[-1].replace('.', '') + version = (version + '0' * (3 - len(version))).zfill(4) + if build: + build = build.split()[-1] + XcodeSettings._xcode_version_cache = (version, build) + return XcodeSettings._xcode_version_cache def _XcodeIOSDeviceFamily(self, configname): family = self.xcode_settings[configname].get('TARGETED_DEVICE_FAMILY', '1') @@ -884,6 +949,8 @@ class XcodeSettings(object): cache['DTXcodeBuild'] = xcode_build sdk_root = self._SdkRoot(configname) + if not sdk_root: + sdk_root = self._DefaultSdkRoot() cache['DTSDKName'] = sdk_root if xcode >= '0430': cache['DTSDKBuild'] = self._GetSdkVersionInfoItem( @@ -908,6 +975,55 @@ class XcodeSettings(object): items['UIDeviceFamily'] = self._XcodeIOSDeviceFamily(configname) return items + def _DefaultSdkRoot(self): + """Returns the default SDKROOT to use. + + Prior to version 5.0.0, if SDKROOT was not explicitly set in the Xcode + project, then the environment variable was empty. Starting with this + version, Xcode uses the name of the newest SDK installed. + """ + if self._XcodeVersion() < '0500': + return '' + default_sdk_path = self._XcodeSdkPath('') + default_sdk_root = XcodeSettings._sdk_root_cache.get(default_sdk_path) + if default_sdk_root: + return default_sdk_root + try: + all_sdks = self._GetStdout(['xcodebuild', '-showsdks']) + except: + # If xcodebuild fails, there will be no valid SDKs + return '' + for line in all_sdks.splitlines(): + items = line.split() + if len(items) >= 3 and items[-2] == '-sdk': + sdk_root = items[-1] + sdk_path = self._XcodeSdkPath(sdk_root) + if sdk_path == default_sdk_path: + return sdk_root + return '' + + def _DefaultArch(self): + # For Mac projects, Xcode changed the default value used when ARCHS is not + # set from "i386" to "x86_64". + # + # For iOS projects, if ARCHS is unset, it defaults to "armv7 armv7s" when + # building for a device, and the simulator binaries are always build for + # "i386". + # + # For new projects, ARCHS is set to $(ARCHS_STANDARD_INCLUDING_64_BIT), + # which correspond to "armv7 armv7s arm64", and when building the simulator + # the architecture is either "i386" or "x86_64" depending on the simulated + # device (respectively 32-bit or 64-bit device). + # + # Since the value returned by this function is only used when ARCHS is not + # set, then on iOS we return "i386", as the default xcode project generator + # does not set ARCHS if it is not set in the .gyp file. + if self.isIOS: + return 'i386' + version, build = self._XcodeVersion() + if version >= '0500': + return 'x86_64' + return 'i386' class MacPrefixHeader(object): """A class that helps with emulating Xcode's GCC_PREFIX_HEADER feature. diff --git a/deps/npm/node_modules/node-gyp/lib/configure.js b/deps/npm/node_modules/node-gyp/lib/configure.js index e101a315a..268c33625 100644 --- a/deps/npm/node_modules/node-gyp/lib/configure.js +++ b/deps/npm/node_modules/node-gyp/lib/configure.js @@ -1,4 +1,3 @@ - module.exports = exports = configure /** @@ -14,6 +13,7 @@ var fs = require('graceful-fs') , semver = require('semver') , mkdirp = require('mkdirp') , cp = require('child_process') + , extend = require('util')._extend , spawn = cp.spawn , execFile = cp.execFile , win = process.platform == 'win32' @@ -73,7 +73,9 @@ function configure (gyp, argv, callback) { } function checkPythonVersion () { - var env = { TERM: 'dumb', PATH: process.env.PATH }; + var env = extend({}, process.env); + env.TERM = 'dumb'; + execFile(python, ['-c', 'import platform; print(platform.python_version());'], { env: env }, function (err, stdout) { if (err) { return callback(err) @@ -88,7 +90,7 @@ function configure (gyp, argv, callback) { log.silly('stripping "rc" identifier from version') version = version.replace(/rc(.*)$/ig, '') } - var range = semver.Range('>=2.5.0 <3.0.0'); + var range = semver.Range('>=2.5.0 <3.0.0') if (range.test(version)) { getNodeDir() } else { @@ -210,7 +212,7 @@ function configure (gyp, argv, callback) { variables.copy_dev_lib = !gyp.opts.nodedir // disable -T "thin" static archives by default - variables.standalone_static_library = gyp.opts.thin ? 0 : 1; + variables.standalone_static_library = gyp.opts.thin ? 0 : 1 // loop through the rest of the opts and add the unknown ones as variables. // this allows for module-specific configure flags like: @@ -311,6 +313,7 @@ function configure (gyp, argv, callback) { argv.push('-Dnode_root_dir=' + nodeDir) argv.push('-Dmodule_root_dir=' + process.cwd()) argv.push('--depth=.') + argv.push('--no-parallel') // tell gyp to write the Makefile/Solution files into output_dir argv.push('--generator-output', output_dir) diff --git a/deps/npm/node_modules/node-gyp/lib/install.js b/deps/npm/node_modules/node-gyp/lib/install.js index 60dc3cd63..a9a18bcc7 100644 --- a/deps/npm/node_modules/node-gyp/lib/install.js +++ b/deps/npm/node_modules/node-gyp/lib/install.js @@ -12,6 +12,7 @@ var fs = require('graceful-fs') , tar = require('tar') , rm = require('rimraf') , path = require('path') + , crypto = require('crypto') , zlib = require('zlib') , log = require('npmlog') , semver = require('semver') @@ -151,6 +152,15 @@ function install (gyp, argv, callback) { return req } + function getContentSha(res, callback) { + var shasum = crypto.createHash('sha1') + res.on('data', function (chunk) { + shasum.update(chunk) + }).on('end', function () { + callback(null, shasum.digest('hex')) + }) + } + function go () { log.verbose('ensuring nodedir is created', devDir) @@ -171,13 +181,16 @@ function install (gyp, argv, callback) { } // now download the node tarball - var tarPath = gyp.opts['tarball']; + var tarPath = gyp.opts['tarball'] var tarballUrl = tarPath ? tarPath : distUrl + '/v' + version + '/node-v' + version + '.tar.gz' , badDownload = false , extractCount = 0 , gunzip = zlib.createGunzip() , extracter = tar.Extract({ path: devDir, strip: 1, filter: isValid }) + var contentShasums = {} + var expectShasums = {} + // checks if a file to be extracted from the tarball is valid. // only .h header files and the gyp files get extracted function isValid () { @@ -230,6 +243,13 @@ function install (gyp, argv, callback) { cb(new Error(res.statusCode + ' status code downloading tarball')) return } + // content sha1 + getContentSha(res, function (_, sha1) { + var filename = path.basename(tarballUrl).trim() + contentShasums[filename] = sha1 + log.verbose('content sha1', filename, sha1) + }) + // start unzipping and untaring req.pipe(gunzip).pipe(extracter) }) @@ -254,6 +274,10 @@ function install (gyp, argv, callback) { var installVersionPath = path.resolve(devDir, 'installVersion') fs.writeFile(installVersionPath, gyp.package.installVersion + '\n', deref) + // download SHASUMS.txt + async++ + downloadShasums(deref) + if (async === 0) { // no async tasks required cb() @@ -261,10 +285,59 @@ function install (gyp, argv, callback) { function deref (err) { if (err) return cb(err) - --async || cb() + + async-- + if (!async) { + log.verbose('download contents shasums', JSON.stringify(contentShasums)) + // check content shasums + for (var k in contentShasums) { + log.verbose('validating download shasum for ' + k, '(%s == %s)', contentShasums[k], expectShasums[k]) + if (contentShasums[k] !== expectShasums[k]) { + cb(new Error(k + ' local sha1 ' + contentShasums[k] + ' not match remote ' + expectShasums[k])) + return + } + } + cb() + } } } + function downloadShasums(done) { + log.verbose('check download content sha1, need to download `SHASUMS.txt`...') + var shasumsPath = path.resolve(devDir, 'SHASUMS.txt') + , shasumsUrl = distUrl + '/v' + version + '/SHASUMS.txt' + + log.verbose('`SHASUMS.txt` url', shasumsUrl) + var req = download(shasumsUrl) + if (!req) return + req.on('error', done) + req.on('response', function (res) { + if (res.statusCode !== 200) { + done(new Error(res.statusCode + ' status code downloading SHASUMS.txt')) + return + } + + var chunks = [] + res.on('data', function (chunk) { + chunks.push(chunk) + }) + res.on('end', function () { + var lines = Buffer.concat(chunks).toString().trim().split('\n') + lines.forEach(function (line) { + var items = line.trim().split(/\s+/) + if (items.length !== 2) return + + // 0035d18e2dcf9aad669b1c7c07319e17abfe3762 ./node-v0.11.4.tar.gz + var name = items[1].replace(/^\.\//, '') + expectShasums[name] = items[0] + }) + + log.verbose('`SHASUMS.txt` data', JSON.stringify(expectShasums)) + done() + }) + }) + } + function downloadNodeLib (done) { log.verbose('on Windows; need to download `node.lib`...') var dir32 = path.resolve(devDir, 'ia32') @@ -293,6 +366,11 @@ function install (gyp, argv, callback) { return } + getContentSha(res, function (_, sha1) { + contentShasums['node.lib'] = sha1 + log.verbose('content sha1', 'node.lib', sha1) + }) + var ws = fs.createWriteStream(nodeLibPath32) ws.on('error', cb) req.pipe(ws) @@ -314,6 +392,11 @@ function install (gyp, argv, callback) { return } + getContentSha(res, function (_, sha1) { + contentShasums['x64/node.lib'] = sha1 + log.verbose('content sha1', 'x64/node.lib', sha1) + }) + var ws = fs.createWriteStream(nodeLibPath64) ws.on('error', cb) req.pipe(ws) diff --git a/deps/npm/node_modules/node-gyp/package.json b/deps/npm/node_modules/node-gyp/package.json index b28964c5e..c9dbae5a8 100644 --- a/deps/npm/node_modules/node-gyp/package.json +++ b/deps/npm/node_modules/node-gyp/package.json @@ -10,7 +10,7 @@ "bindings", "gyp" ], - "version": "0.12.2", + "version": "0.13.0", "installVersion": 9, "author": { "name": "Nathan Rajlich", @@ -50,6 +50,10 @@ "url": "https://github.com/TooTallNate/node-gyp/issues" }, "homepage": "https://github.com/TooTallNate/node-gyp", - "_id": "node-gyp@0.12.2", - "_from": "node-gyp@latest" + "_id": "node-gyp@0.13.0", + "dist": { + "shasum": "97765303203579f1445358d4d25d03645811d87d" + }, + "_from": "node-gyp@latest", + "_resolved": "https://registry.npmjs.org/node-gyp/-/node-gyp-0.13.0.tgz" } diff --git a/deps/npm/node_modules/npm-registry-client/lib/adduser.js b/deps/npm/node_modules/npm-registry-client/lib/adduser.js index aebf71d67..a4581a6c8 100644 --- a/deps/npm/node_modules/npm-registry-client/lib/adduser.js +++ b/deps/npm/node_modules/npm-registry-client/lib/adduser.js @@ -24,8 +24,7 @@ function adduser (username, password, email, cb) { var salt = crypto.randomBytes(30).toString('hex') , userobj = { name : username - , salt : salt - , password_sha : sha(password + salt) + , password : password , email : email , _id : 'org.couchdb.user:'+username , type : "user" @@ -51,7 +50,7 @@ function adduser (username, password, email, cb) { cb = done.call(this, cb, pre) var logObj = Object.keys(userobj).map(function (k) { - if (k === 'salt' || k === 'password_sha') return [k, 'XXXXX'] + if (k === 'password') return [k, 'XXXXX'] return [k, userobj[k]] }).reduce(function (s, kv) { s[kv[0]] = kv[1] diff --git a/deps/npm/node_modules/npm-registry-client/lib/request.js b/deps/npm/node_modules/npm-registry-client/lib/request.js index b2cff11a7..c11dc9ca3 100644 --- a/deps/npm/node_modules/npm-registry-client/lib/request.js +++ b/deps/npm/node_modules/npm-registry-client/lib/request.js @@ -1,6 +1,7 @@ module.exports = regRequest var url = require("url") + , zlib = require("zlib") , fs = require("graceful-fs") , rm = require("rimraf") , asyncMap = require("slide").asyncMap @@ -128,6 +129,7 @@ function makeRequest (method, remote, where, what, etag, nofollow, cb_) { if (strict === undefined) strict = true var opts = { url: remote , method: method + , encoding: null // tell request let body be Buffer instance , ca: this.conf.get('ca') , localAddress: this.conf.get('local-address') , cert: this.conf.get('cert') @@ -140,6 +142,7 @@ function makeRequest (method, remote, where, what, etag, nofollow, cb_) { } headers.accept = "application/json" + headers['accept-encoding'] = 'gzip' headers["user-agent"] = this.conf.get('user-agent') || 'node/' + process.version @@ -170,7 +173,7 @@ function makeRequest (method, remote, where, what, etag, nofollow, cb_) { this.log.http(method, remote.href || "/") var done = requestDone.call(this, method, where, cb) - var req = request(opts, done) + var req = request(opts, decodeResponseBody(done)) req.on("error", cb) req.on("socket", function (s) { @@ -182,6 +185,20 @@ function makeRequest (method, remote, where, what, etag, nofollow, cb_) { } } +function decodeResponseBody(cb) { + return function (er, response, data) { + if (er) return cb(er, response, data) + + if (response.headers['content-encoding'] !== 'gzip') return cb(er, response, data) + + zlib.gunzip(data, function (er, buf) { + if (er) return cb(er, response, data) + + cb(null, response, buf) + }) + } +} + // cb(er, parsed, raw, response) function requestDone (method, where, cb) { return function (er, response, data) { diff --git a/deps/npm/node_modules/npm-registry-client/package.json b/deps/npm/node_modules/npm-registry-client/package.json index 70869bc2e..17d1f782c 100644 --- a/deps/npm/node_modules/npm-registry-client/package.json +++ b/deps/npm/node_modules/npm-registry-client/package.json @@ -6,7 +6,7 @@ }, "name": "npm-registry-client", "description": "Client for the npm registry", - "version": "0.4.4", + "version": "0.4.5", "repository": { "url": "git://github.com/isaacs/npm-registry-client" }, @@ -38,6 +38,6 @@ "url": "https://github.com/isaacs/npm-registry-client/issues" }, "homepage": "https://github.com/isaacs/npm-registry-client", - "_id": "npm-registry-client@0.4.4", + "_id": "npm-registry-client@0.4.5", "_from": "npm-registry-client@latest" } diff --git a/deps/npm/node_modules/npm-registry-client/test/adduser-new.js b/deps/npm/node_modules/npm-registry-client/test/adduser-new.js index a0fee04c3..96dfc26d1 100644 --- a/deps/npm/node_modules/npm-registry-client/test/adduser-new.js +++ b/deps/npm/node_modules/npm-registry-client/test/adduser-new.js @@ -32,9 +32,7 @@ tap.test("create new user account", function (t) { req.on("end", function () { var o = JSON.parse(b) - var salt = o.salt - userdata.salt = salt - userdata.password_sha = sha(password + salt) + userdata.password = password userdata.date = o.date t.deepEqual(o, userdata) diff --git a/deps/npm/node_modules/npm-registry-client/test/adduser-update.js b/deps/npm/node_modules/npm-registry-client/test/adduser-update.js index 1d70c5a78..370457147 100644 --- a/deps/npm/node_modules/npm-registry-client/test/adduser-update.js +++ b/deps/npm/node_modules/npm-registry-client/test/adduser-update.js @@ -47,9 +47,7 @@ tap.test("update a user acct", function (t) { req.on("end", function () { var o = JSON.parse(b) - var salt = o.salt - userdata.salt = salt - userdata.password_sha = sha(password + salt) + userdata.password = password userdata.date = o.date t.deepEqual(o, userdata) diff --git a/deps/npm/node_modules/npm-registry-client/test/request-gzip-content.js b/deps/npm/node_modules/npm-registry-client/test/request-gzip-content.js new file mode 100644 index 000000000..2c7dcae59 --- /dev/null +++ b/deps/npm/node_modules/npm-registry-client/test/request-gzip-content.js @@ -0,0 +1,47 @@ +var zlib = require('zlib') +var tap = require('tap') +var server = require('./fixtures/server.js') +var RC = require('../') +var pkg = { + _id: 'some-package-gzip@1.2.3', + name: 'some-package-gzip', + version: '1.2.3' +} + +zlib.gzip(JSON.stringify(pkg), function (err, pkgGzip) { + var client = new RC({ + cache: __dirname + '/fixtures/cache' + , 'fetch-retries': 1 + , 'fetch-retry-mintimeout': 10 + , 'fetch-retry-maxtimeout': 100 + , registry: 'http://localhost:' + server.port }) + + tap.test('request gzip package content', function (t) { + server.expect('GET', '/some-package-gzip/1.2.3', function (req, res) { + res.statusCode = 200 + res.setHeader('Content-Encoding', 'gzip'); + res.setHeader('Content-Type', 'application/json'); + res.end(pkgGzip) + }) + + client.get('/some-package-gzip/1.2.3', function (er, data, raw, res) { + if (er) throw er + t.deepEqual(data, pkg) + t.end() + }) + }) + + tap.test('request wrong gzip package content', function (t) { + server.expect('GET', '/some-package-gzip-error/1.2.3', function (req, res) { + res.statusCode = 200 + res.setHeader('Content-Encoding', 'gzip') + res.setHeader('Content-Type', 'application/json') + res.end(new Buffer('wrong gzip content')) + }) + + client.get('/some-package-gzip-error/1.2.3', function (er, data, raw, res) { + t.ok(er) + t.end() + }) + }) +}); diff --git a/deps/npm/node_modules/npmconf/config-defs.js b/deps/npm/node_modules/npmconf/config-defs.js index 4a91dc2e7..1815870f6 100644 --- a/deps/npm/node_modules/npmconf/config-defs.js +++ b/deps/npm/node_modules/npmconf/config-defs.js @@ -186,6 +186,7 @@ Object.defineProperty(exports, "defaults", {get: function () { , save : false , "save-bundle": false , "save-dev" : false + , "save-exact" : false , "save-optional" : false , searchopts: "" , searchexclude: null @@ -287,6 +288,7 @@ exports.types = , save : Boolean , "save-bundle": Boolean , "save-dev" : Boolean + , "save-exact" : Boolean , "save-optional" : Boolean , searchopts : String , searchexclude: [null, String] @@ -346,6 +348,7 @@ exports.shorthands = , g : ["--global"] , S : ["--save"] , D : ["--save-dev"] + , E : ["--save-exact"] , O : ["--save-optional"] , y : ["--yes"] , n : ["--no-yes"] diff --git a/deps/npm/node_modules/npmconf/node_modules/config-chain/node_modules/proto-list/package.json b/deps/npm/node_modules/npmconf/node_modules/config-chain/node_modules/proto-list/package.json index 1d73d658f..b7117440c 100644 --- a/deps/npm/node_modules/npmconf/node_modules/config-chain/node_modules/proto-list/package.json +++ b/deps/npm/node_modules/npmconf/node_modules/config-chain/node_modules/proto-list/package.json @@ -29,5 +29,9 @@ }, "homepage": "https://github.com/isaacs/proto-list", "_id": "proto-list@1.2.2", - "_from": "proto-list@~1.2.1" + "dist": { + "shasum": "48b88798261ec2c4a785720cdfec6200d57d3326" + }, + "_from": "proto-list@~1.2.1", + "_resolved": "https://registry.npmjs.org/proto-list/-/proto-list-1.2.2.tgz" } diff --git a/deps/npm/node_modules/npmconf/node_modules/config-chain/package.json b/deps/npm/node_modules/npmconf/node_modules/config-chain/package.json index 10e9b4c4b..72ab798b7 100644 --- a/deps/npm/node_modules/npmconf/node_modules/config-chain/package.json +++ b/deps/npm/node_modules/npmconf/node_modules/config-chain/package.json @@ -28,5 +28,9 @@ "url": "https://github.com/dominictarr/config-chain/issues" }, "_id": "config-chain@1.1.8", - "_from": "config-chain@~1.1.8" + "dist": { + "shasum": "a3b9ae699dedb3a7837615001f3cf646ca37c77a" + }, + "_from": "config-chain@~1.1.8", + "_resolved": "https://registry.npmjs.org/config-chain/-/config-chain-1.1.8.tgz" } diff --git a/deps/npm/node_modules/npmconf/package.json b/deps/npm/node_modules/npmconf/package.json index 182252d90..89b8fc808 100644 --- a/deps/npm/node_modules/npmconf/package.json +++ b/deps/npm/node_modules/npmconf/package.json @@ -1,6 +1,6 @@ { "name": "npmconf", - "version": "0.1.12", + "version": "0.1.13", "description": "The config thing npm uses", "main": "npmconf.js", "directories": { @@ -45,6 +45,6 @@ "url": "https://github.com/isaacs/npmconf/issues" }, "homepage": "https://github.com/isaacs/npmconf", - "_id": "npmconf@0.1.12", - "_from": "npmconf@0.1.12" + "_id": "npmconf@0.1.13", + "_from": "npmconf@latest" } diff --git a/deps/npm/node_modules/path-is-inside/LICENSE.txt b/deps/npm/node_modules/path-is-inside/LICENSE.txt index db2caa13f..ae20051ff 100644 --- a/deps/npm/node_modules/path-is-inside/LICENSE.txt +++ b/deps/npm/node_modules/path-is-inside/LICENSE.txt @@ -1,7 +1,13 @@ - DO WHAT THE FUCK YOU WANT TO PUBLIC LICENSE +Copyright © 2013–2014 Domenic Denicola <domenic@domenicdenicola.com> + +This work is free. You can redistribute it and/or modify it under the +terms of the Do What The Fuck You Want To Public License, Version 2, +as published by Sam Hocevar. See below for more details. + + DO WHAT THE FUCK YOU WANT TO PUBLIC LICENSE Version 2, December 2004 - Copyright (C) 2013 Domenic Denicola <domenic@domenicdenicola.com> + Copyright (C) 2004 Sam Hocevar <sam@hocevar.net> Everyone is permitted to copy and distribute verbatim or modified copies of this license document, and changing it is allowed as long @@ -11,4 +17,3 @@ TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION 0. You just DO WHAT THE FUCK YOU WANT TO. - diff --git a/deps/npm/node_modules/path-is-inside/lib/path-is-inside.js b/deps/npm/node_modules/path-is-inside/lib/path-is-inside.js index 5d1160e57..596dfd3b3 100644 --- a/deps/npm/node_modules/path-is-inside/lib/path-is-inside.js +++ b/deps/npm/node_modules/path-is-inside/lib/path-is-inside.js @@ -13,7 +13,11 @@ module.exports = function (thePath, potentialParent) { potentialParent = potentialParent.toLowerCase(); } - return thePath.indexOf(potentialParent) === 0; + return thePath.lastIndexOf(potentialParent, 0) === 0 && + ( + thePath[potentialParent.length] === path.sep || + thePath[potentialParent.length] === undefined + ); }; function stripTrailingSep(thePath) { diff --git a/deps/npm/node_modules/path-is-inside/package.json b/deps/npm/node_modules/path-is-inside/package.json index 7df0a695e..b96d6fea0 100644 --- a/deps/npm/node_modules/path-is-inside/package.json +++ b/deps/npm/node_modules/path-is-inside/package.json @@ -8,7 +8,7 @@ "inside", "relative" ], - "version": "1.0.0", + "version": "1.0.1", "author": { "name": "Domenic Denicola", "email": "domenic@domenicdenicola.com", @@ -34,6 +34,10 @@ "readme": "# Is This Path Inside This Other Path?\n\nIt turns out this question isn't trivial to answer using Node's built-in path APIs. A naive `indexOf`-based solution will fail sometimes on Windows, which is case-insensitive (see e.g. [isaacs/npm#4214][]). You might then think to be clever with `path.resolve`, but you have to be careful to account for situations whether the paths have different drive letters, or else you'll cause bugs like [isaacs/npm#4313][]. And let's not even get started on trailing slashes.\n\nThe **path-is-inside** package will give you a robust, cross-platform way of detecting whether a given path is inside another path.\n\n## Usage\n\nPretty simple. First the path being tested; then the potential parent. Like so:\n\n```js\nvar pathIsInside = require(\"path-is-inside\");\n\npathIsInside(\"/x/y/z\", \"/x/y\") // true\npathIsInside(\"/x/y\", \"/x/y/z\") // false\n```\n\n## OS-Specific Behavior\n\nLike Node's built-in path module, path-is-inside treats all file paths on Windows as case-insensitive, whereas it treats all file paths on *-nix operating systems as case-sensitive. Keep this in mind especially when working on a Mac, where, despite Node's defaults, the OS usually treats paths case-insensitively.\n\nIn practice, this means:\n\n```js\n// On Windows\n\npathIsInside(\"C:\\\\X\\\\Y\\\\Z\", \"C:\\\\x\\\\y\") // true\n\n// On *-nix, including Mac OS X\n\npathIsInside(\"/X/Y/Z\", \"/x/y\") // false\n```\n\n[isaacs/npm#4214]: https://github.com/isaacs/npm/pull/4214\n[isaacs/npm#4313]: https://github.com/isaacs/npm/issues/4313\n", "readmeFilename": "README.md", "homepage": "https://github.com/domenic/path-is-inside", - "_id": "path-is-inside@1.0.0", - "_from": "path-is-inside@" + "_id": "path-is-inside@1.0.1", + "dist": { + "shasum": "c5e6c4764c4cd41f2ac839c53be5621d085726b3" + }, + "_from": "path-is-inside@1.0.1", + "_resolved": "https://registry.npmjs.org/path-is-inside/-/path-is-inside-1.0.1.tgz" } diff --git a/deps/npm/node_modules/read-installed/.npmignore b/deps/npm/node_modules/read-installed/.npmignore new file mode 100644 index 000000000..8c23deeb3 --- /dev/null +++ b/deps/npm/node_modules/read-installed/.npmignore @@ -0,0 +1,13 @@ +*.swp +.*.swp + +.DS_Store +*~ +.project +.settings +npm-debug.log +coverage.html +.idea +lib-cov + +node_modules diff --git a/deps/npm/node_modules/read-installed/README.md b/deps/npm/node_modules/read-installed/README.md index 535a8496f..312153b4f 100644 --- a/deps/npm/node_modules/read-installed/README.md +++ b/deps/npm/node_modules/read-installed/README.md @@ -5,21 +5,23 @@ structure with all the data. npm uses this. -## 1.0.0 +## 2.0.0 -Breaking changes in `1.0.0`: +Breaking changes in `2.0.0`: The second argument is now an `Object` that contains the following keys: * `depth` optional, defaults to Infinity * `log` optional log Function - * `dev` optional, dev=true to mark devDeps as extraneous + * `dev` optional, default false, set to true to include devDependencies ## Usage ```javascript var readInstalled = require("read-installed") -readInstalled(folder, { depth, log, dev }, function (er, data) { +// optional options +var options = { dev: false, log: fn, depth: 2 } +readInstalled(folder, options, function (er, data) { ... }) ``` diff --git a/deps/npm/node_modules/read-installed/node_modules/util-extend/README.md b/deps/npm/node_modules/read-installed/node_modules/util-extend/README.md new file mode 100644 index 000000000..be03922ab --- /dev/null +++ b/deps/npm/node_modules/read-installed/node_modules/util-extend/README.md @@ -0,0 +1,13 @@ +# util-extend + +The Node object extending function that Node uses for Node! + +## Usage + +```js +var extend = require('util-extend'); +function functionThatTakesOptions(options) { + var options = extend(defaults, options); + // now any unset options are set to the defaults. +} +``` diff --git a/deps/npm/node_modules/read-installed/node_modules/util-extend/extend.js b/deps/npm/node_modules/read-installed/node_modules/util-extend/extend.js new file mode 100644 index 000000000..de9fcf471 --- /dev/null +++ b/deps/npm/node_modules/read-installed/node_modules/util-extend/extend.js @@ -0,0 +1,33 @@ +// Copyright Joyent, Inc. and other Node 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. + +module.exports = extend; +function extend(origin, add) { + // Don't do anything if add isn't an object + if (!add || typeof add !== 'object') return origin; + + var keys = Object.keys(add); + var i = keys.length; + while (i--) { + origin[keys[i]] = add[keys[i]]; + } + return origin; +} diff --git a/deps/npm/node_modules/read-installed/node_modules/util-extend/package.json b/deps/npm/node_modules/read-installed/node_modules/util-extend/package.json new file mode 100644 index 000000000..f45c5c94f --- /dev/null +++ b/deps/npm/node_modules/read-installed/node_modules/util-extend/package.json @@ -0,0 +1,23 @@ +{ + "name": "util-extend", + "version": "1.0.1", + "description": "Node's internal object extension function", + "main": "extend.js", + "scripts": { + "test": "node test.js" + }, + "repository": { + "type": "git", + "url": "git://github.com/isaacs/util-extend" + }, + "author": "", + "license": "MIT", + "readmeFilename": "README.md", + "readme": "# util-extend\n\nThe Node object extending function that Node uses for Node!\n\n## Usage\n\n```js\nvar extend = require('util-extend');\nfunction functionThatTakesOptions(options) {\n var options = extend(defaults, options);\n // now any unset options are set to the defaults.\n}\n```\n", + "bugs": { + "url": "https://github.com/isaacs/util-extend/issues" + }, + "homepage": "https://github.com/isaacs/util-extend", + "_id": "util-extend@1.0.1", + "_from": "util-extend@^1.0.1" +} diff --git a/deps/npm/node_modules/read-installed/node_modules/util-extend/test.js b/deps/npm/node_modules/read-installed/node_modules/util-extend/test.js new file mode 100644 index 000000000..fbee2b1e1 --- /dev/null +++ b/deps/npm/node_modules/read-installed/node_modules/util-extend/test.js @@ -0,0 +1,10 @@ +var assert = require('assert'); +var extend = require('./'); +assert.deepEqual(extend({a:1}), {a:1}); +assert.deepEqual(extend({a:1}, []), {a:1}); +assert.deepEqual(extend({a:1}, null), {a:1}); +assert.deepEqual(extend({a:1}, true), {a:1}); +assert.deepEqual(extend({a:1}, false), {a:1}); +assert.deepEqual(extend({a:1}, {b:2}), {a:1, b:2}); +assert.deepEqual(extend({a:1, b:2}, {b:3}), {a:1, b:3}); +console.log('ok'); diff --git a/deps/npm/node_modules/read-installed/package.json b/deps/npm/node_modules/read-installed/package.json index 16836d266..7887f71a9 100644 --- a/deps/npm/node_modules/read-installed/package.json +++ b/deps/npm/node_modules/read-installed/package.json @@ -1,19 +1,20 @@ { "name": "read-installed", "description": "Read all the installed packages in a folder, and return a tree structure with all the data.", - "version": "1.0.0", + "version": "2.0.1", "repository": { "type": "git", "url": "git://github.com/isaacs/read-installed" }, "main": "read-installed.js", "scripts": { - "test": "tap ./test/" + "test": "tap ./test/*.js" }, "dependencies": { + "read-package-json": "1", "semver": "2", "slide": "~1.1.3", - "read-package-json": "1", + "util-extend": "^1.0.1", "graceful-fs": "~2" }, "optionalDependencies": { @@ -28,12 +29,12 @@ "devDependencies": { "tap": "~0.4.8" }, - "readme": "# read-installed\n\nRead all the installed packages in a folder, and return a tree\nstructure with all the data.\n\nnpm uses this.\n\n## 1.0.0\n\nBreaking changes in `1.0.0`:\n\nThe second argument is now an `Object` that contains the following keys:\n\n * `depth` optional, defaults to Infinity\n * `log` optional log Function\n * `dev` optional, dev=true to mark devDeps as extraneous\n\n## Usage\n\n```javascript\nvar readInstalled = require(\"read-installed\")\nreadInstalled(folder, { depth, log, dev }, function (er, data) {\n ...\n})\n```\n", + "readme": "# read-installed\n\nRead all the installed packages in a folder, and return a tree\nstructure with all the data.\n\nnpm uses this.\n\n## 2.0.0\n\nBreaking changes in `2.0.0`:\n\nThe second argument is now an `Object` that contains the following keys:\n\n * `depth` optional, defaults to Infinity\n * `log` optional log Function\n * `dev` optional, default false, set to true to include devDependencies\n\n## Usage\n\n```javascript\nvar readInstalled = require(\"read-installed\")\n// optional options\nvar options = { dev: false, log: fn, depth: 2 }\nreadInstalled(folder, options, function (er, data) {\n ...\n})\n```\n", "readmeFilename": "README.md", "bugs": { "url": "https://github.com/isaacs/read-installed/issues" }, "homepage": "https://github.com/isaacs/read-installed", - "_id": "read-installed@1.0.0", + "_id": "read-installed@2.0.1", "_from": "read-installed@latest" } diff --git a/deps/npm/node_modules/read-installed/read-installed.js b/deps/npm/node_modules/read-installed/read-installed.js index 9ca482dab..f9104934d 100644 --- a/deps/npm/node_modules/read-installed/read-installed.js +++ b/deps/npm/node_modules/read-installed/read-installed.js @@ -98,6 +98,8 @@ var asyncMap = require("slide").asyncMap var semver = require("semver") var readJson = require("read-package-json") var url = require("url") +var util = require("util") +var extend = require("util-extend") module.exports = readInstalled @@ -105,20 +107,32 @@ function readInstalled (folder, opts, cb) { if (typeof opts === 'function') { cb = opts opts = {} + } else { + opts = extend({}, opts) } - var depth = Infinity || opts.depth, log = function () {} || opts.log, dev = false || opts.dev - readInstalled_(folder, null, null, null, 0, depth, dev, function (er, obj) { + if (typeof opts.depth !== 'number') + opts.depth = Infinity + + opts.depth = Math.max(0, opts.depth) + + if (typeof opts.log !== 'function') + opts.log = function () {} + + opts.dev = !!opts.dev + + readInstalled_(folder, null, null, null, 0, opts, function (er, obj) { if (er) return cb(er) // now obj has all the installed things, where they're installed // figure out the inheritance links, now that the object is built. - resolveInheritance(obj, log) + resolveInheritance(obj, opts) + markExtraneous(obj) cb(null, obj) }) } var rpSeen = {} -function readInstalled_ (folder, parent, name, reqver, depth, maxDepth, dev, cb) { +function readInstalled_ (folder, parent, name, reqver, depth, opts, cb) { var installed , obj , real @@ -181,29 +195,36 @@ function readInstalled_ (folder, parent, name, reqver, depth, maxDepth, dev, cb) obj.invalid = true } - if (parent - && !(name in parent.dependencies) - && (dev || !(name in (parent.devDependencies || {})))) { - obj.extraneous = true + if (parent) { + var deps = parent.dependencies || {} + var inDeps = name in deps + var devDeps = parent.devDependencies || {} + var inDev = opts.dev && (name in devDeps) + if (!inDeps && !inDev) { + obj.extraneous = true + } } + obj.path = obj.path || folder obj.realPath = real obj.link = link if (parent && !obj.link) obj.parent = parent rpSeen[real] = obj obj.depth = depth - //if (depth >= maxDepth) return cb(null, obj) + //if (depth >= opts.depth) return cb(null, obj) asyncMap(installed, function (pkg, cb) { var rv = obj.dependencies[pkg] - if (!rv && obj.devDependencies && !dev) rv = obj.devDependencies[pkg] - if (depth >= maxDepth) { + if (!rv && obj.devDependencies && opts.dev) + rv = obj.devDependencies[pkg] + + if (depth >= opts.depth) { // just try to get the version number var pkgfolder = path.resolve(folder, "node_modules", pkg) , jsonFile = path.resolve(pkgfolder, "package.json") return readJson(jsonFile, function (er, depData) { // already out of our depth, ignore errors if (er || !depData || !depData.version) return cb(null, obj) - if (depth === maxDepth) { + if (depth === opts.depth) { // edge case, ignore dependencies depData.dependencies = {} depData.peerDependencies = {} @@ -216,8 +237,7 @@ function readInstalled_ (folder, parent, name, reqver, depth, maxDepth, dev, cb) } readInstalled_( path.resolve(folder, "node_modules/"+pkg) - , obj, pkg, obj.dependencies[pkg], depth + 1, maxDepth - , dev + , obj, pkg, obj.dependencies[pkg], depth + 1, opts , cb ) }, function (er, installedData) { @@ -242,7 +262,7 @@ function readInstalled_ (folder, parent, name, reqver, depth, maxDepth, dev, cb) // starting from a root object, call findUnmet on each layer of children var riSeen = [] -function resolveInheritance (obj, log) { +function resolveInheritance (obj, opts) { if (typeof obj !== "object") return if (riSeen.indexOf(obj) !== -1) return riSeen.push(obj) @@ -250,18 +270,18 @@ function resolveInheritance (obj, log) { obj.dependencies = {} } Object.keys(obj.dependencies).forEach(function (dep) { - findUnmet(obj.dependencies[dep], log) + findUnmet(obj.dependencies[dep], opts) }) Object.keys(obj.dependencies).forEach(function (dep) { - resolveInheritance(obj.dependencies[dep], log) + resolveInheritance(obj.dependencies[dep], opts) }) - findUnmet(obj, log) + findUnmet(obj, opts) } // find unmet deps by walking up the tree object. // No I/O var fuSeen = [] -function findUnmet (obj, log) { +function findUnmet (obj, opts) { if (fuSeen.indexOf(obj) !== -1) return fuSeen.push(obj) //console.error("find unmet", obj.name, obj.parent && obj.parent.name) @@ -288,13 +308,11 @@ function findUnmet (obj, log) { && semver.validRange(deps[d], true) && !semver.satisfies(found.version, deps[d], true)) { // the bad thing will happen - log("unmet dependency", obj.path + " requires "+d+"@'"+deps[d] + opts.log("unmet dependency", obj.path + " requires "+d+"@'"+deps[d] +"' but will load\n" +found.path+",\nwhich is version "+found.version ) found.invalid = true - } else { - found.extraneous = false } deps[d] = found } @@ -318,8 +336,6 @@ function findUnmet (obj, log) { if (!dependency) return - dependency.extraneous = false - if (!semver.satisfies(dependency.version, peerDeps[d], true)) { dependency.peerInvalid = true } @@ -328,6 +344,28 @@ function findUnmet (obj, log) { return obj } +function recursivelyMarkExtraneous (obj, extraneous) { + // stop recursion if we're not changing anything + if (obj.extraneous === extraneous) return + + obj.extraneous = extraneous + var deps = obj.dependencies = obj.dependencies || {} + Object.keys(deps).forEach(function(d){ + recursivelyMarkExtraneous(deps[d], extraneous) + }); +} + +function markExtraneous (obj) { + // start from the root object and mark as non-extraneous all modules that haven't been previously flagged as + // extraneous then propagate to all their dependencies + var deps = obj.dependencies = obj.dependencies || {} + Object.keys(deps).forEach(function(d){ + if (!deps[d].extraneous){ + recursivelyMarkExtraneous(deps[d], false); + } + }); +} + function copy (obj) { if (!obj || typeof obj !== 'object') return obj if (Array.isArray(obj)) return obj.map(copy) diff --git a/deps/npm/node_modules/read-installed/test/basic.js b/deps/npm/node_modules/read-installed/test/basic.js index a6c5ff546..4d83cd0ca 100644 --- a/deps/npm/node_modules/read-installed/test/basic.js +++ b/deps/npm/node_modules/read-installed/test/basic.js @@ -1,5 +1,5 @@ var readInstalled = require("../read-installed.js") -var json = require("../package.json") +var json = require("./fixtures/package.json") var known = [].concat(Object.keys(json.dependencies) , Object.keys(json.optionalDependencies) , Object.keys(json.devDependencies)).sort() @@ -8,6 +8,7 @@ var path = require("path") test("make sure that it works", function (t) { readInstalled(path.join(__dirname, "../"), { + dev: true, log: console.error }, function (er, map) { t.notOk(er, "er should be bull") @@ -21,6 +22,7 @@ test("make sure that it works", function (t) { t.end() }) }) + var seen = [] function cleanup (map) { if (seen.indexOf(map) !== -1) return diff --git a/deps/npm/node_modules/read-installed/test/depth-0.js b/deps/npm/node_modules/read-installed/test/depth-0.js new file mode 100644 index 000000000..16dc6c525 --- /dev/null +++ b/deps/npm/node_modules/read-installed/test/depth-0.js @@ -0,0 +1,25 @@ +var readInstalled = require("../read-installed.js") +var test = require("tap").test +var json = require("../package.json") +var path = require("path") +var known = [].concat(Object.keys(json.dependencies) + , Object.keys(json.optionalDependencies) + , Object.keys(json.devDependencies)).sort() + +test("make sure that it works with depth=0", function (t) { + readInstalled(path.join(__dirname, "../"), { + depth: 0 + }, function (er, map) { + t.notOk(er, "er should be bull") + t.ok(map, "map should be data") + if (er) return console.error(er.stack || er.message) + // Exclude self from dependencies when depth = 0 + delete map.dependencies[json.name] + var subdeps = Object.keys(map.dependencies).reduce(function(acc, dep) { + acc += Object.keys(map.dependencies[dep].dependencies).length; + return acc; + }, 0); + t.equal(subdeps, 0, "there should be no sub dependencies") + t.end() + }) +}) diff --git a/deps/npm/node_modules/read-installed/test/depth-1.js b/deps/npm/node_modules/read-installed/test/depth-1.js new file mode 100644 index 000000000..977c9276f --- /dev/null +++ b/deps/npm/node_modules/read-installed/test/depth-1.js @@ -0,0 +1,23 @@ +var readInstalled = require("../read-installed.js") +var test = require("tap").test +var json = require("../package.json") +var path = require("path") +var known = [].concat(Object.keys(json.dependencies) + , Object.keys(json.optionalDependencies) + , Object.keys(json.devDependencies)).sort() + +test("make sure that it works with depth=1", function (t) { + readInstalled(path.join(__dirname, "../"), { + depth: 1 + }, function (er, map) { + t.notOk(er, "er should be bull") + t.ok(map, "map should be data") + if (er) return console.error(er.stack || er.message) + var subdeps = Object.keys(map.dependencies).reduce(function(acc, dep) { + acc += Object.keys(map.dependencies[dep].dependencies).length; + return acc; + }, 0); + t.notEqual(subdeps, 0, "there should some sub dependencies") + t.end() + }) +}) diff --git a/deps/npm/node_modules/read-installed/test/dev.js b/deps/npm/node_modules/read-installed/test/dev.js index 104761745..f6f4857bb 100644 --- a/deps/npm/node_modules/read-installed/test/dev.js +++ b/deps/npm/node_modules/read-installed/test/dev.js @@ -1,6 +1,6 @@ var readInstalled = require("../read-installed.js") var test = require("tap").test -var json = require("../package.json") +var json = require("./fixtures/package.json") var path = require("path") var known = [].concat(Object.keys(json.dependencies) , Object.keys(json.optionalDependencies) @@ -8,8 +8,9 @@ var known = [].concat(Object.keys(json.dependencies) test("make sure that it works without dev deps", function (t) { readInstalled(path.join(__dirname, "../"), { - log: console.error - , dev: true }, function (er, map) { + log: console.error, + dev: false + }, function (er, map) { t.notOk(er, "er should be bull") t.ok(map, "map should be data") if (er) return console.error(er.stack || er.message) diff --git a/deps/npm/node_modules/read-installed/test/extraneous.js b/deps/npm/node_modules/read-installed/test/extraneous.js new file mode 100644 index 000000000..2cc0d04e7 --- /dev/null +++ b/deps/npm/node_modules/read-installed/test/extraneous.js @@ -0,0 +1,17 @@ +var readInstalled = require('../read-installed.js') +var test = require('tap').test +var path = require('path'); + +test('extraneous detected', function(t) { + // This test verifies read-installed#16 + readInstalled( + path.join(__dirname, 'fixtures/extraneous-detected'), + { log: console.error }, + function(err, map) { + t.ok(map.dependencies.foo.extraneous, 'foo is extraneous, it\'s not required by any module') + t.ok(map.dependencies.bar.extraneous, 'bar is extraneous, it\'s not required by any module') + t.notOk(map.dependencies.asdf.extraneous, 'asdf is not extraneous, it\'s required by ghjk') + t.notOk(map.dependencies.ghjk.extraneous, 'ghjk is not extraneous, it\'s required by our root module') + t.end(); + }) +}) diff --git a/deps/npm/node_modules/read-installed/test/fixtures/extraneous-detected/package.json b/deps/npm/node_modules/read-installed/test/fixtures/extraneous-detected/package.json new file mode 100644 index 000000000..f61531551 --- /dev/null +++ b/deps/npm/node_modules/read-installed/test/fixtures/extraneous-detected/package.json @@ -0,0 +1,7 @@ +{ + "name": "extraneous-detected", + "version": "0.0.0", + "dependencies": { + "ghjk": "0.0.0" + } +} diff --git a/deps/npm/node_modules/read-installed/test/fixtures/package.json b/deps/npm/node_modules/read-installed/test/fixtures/package.json new file mode 100644 index 000000000..8f4f11916 --- /dev/null +++ b/deps/npm/node_modules/read-installed/test/fixtures/package.json @@ -0,0 +1,27 @@ +{ + "name": "read-installed", + "description": "Read all the installed packages in a folder, and return a tree structure with all the data.", + "version": "1.0.0", + "repository": { + "type": "git", + "url": "git://github.com/isaacs/read-installed" + }, + "main": "read-installed.js", + "scripts": { + "test": "tap ./test/" + }, + "dependencies": { + "semver": "2", + "slide": "~1.1.3", + "read-package-json": "1", + "util-extend":"1" + }, + "optionalDependencies": { + "graceful-fs": "~2" + }, + "author": "Isaac Z. Schlueter <i@izs.me> (http://blog.izs.me/)", + "license": "ISC", + "devDependencies": { + "tap": "~0.4.8" + } +} diff --git a/deps/npm/node_modules/read-installed/test/fixtures/peer-at-latest/node_modules/strong-task-emitter/package.json b/deps/npm/node_modules/read-installed/test/fixtures/peer-at-latest/node_modules/strong-task-emitter/package.json deleted file mode 100644 index 8824f5387..000000000 --- a/deps/npm/node_modules/read-installed/test/fixtures/peer-at-latest/node_modules/strong-task-emitter/package.json +++ /dev/null @@ -1,10 +0,0 @@ -{ - "name": "strong-task-emitter", - "version": "0.0.4", - "dependencies": { - "debug": "latest" - }, - "_id": "strong-task-emitter@0.0.4", - "_from": "strong-task-emitter@0.0.4", - "_resolved": "https://registry.npmjs.org/strong-task-emitter/-/strong-task-emitter-0.0.4.tgz" -} diff --git a/deps/npm/node_modules/read-installed/test/noargs.js b/deps/npm/node_modules/read-installed/test/noargs.js index 0de5ba430..a84a8f4cf 100644 --- a/deps/npm/node_modules/read-installed/test/noargs.js +++ b/deps/npm/node_modules/read-installed/test/noargs.js @@ -1,6 +1,6 @@ var readInstalled = require("../read-installed.js") var test = require("tap").test -var json = require("../package.json") +var json = require("./fixtures/package.json") var path = require("path") var known = [].concat(Object.keys(json.dependencies) , Object.keys(json.optionalDependencies) @@ -14,7 +14,7 @@ test("make sure that it works without dev deps", function (t) { var deps = Object.keys(map.dependencies).sort() t.equal(deps.length, known.length, "array lengths are equal") t.deepEqual(deps, known, "arrays should be equal") - t.notOk(map.dependencies.tap.extraneous, 'extraneous is set on devDep') + t.ok(map.dependencies.tap.extraneous, 'extraneous is set on devDep') t.end() }) }) diff --git a/deps/npm/node_modules/read-package-json/node_modules/normalize-package-data/lib/fixer.js b/deps/npm/node_modules/read-package-json/node_modules/normalize-package-data/lib/fixer.js index 9d832ee17..3414c0932 100644 --- a/deps/npm/node_modules/read-package-json/node_modules/normalize-package-data/lib/fixer.js +++ b/deps/npm/node_modules/read-package-json/node_modules/normalize-package-data/lib/fixer.js @@ -110,7 +110,7 @@ var fixer = module.exports = { } else if (data[bd]) { data[bd] = data[bd].filter(function(bd) { if (!bd || typeof bd !== 'string') { - this.warn(format(nonStringBundleDependency, bd)) + this.warn(format(warningMessages.nonStringBundleDependency, bd)) return false } else { return true @@ -135,7 +135,7 @@ var fixer = module.exports = { Object.keys(data[deps]).forEach(function (d) { var r = data[deps][d] if (typeof r !== 'string') { - this.warn(format(nonStringDependency, d, JSON.stringify(r))) + this.warn(format(warningMessages.nonStringDependency, d, JSON.stringify(r))) delete data[deps][d] } // "/" is not allowed as packagename for publishing, but for git-urls diff --git a/deps/npm/node_modules/read-package-json/node_modules/normalize-package-data/package.json b/deps/npm/node_modules/read-package-json/node_modules/normalize-package-data/package.json index 05037bf92..cee907988 100644 --- a/deps/npm/node_modules/read-package-json/node_modules/normalize-package-data/package.json +++ b/deps/npm/node_modules/read-package-json/node_modules/normalize-package-data/package.json @@ -1,6 +1,6 @@ { "name": "normalize-package-data", - "version": "0.2.9", + "version": "0.2.12", "author": { "name": "Meryn Stol", "email": "merynstol@gmail.com" @@ -44,10 +44,6 @@ "url": "https://github.com/meryn/normalize-package-data/issues" }, "homepage": "https://github.com/meryn/normalize-package-data", - "_id": "normalize-package-data@0.2.9", - "dist": { - "shasum": "73fff1f896ce6f95bd089c57037a96389ad5789e" - }, - "_from": "normalize-package-data@~0.2.9", - "_resolved": "https://registry.npmjs.org/normalize-package-data/-/normalize-package-data-0.2.9.tgz" + "_id": "normalize-package-data@0.2.12", + "_from": "normalize-package-data@~0.2.9" } diff --git a/deps/npm/node_modules/read-package-json/node_modules/normalize-package-data/test/dependencies.js b/deps/npm/node_modules/read-package-json/node_modules/normalize-package-data/test/dependencies.js new file mode 100644 index 000000000..dda24dc4f --- /dev/null +++ b/deps/npm/node_modules/read-package-json/node_modules/normalize-package-data/test/dependencies.js @@ -0,0 +1,43 @@ +var tap = require("tap") +var normalize = require("../lib/normalize") + +var warningMessages = require("../lib/warning_messages.json") +var safeFormat = require("../lib/safe_format") + +tap.test("warn if dependency contains anything else but a string", function(t) { + var a + var warnings = [] + function warn(w) { + warnings.push(w) + } + normalize(a={ + dependencies: { "a": 123}, + devDependencies: { "b": 456}, + optionalDependencies: { "c": 789} + }, warn) + + var wanted1 = safeFormat(warningMessages.nonStringDependency, "a", 123) + var wanted2 = safeFormat(warningMessages.nonStringDependency, "b", 456) + var wanted3 = safeFormat(warningMessages.nonStringDependency, "c", 789) + t.ok(~warnings.indexOf(wanted1), wanted1) + t.ok(~warnings.indexOf(wanted2), wanted2) + t.ok(~warnings.indexOf(wanted3), wanted3) + t.end() +}) + +tap.test("warn if bundleDependencies array contains anything else but strings", function(t) { + var a + var warnings = [] + function warn(w) { + warnings.push(w) + } + normalize(a={ + bundleDependencies: ["abc", 123, {foo:"bar"}] + }, warn) + + var wanted1 = safeFormat(warningMessages.nonStringBundleDependency, 123) + var wanted2 = safeFormat(warningMessages.nonStringBundleDependency, {foo:"bar"}) + t.ok(~warnings.indexOf(wanted1), wanted1) + t.ok(~warnings.indexOf(wanted2), wanted2) + t.end() +})
\ No newline at end of file diff --git a/deps/npm/node_modules/read-package-json/package.json b/deps/npm/node_modules/read-package-json/package.json index 794aedb8e..a2eb414c0 100644 --- a/deps/npm/node_modules/read-package-json/package.json +++ b/deps/npm/node_modules/read-package-json/package.json @@ -1,6 +1,6 @@ { "name": "read-package-json", - "version": "1.1.7", + "version": "1.1.8", "author": { "name": "Isaac Z. Schlueter", "email": "i@izs.me", @@ -34,6 +34,6 @@ "url": "https://github.com/isaacs/read-package-json/issues" }, "homepage": "https://github.com/isaacs/read-package-json", - "_id": "read-package-json@1.1.7", - "_from": "read-package-json@~1.1.6" + "_id": "read-package-json@1.1.8", + "_from": "read-package-json@latest" } diff --git a/deps/npm/node_modules/read-package-json/read-json.js b/deps/npm/node_modules/read-package-json/read-json.js index 5f69c0dcf..acb7d62d8 100644 --- a/deps/npm/node_modules/read-package-json/read-json.js +++ b/deps/npm/node_modules/read-package-json/read-json.js @@ -231,17 +231,31 @@ function readme (file, data, cb) { if (data.readme) return cb(null, data); var dir = path.dirname(file) var globOpts = { cwd: dir, nocase: true, mark: true } - glob("README?(.*)", globOpts, function (er, files) { + glob("{README,README.*}", globOpts, function (er, files) { if (er) return cb(er); // don't accept directories. files = files.filter(function (file) { return !file.match(/\/$/) }) if (!files.length) return cb(); - var rm = path.resolve(dir, files[0]) + var fn = preferMarkdownReadme(files) + var rm = path.resolve(dir, fn) readme_(file, data, rm, cb) }) } +function preferMarkdownReadme(files) { + var fallback = 0; + var re = /\.m?a?r?k?d?o?w?n?$/i + for (var i = 0; i < files.length; i++) { + if (files[i].match(re)) + return files[i] + else if (files[i].match(/README$/)) + fallback = i + } + // prefer README.md, followed by README; otherwise, return + // the first filename (which could be README) + return files[fallback]; +} function readme_(file, data, rm, cb) { var rmfn = path.basename(rm); fs.readFile(rm, "utf8", function (er, rm) { diff --git a/deps/npm/node_modules/read-package-json/test/fixtures/readmes/README b/deps/npm/node_modules/read-package-json/test/fixtures/readmes/README new file mode 100644 index 000000000..257cc5642 --- /dev/null +++ b/deps/npm/node_modules/read-package-json/test/fixtures/readmes/README @@ -0,0 +1 @@ +foo diff --git a/deps/npm/node_modules/read-package-json/test/fixtures/readmes/README.md b/deps/npm/node_modules/read-package-json/test/fixtures/readmes/README.md new file mode 100644 index 000000000..e444c2f0f --- /dev/null +++ b/deps/npm/node_modules/read-package-json/test/fixtures/readmes/README.md @@ -0,0 +1 @@ +*markdown* diff --git a/deps/npm/node_modules/read-package-json/test/fixtures/readmes/package.json b/deps/npm/node_modules/read-package-json/test/fixtures/readmes/package.json new file mode 100644 index 000000000..b0c1a318a --- /dev/null +++ b/deps/npm/node_modules/read-package-json/test/fixtures/readmes/package.json @@ -0,0 +1 @@ +{"name":"readmes", "version":"99.999.999999999"} diff --git a/deps/npm/node_modules/read-package-json/test/fixtures/readmes/readmexxx.yz b/deps/npm/node_modules/read-package-json/test/fixtures/readmes/readmexxx.yz new file mode 100644 index 000000000..662da9128 --- /dev/null +++ b/deps/npm/node_modules/read-package-json/test/fixtures/readmes/readmexxx.yz @@ -0,0 +1 @@ +extra noise diff --git a/deps/npm/node_modules/read-package-json/test/readmes.js b/deps/npm/node_modules/read-package-json/test/readmes.js new file mode 100644 index 000000000..1c1cee1b3 --- /dev/null +++ b/deps/npm/node_modules/read-package-json/test/readmes.js @@ -0,0 +1,29 @@ +// vim: set softtabstop=16 shiftwidth=16: +var tap = require("tap") +var readJson = require("../") +var path = require("path") +var fs = require("fs") +var p = path.resolve(__dirname, "fixtures/readmes/package.json") + +var expect = {} +var expect = { + "name" : "readmes", + "version" : "99.999.999999999", + "readme" : "*markdown*\n", + "readmeFilename" : "README.md", + "description" : "*markdown*", + "_id" : "readmes@99.999.999999999" +} + +console.error("readme test") +tap.test("readme test", function (t) { + readJson(p, function (er, data) { + if (er) throw er; + test(t, data) + }) +}) + +function test(t, data) { + t.deepEqual(data, expect) + t.end() +} diff --git a/deps/npm/node_modules/sorted-object/LICENSE.txt b/deps/npm/node_modules/sorted-object/LICENSE.txt new file mode 100644 index 000000000..a92a60b82 --- /dev/null +++ b/deps/npm/node_modules/sorted-object/LICENSE.txt @@ -0,0 +1,19 @@ +Copyright © 2014 Domenic Denicola <domenic@domenicdenicola.com> + +This work is free. You can redistribute it and/or modify it under the +terms of the Do What The Fuck You Want To Public License, Version 2, +as published by Sam Hocevar. See below for more details. + + DO WHAT THE FUCK YOU WANT TO PUBLIC LICENSE + Version 2, December 2004 + + Copyright (C) 2004 Sam Hocevar <sam@hocevar.net> + + Everyone is permitted to copy and distribute verbatim or modified + copies of this license document, and changing it is allowed as long + as the name is changed. + + DO WHAT THE FUCK YOU WANT TO PUBLIC LICENSE + TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION + + 0. You just DO WHAT THE FUCK YOU WANT TO. diff --git a/deps/npm/node_modules/sorted-object/README.md b/deps/npm/node_modules/sorted-object/README.md new file mode 100644 index 000000000..d3f12a278 --- /dev/null +++ b/deps/npm/node_modules/sorted-object/README.md @@ -0,0 +1,20 @@ +# Get a Version of an Object with Sorted Keys + +Although objects in JavaScript are theoretically unsorted, in practice most engines use insertion order—at least, ignoring numeric keys. This manifests itself most prominently when dealing with an object's JSON serialization. + +So, for example, you might be trying to serialize some object to a JSON file. But every time you write it, it ends up being output in a different order, depending on how you created it in the first place! This makes for some ugly diffs. + +**sorted-object** gives you the answer. Just use this package to create a version of your object with its keys sorted before serializing, and you'll get a consistent order every time. + +```js +var sortedObject = require("sorted-object"); + +var objectToSerialize = generateStuffNondeterministically(); + +// Before: +fs.writeFileSync("dest.json", JSON.stringify(objectToSerialize)); + +// After: +var sortedVersion = sortedObject(objectToSerialize); +fs.writeFileSync("dest.json", JSON.stringify(sortedVersion)); +``` diff --git a/deps/npm/node_modules/sorted-object/lib/sorted-object.js b/deps/npm/node_modules/sorted-object/lib/sorted-object.js new file mode 100644 index 000000000..26ebd500a --- /dev/null +++ b/deps/npm/node_modules/sorted-object/lib/sorted-object.js @@ -0,0 +1,11 @@ +"use strict"; + +module.exports = function (input) { + var output = Object.create(null); + + Object.keys(input).sort().forEach(function (key) { + output[key] = input[key]; + }); + + return output; +}; diff --git a/deps/npm/node_modules/sorted-object/package.json b/deps/npm/node_modules/sorted-object/package.json new file mode 100644 index 000000000..5bd814207 --- /dev/null +++ b/deps/npm/node_modules/sorted-object/package.json @@ -0,0 +1,37 @@ +{ + "name": "sorted-object", + "description": "Returns a copy of an object with its keys sorted", + "keywords": [ + "sort", + "keys", + "object" + ], + "version": "1.0.0", + "author": { + "name": "Domenic Denicola", + "email": "domenic@domenicdenicola.com", + "url": "http://domenic.me/" + }, + "license": "WTFPL", + "repository": { + "type": "git", + "url": "git://github.com/domenic/sorted-object.git" + }, + "bugs": { + "url": "http://github.com/domenic/sorted-object/issues" + }, + "main": "lib/sorted-object.js", + "scripts": { + "test": "tape test/tests.js", + "lint": "jshint lib && jshint test" + }, + "devDependencies": { + "jshint": "~2.4.3", + "tape": "~2.4.2" + }, + "readme": "# Get a Version of an Object with Sorted Keys\n\nAlthough objects in JavaScript are theoretically unsorted, in practice most engines use insertion order—at least, ignoring numeric keys. This manifests itself most prominently when dealing with an object's JSON serialization.\n\nSo, for example, you might be trying to serialize some object to a JSON file. But every time you write it, it ends up being output in a different order, depending on how you created it in the first place! This makes for some ugly diffs.\n\n**sorted-object** gives you the answer. Just use this package to create a version of your object with its keys sorted before serializing, and you'll get a consistent order every time.\n\n```js\nvar sortedObject = require(\"sorted-object\");\n\nvar objectToSerialize = generateStuffNondeterministically();\n\n// Before:\nfs.writeFileSync(\"dest.json\", JSON.stringify(objectToSerialize));\n\n// After:\nvar sortedVersion = sortedObject(objectToSerialize);\nfs.writeFileSync(\"dest.json\", JSON.stringify(sortedVersion));\n```\n", + "readmeFilename": "README.md", + "homepage": "https://github.com/domenic/sorted-object", + "_id": "sorted-object@1.0.0", + "_from": "sorted-object@" +} diff --git a/deps/npm/node_modules/uid-number/LICENCE b/deps/npm/node_modules/uid-number/LICENCE deleted file mode 100644 index 74489e2e2..000000000 --- a/deps/npm/node_modules/uid-number/LICENCE +++ /dev/null @@ -1,25 +0,0 @@ -Copyright (c) Isaac Z. Schlueter -All rights reserved. - -The BSD License - -Redistribution and use in source and binary forms, with or without -modification, are permitted provided that the following conditions -are met: -1. Redistributions of source code must retain the above copyright - notice, this list of conditions and the following disclaimer. -2. Redistributions in binary form must reproduce the above copyright - notice, this list of conditions and the following disclaimer in the - documentation and/or other materials provided with the distribution. - -THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS -``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED -TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR -PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS -BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR -CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF -SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS -INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN -CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) -ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE -POSSIBILITY OF SUCH DAMAGE. diff --git a/deps/npm/node_modules/uid-number/LICENSE b/deps/npm/node_modules/uid-number/LICENSE new file mode 100644 index 000000000..05eeeb88c --- /dev/null +++ b/deps/npm/node_modules/uid-number/LICENSE @@ -0,0 +1,15 @@ +The ISC License + +Copyright (c) Isaac Z. Schlueter + +Permission to use, copy, modify, and/or distribute this software for any +purpose with or without fee is hereby granted, provided that the above +copyright notice and this permission notice appear in all copies. + +THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES +WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF +MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR +ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES +WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN +ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR +IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. diff --git a/deps/npm/node_modules/uid-number/package.json b/deps/npm/node_modules/uid-number/package.json index babe6f43e..0b10753b1 100644 --- a/deps/npm/node_modules/uid-number/package.json +++ b/deps/npm/node_modules/uid-number/package.json @@ -6,7 +6,7 @@ }, "name": "uid-number", "description": "Convert a username/group name to a uid/gid number", - "version": "0.0.3", + "version": "0.0.5", "repository": { "type": "git", "url": "git://github.com/isaacs/uid-number.git" @@ -18,18 +18,13 @@ "engines": { "node": "*" }, - "license": "BSD", - "_npmUser": { - "name": "isaacs", - "email": "i@izs.me" + "license": "ISC", + "readme": "Use this module to convert a username/groupname to a uid/gid number.\n\nUsage:\n\n```\nnpm install uid-number\n```\n\nThen, in your node program:\n\n```javascript\nvar uidNumber = require(\"uid-number\")\nuidNumber(\"isaacs\", function (er, uid, gid) {\n // gid is null because we didn't ask for a group name\n // uid === 24561 because that's my number.\n})\n```\n", + "readmeFilename": "README.md", + "bugs": { + "url": "https://github.com/isaacs/uid-number/issues" }, - "_id": "uid-number@0.0.3", - "_engineSupported": true, - "_npmVersion": "1.1.23", - "_nodeVersion": "v0.7.10-pre", - "_defaultsLoaded": true, - "dist": { - "shasum": "cefb0fa138d8d8098da71a40a0d04a8327d6e1cc" - }, - "_from": "../uid-number" + "homepage": "https://github.com/isaacs/uid-number", + "_id": "uid-number@0.0.5", + "_from": "uid-number@latest" } diff --git a/deps/npm/node_modules/uid-number/uid-number.js b/deps/npm/node_modules/uid-number/uid-number.js index 93f372bb9..2ae421ede 100644 --- a/deps/npm/node_modules/uid-number/uid-number.js +++ b/deps/npm/node_modules/uid-number/uid-number.js @@ -18,7 +18,7 @@ function uidNumber (uid, gid, cb) { if (typeof cb !== "function") cb = uid, uid = null if (gid == null) gid = process.getgid() if (uid == null) uid = process.getuid() - if (!isNaN(gid)) gid = uidCache[gid] = +gid + if (!isNaN(gid)) gid = gidCache[gid] = +gid if (!isNaN(uid)) uid = uidCache[uid] = +uid if (uidCache.hasOwnProperty(uid)) uid = uidCache[uid] @@ -49,6 +49,6 @@ function uidNumber (uid, gid, cb) { if (isNaN(out.uid) || isNaN(out.gid)) return cb(new Error( "Could not get uid/gid: "+JSON.stringify(out))) - cb(null, uidCache[uid] = +out.uid, uidCache[gid] = +out.gid) + cb(null, uidCache[uid] = +out.uid, gidCache[gid] = +out.gid) }) } |
